1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-25 22:43:50 +01:00

Merge pull request #3780 from haukepetersen/add_test_periph_timer

tests: added test for periph_timer plus adaption
This commit is contained in:
Hauke Petersen 2015-09-18 18:03:32 +02:00
commit fc3c0f373c
15 changed files with 208 additions and 59 deletions

View File

@ -39,7 +39,8 @@ extern "C" {
* @brief Timer configuration
* @{
*/
#define TIMER_DEV (TIMER_A0)
#define TIMER_NUMOF (1U)
#define TIMER_BASE (TIMER_A0)
#define TIMER_CHAN (5)
#define TIMER_ISR_CC0 (TIMER0_A0_VECTOR)
#define TIMER_ISR_CCX (TIMER0_A1_VECTOR)

View File

@ -56,7 +56,7 @@ extern "C"
#define TIMER_0_EN 1
#define TIMER_1_EN 0
#define TIMER_IRQ_PRIO 1
#define TIMER_DEV PIT
#define TIMER_BASE PIT
#define TIMER_MAX_VALUE (0xffffffff)
#define TIMER_CLOCK CLOCK_CORECLOCK
#define TIMER_CLKEN() (SIM->SCGC6 |= (SIM_SCGC6_PIT_MASK))

View File

@ -39,7 +39,8 @@ extern "C" {
* @brief Timer configuration
* @{
*/
#define TIMER_DEV (TIMER_A)
#define TIMER_NUMOF (1U)
#define TIMER_BASE (TIMER_A)
#define TIMER_CHAN (3)
#define TIMER_ISR_CC0 (TIMERA0_VECTOR)
#define TIMER_ISR_CCX (TIMERA1_VECTOR)

View File

@ -41,7 +41,8 @@ extern "C" {
* @brief Timer configuration
* @{
*/
#define TIMER_DEV (TIMER_A)
#define TIMER_NUMOF (1U)
#define TIMER_BASE (TIMER_A)
#define TIMER_CHAN (3)
#define TIMER_ISR_CC0 (TIMERA0_VECTOR)
#define TIMER_ISR_CCX (TIMERA1_VECTOR)

View File

@ -64,7 +64,7 @@ extern "C"
#define TIMER_0_EN 1
#define TIMER_1_EN 0
#define TIMER_IRQ_PRIO 1
#define TIMER_DEV PIT
#define TIMER_BASE PIT
#define TIMER_MAX_VALUE (0xffffffff)
#define TIMER_CLOCK SystemBusClock
#define TIMER_CLKEN() (BITBAND_REG32(SIM->SCGC6, SIM_SCGC6_PIT_SHIFT) = 1)

View File

@ -58,7 +58,7 @@ extern "C"
#define TIMER_0_EN 1
#define TIMER_1_EN 0
#define TIMER_IRQ_PRIO 1
#define TIMER_DEV PIT
#define TIMER_BASE PIT
#define TIMER_MAX_VALUE (0xffffffff)
#define TIMER_CLOCK CLOCK_CORECLOCK
#define TIMER_CLKEN() (SIM->SCGC6 |= (SIM_SCGC6_PIT_MASK))

View File

@ -39,7 +39,8 @@ extern "C" {
* @brief Timer configuration
* @{
*/
#define TIMER_DEV (TIMER_A)
#define TIMER_NUMOF (1U)
#define TIMER_BASE (TIMER_A)
#define TIMER_CHAN (3)
#define TIMER_ISR_CC0 (TIMERA0_VECTOR)
#define TIMER_ISR_CCX (TIMERA1_VECTOR)

View File

@ -39,7 +39,8 @@ extern "C" {
* @brief Timer configuration
* @{
*/
#define TIMER_DEV (TIMER_A)
#define TIMER_NUMOF (1U)
#define TIMER_BASE (TIMER_A)
#define TIMER_CHAN (3)
#define TIMER_ISR_CC0 (TIMERA0_VECTOR)
#define TIMER_ISR_CCX (TIMERA1_VECTOR)

View File

@ -39,7 +39,8 @@ extern "C" {
* @brief Timer configuration
* @{
*/
#define TIMER_DEV (TIMER_A)
#define TIMER_NUMOF (1U)
#define TIMER_BASE (TIMER_A)
#define TIMER_CHAN (3)
#define TIMER_ISR_CC0 (TIMERA0_VECTOR)
#define TIMER_ISR_CCX (TIMERA1_VECTOR)

View File

@ -37,7 +37,7 @@ static void (*isr_cb)(int chan);
int timer_init(tim_t dev, unsigned int us_per_tick, void (*callback)(int))
{
/* using fixed TIMER_DEV for now */
/* using fixed TIMER_BASE for now */
if (dev != 0) {
return -1;
}
@ -47,23 +47,23 @@ int timer_init(tim_t dev, unsigned int us_per_tick, void (*callback)(int))
}
/* reset the timer A configuration */
TIMER_DEV->CTL = CTL_CLR;
TIMER_BASE->CTL = CTL_CLR;
/* save callback */
isr_cb = callback;
/* configure timer to use the SMCLK with prescaler of 8 */
TIMER_DEV->CTL = (CTL_TASSEL_SMCLK | CTL_ID_DIV8);
TIMER_BASE->CTL = (CTL_TASSEL_SMCLK | CTL_ID_DIV8);
/* configure CC channels */
for (int i = 0; i < TIMER_CHAN; i++) {
TIMER_DEV->CCTL[i] = 0;
TIMER_BASE->CCTL[i] = 0;
}
/* start the timer in continuous mode */
TIMER_DEV->CTL |= CTL_MC_CONT;
TIMER_BASE->CTL |= CTL_MC_CONT;
return 0;
}
int timer_set(tim_t dev, int channel, unsigned int timeout)
{
uint16_t target = TIMER_DEV->R + (uint16_t)timeout;
uint16_t target = TIMER_BASE->R + (uint16_t)timeout;
return timer_set_absolute(dev, channel, (unsigned int)target);
}
@ -72,9 +72,9 @@ int timer_set_absolute(tim_t dev, int channel, unsigned int value)
if (dev != 0 || channel > TIMER_CHAN) {
return -1;
}
TIMER_DEV->CCR[channel] = value;
TIMER_DEV->CCTL[channel] &= ~(CCTL_CCIFG);
TIMER_DEV->CCTL[channel] |= (CCTL_CCIE);
TIMER_BASE->CCR[channel] = value;
TIMER_BASE->CCTL[channel] &= ~(CCTL_CCIFG);
TIMER_BASE->CCTL[channel] |= (CCTL_CCIE);
return 0;
}
@ -83,23 +83,23 @@ int timer_clear(tim_t dev, int channel)
if (dev != 0 || channel > TIMER_CHAN) {
return -1;
}
TIMER_DEV->CCTL[channel] &= ~(CCTL_CCIE);
TIMER_BASE->CCTL[channel] &= ~(CCTL_CCIE);
return 0;
}
unsigned int timer_read(tim_t dev)
{
return (unsigned int)TIMER_DEV->R;
return (unsigned int)TIMER_BASE->R;
}
void timer_start(tim_t dev)
{
TIMER_DEV->CTL |= CTL_MC_CONT;
TIMER_BASE->CTL |= CTL_MC_CONT;
}
void timer_stop(tim_t dev)
{
TIMER_DEV->CTL &= ~(CTL_MC_MASK);
TIMER_BASE->CTL &= ~(CTL_MC_MASK);
}
void timer_irq_enable(tim_t dev)
@ -121,14 +121,14 @@ void timer_irq_disable(tim_t dev)
void timer_reset(tim_t dev)
{
TIMER_DEV->R = 0;
TIMER_BASE->R = 0;
}
ISR(TIMER_ISR_CC0, isr_timer_a_cc0)
{
__enter_isr();
TIMER_DEV->CCTL[0] &= ~(CCTL_CCIE);
TIMER_BASE->CCTL[0] &= ~(CCTL_CCIE);
isr_cb(0);
__exit_isr();
@ -138,8 +138,8 @@ ISR(TIMER_ISR_CCX, isr_timer_a_ccx_isr)
{
__enter_isr();
int chan = (int)(TIMER_DEV->IV >> 1);
TIMER_DEV->CCTL[chan] &= ~(CCTL_CCIE);
int chan = (int)(TIMER_BASE->IV >> 1);
TIMER_BASE->CCTL[chan] &= ~(CCTL_CCIE);
isr_cb(chan);
__exit_isr();

View File

@ -288,7 +288,7 @@
* #define TIMER_0_EN 1
* #define TIMER_1_EN 0
* #define TIMER_IRQ_PRIO 1
* #define TIMER_DEV PIT
* #define TIMER_BASE PIT
* #define TIMER_MAX_VALUE (0xffffffff)
* #define TIMER_CLOCK CLOCK_CORECLOCK
* #define TIMER_CLKEN() (SIM->SCGC6 |= (SIM_SCGC6_PIT_MASK))

View File

@ -53,45 +53,45 @@ static timer_conf_t config[TIMER_NUMOF];
inline static void pit_timer_start(uint8_t ch)
{
TIMER_DEV->CHANNEL[ch].TCTRL |= (PIT_TCTRL_TEN_MASK);
TIMER_BASE->CHANNEL[ch].TCTRL |= (PIT_TCTRL_TEN_MASK);
}
inline static void pit_timer_stop(uint8_t ch)
{
TIMER_DEV->CHANNEL[ch].TCTRL &= ~(PIT_TCTRL_TEN_MASK);
TIMER_BASE->CHANNEL[ch].TCTRL &= ~(PIT_TCTRL_TEN_MASK);
}
/** use channel n-1 as prescaler */
inline static void timer_set_prescaler(uint8_t ch, unsigned int ticks_per_us)
{
TIMER_DEV->CHANNEL[ch].TCTRL = 0x0;
TIMER_DEV->CHANNEL[ch].LDVAL = (TIMER_CLOCK / 1e6) / ticks_per_us;
TIMER_DEV->CHANNEL[ch].TCTRL = (PIT_TCTRL_TEN_MASK);
TIMER_BASE->CHANNEL[ch].TCTRL = 0x0;
TIMER_BASE->CHANNEL[ch].LDVAL = (TIMER_CLOCK / 1e6) / ticks_per_us;
TIMER_BASE->CHANNEL[ch].TCTRL = (PIT_TCTRL_TEN_MASK);
}
inline static void timer_set_counter(uint8_t ch)
{
TIMER_DEV->CHANNEL[ch].TCTRL = 0x0;
TIMER_DEV->CHANNEL[ch].LDVAL = TIMER_MAX_VALUE;
TIMER_DEV->CHANNEL[ch].TCTRL = (PIT_TCTRL_TIE_MASK | PIT_TCTRL_CHN_MASK);
TIMER_BASE->CHANNEL[ch].TCTRL = 0x0;
TIMER_BASE->CHANNEL[ch].LDVAL = TIMER_MAX_VALUE;
TIMER_BASE->CHANNEL[ch].TCTRL = (PIT_TCTRL_TIE_MASK | PIT_TCTRL_CHN_MASK);
}
inline static uint32_t pit_timer_read(tim_t dev, uint8_t ch)
{
return cu_timer[dev].counter32b + (TIMER_DEV->CHANNEL[ch].LDVAL
- TIMER_DEV->CHANNEL[ch].CVAL);
return cu_timer[dev].counter32b + (TIMER_BASE->CHANNEL[ch].LDVAL
- TIMER_BASE->CHANNEL[ch].CVAL);
}
inline static void pit_timer_set_max(uint8_t ch)
{
pit_timer_stop(ch);
TIMER_DEV->CHANNEL[ch].LDVAL = TIMER_MAX_VALUE;
TIMER_BASE->CHANNEL[ch].LDVAL = TIMER_MAX_VALUE;
pit_timer_start(ch);
}
int timer_init(tim_t dev, unsigned int ticks_per_us, void (*callback)(int))
{
PIT_Type *timer = TIMER_DEV;
PIT_Type *timer = TIMER_BASE;
/* enable timer peripheral clock */
TIMER_CLKEN();
@ -152,7 +152,7 @@ int timer_set_absolute(tim_t dev, int channel, unsigned int value)
pit_timer_stop(TIMER_0_COUNTER_CH);
cu_timer[dev].counter32b = pit_timer_read(dev, TIMER_0_COUNTER_CH);
cu_timer[dev].diff = value - cu_timer[dev].counter32b;
TIMER_DEV->CHANNEL[TIMER_0_COUNTER_CH].LDVAL = cu_timer[dev].diff;
TIMER_BASE->CHANNEL[TIMER_0_COUNTER_CH].LDVAL = cu_timer[dev].diff;
pit_timer_start(TIMER_0_COUNTER_CH);
break;
#endif
@ -162,7 +162,7 @@ int timer_set_absolute(tim_t dev, int channel, unsigned int value)
pit_timer_stop(TIMER_1_COUNTER_CH);
cu_timer[dev].counter32b = pit_timer_read(dev, TIMER_1_COUNTER_CH);
cu_timer[dev].diff = value - cu_timer[dev].counter32b;
TIMER_DEV->CHANNEL[TIMER_1_COUNTER_CH].LDVAL = cu_timer[dev].diff;
TIMER_BASE->CHANNEL[TIMER_1_COUNTER_CH].LDVAL = cu_timer[dev].diff;
pit_timer_start(TIMER_1_COUNTER_CH);
break;
#endif
@ -338,9 +338,9 @@ void timer_reset(tim_t dev)
inline static void pit_timer_irq_handler(tim_t dev, uint8_t ch)
{
cu_timer[dev].counter32b += TIMER_DEV->CHANNEL[ch].LDVAL;
cu_timer[dev].counter32b += TIMER_BASE->CHANNEL[ch].LDVAL;
TIMER_DEV->CHANNEL[ch].TFLG = PIT_TFLG_TIF_MASK;
TIMER_BASE->CHANNEL[ch].TFLG = PIT_TFLG_TIF_MASK;
if (cu_timer[dev].diff) {
if (config[dev].cb != NULL) {

View File

@ -37,7 +37,7 @@ static void (*isr_cb)(int chan);
int timer_init(tim_t dev, unsigned int us_per_tick, void (*callback)(int))
{
/* using fixed TIMER_DEV for now */
/* using fixed TIMER_BASE for now */
if (dev != 0) {
return -1;
}
@ -47,23 +47,23 @@ int timer_init(tim_t dev, unsigned int us_per_tick, void (*callback)(int))
}
/* reset the timer A configuration */
TIMER_DEV->CTL = TIMER_CTL_CLR;
TIMER_BASE->CTL = TIMER_CTL_CLR;
/* save callback */
isr_cb = callback;
/* configure timer to use the SMCLK with prescaler of 8 */
TIMER_DEV->CTL = (TIMER_CTL_TASSEL_SMCLK | TIMER_CTL_ID_DIV8);
TIMER_BASE->CTL = (TIMER_CTL_TASSEL_SMCLK | TIMER_CTL_ID_DIV8);
/* configure CC channels */
for (int i = 0; i < TIMER_CHAN; i++) {
TIMER_DEV->CCTL[i] = 0;
TIMER_BASE->CCTL[i] = 0;
}
/* start the timer in continuous mode */
TIMER_DEV->CTL |= TIMER_CTL_MC_CONT;
TIMER_BASE->CTL |= TIMER_CTL_MC_CONT;
return 0;
}
int timer_set(tim_t dev, int channel, unsigned int timeout)
{
uint16_t target = TIMER_DEV->R + (uint16_t)timeout;
uint16_t target = TIMER_BASE->R + (uint16_t)timeout;
return timer_set_absolute(dev, channel, (unsigned int)target);
}
@ -72,9 +72,9 @@ int timer_set_absolute(tim_t dev, int channel, unsigned int value)
if (dev != 0 || channel > TIMER_CHAN) {
return -1;
}
TIMER_DEV->CCR[channel] = value;
TIMER_DEV->CCTL[channel] &= ~(TIMER_CCTL_CCIFG);
TIMER_DEV->CCTL[channel] |= (TIMER_CCTL_CCIE);
TIMER_BASE->CCR[channel] = value;
TIMER_BASE->CCTL[channel] &= ~(TIMER_CCTL_CCIFG);
TIMER_BASE->CCTL[channel] |= (TIMER_CCTL_CCIE);
return 0;
}
@ -83,23 +83,23 @@ int timer_clear(tim_t dev, int channel)
if (dev != 0 || channel > TIMER_CHAN) {
return -1;
}
TIMER_DEV->CCTL[channel] &= ~(TIMER_CCTL_CCIE);
TIMER_BASE->CCTL[channel] &= ~(TIMER_CCTL_CCIE);
return 0;
}
unsigned int timer_read(tim_t dev)
{
return (unsigned int)TIMER_DEV->R;
return (unsigned int)TIMER_BASE->R;
}
void timer_start(tim_t dev)
{
TIMER_DEV->CTL |= TIMER_CTL_MC_CONT;
TIMER_BASE->CTL |= TIMER_CTL_MC_CONT;
}
void timer_stop(tim_t dev)
{
TIMER_DEV->CTL &= ~(TIMER_CTL_MC_MASK);
TIMER_BASE->CTL &= ~(TIMER_CTL_MC_MASK);
}
void timer_irq_enable(tim_t dev)
@ -121,14 +121,14 @@ void timer_irq_disable(tim_t dev)
void timer_reset(tim_t dev)
{
TIMER_DEV->R = 0;
TIMER_BASE->R = 0;
}
ISR(TIMER_ISR_CC0, isr_timer_a_cc0)
{
__enter_isr();
TIMER_DEV->CCTL[0] &= ~(TIMER_CCTL_CCIE);
TIMER_BASE->CCTL[0] &= ~(TIMER_CCTL_CCIE);
isr_cb(0);
__exit_isr();
@ -139,7 +139,7 @@ ISR(TIMER_ISR_CCX, isr_timer_a_ccx)
__enter_isr();
int chan = (int)(TIMER_IVEC->TAIV >> 1);
TIMER_DEV->CCTL[chan] &= ~(TIMER_CCTL_CCIE);
TIMER_BASE->CCTL[chan] &= ~(TIMER_CCTL_CCIE);
isr_cb(chan);
__exit_isr();

View File

@ -0,0 +1,6 @@
export APPLICATION = periph_timer
include ../Makefile.tests_common
FEATURES_REQUIRED = periph_timer
include $(RIOTBASE)/Makefile.include

137
tests/periph_timer/main.c Normal file
View File

@ -0,0 +1,137 @@
/*
* Copyright (C) 2015 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup tests
* @{
*
* @file
* @brief Peripheral timer test application
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "periph/timer.h"
/**
* @brief Make sure, the maximum number of timers is defined
*/
#ifndef TIMER_NUMOF
#error "TIMER_NUMOF not defined!"
#endif
#define MAX_CHANNELS (10U)
#define TIM_SPEED (1U) /* try to run with 1MHz */
#define CHAN_OFFSET (5000U) /* fire every 5ms */
static volatile int fired;
static volatile uint32_t sw_count;
static volatile uint32_t timeouts[MAX_CHANNELS];
static void cb(int chan)
{
timeouts[chan] = sw_count;
fired++;
}
static int test_timer(unsigned num)
{
int set = 0;
/* reset state */
sw_count = 0;
fired = 0;
for (unsigned i = 0; i < MAX_CHANNELS; i++) {
timeouts[i] = 0;
}
/* initialize and halt timer */
if (timer_init(TIMER_DEV(num), TIM_SPEED, cb) < 0) {
printf("TIMER_%u: ERROR on initialization - skipping\n\n", num);
return 0;
}
else {
printf("TIMER_%u: initialization successful\n", num);
}
timer_stop(TIMER_DEV(num));
printf("TIMER_%u: stopped\n", num);
/* set each available channel */
for (unsigned i = 0; i < MAX_CHANNELS; i++) {
unsigned timeout = ((i + 1) * CHAN_OFFSET);
if (timer_set(TIMER_DEV(num), i, timeout) < 0) {
break;
}
else {
++set;
printf("TIMER_%u: set channel %u to %u\n", num, i, timeout);
}
}
if (set == 0) {
printf("TIMER_%u: ERROR setting any channel\n\n", num);
return 0;
}
/* start the timer */
printf("TIMER_%u: starting\n", num);
timer_start(TIMER_DEV(num));
/* wait for all channels to fire */
do {
++sw_count;
} while (fired != set);
/* collect results */
for (int i = 0; i < fired; i++) {
printf("TIMER_%u: channel %i fired at SW count %8u",
num, i, (unsigned)timeouts[i]);
if (i == 0) {
printf(" - init: %8u\n", (unsigned)timeouts[i]);
}
else {
printf(" - diff: %8u\n", (unsigned)(timeouts[i] - timeouts[i - 1]));
}
}
return 1;
}
int main(void)
{
int res = 0;
puts("\nTest for peripheral TIMERs\n");
puts("This test will test all configured peripheral timers of the\n"
"targeted platform. For each timer, it will set each channel with\n"
"an incrementing timeout. CH0 set to 5ms, CH1 to 10ms, CH2 to 15ms\n"
"and so on.\n"
"In the output you should see that every channel fired, after an\n"
"evenly distributed amount of time -> the shown diff values should\n"
"be pretty much equal (to some jitter...)\n"
"This test does however NOT show, if the timeouts were correct in\n"
"relation to the expected real-time ~ use e.g. tests/xtimer_msg for\n"
"this.\n\n");
printf("Available timers: %i\n", TIMER_NUMOF);
/* test all configured timers */
for (unsigned i = 0; i < TIMER_NUMOF; i++) {
printf("\nTesting TIMER_%u:\n", i);
res += test_timer(i);
}
/* draw conclusion */
if (res == TIMER_NUMOF) {
puts("\nTEST SUCCEEDED");
}
else {
puts("\nTEST FAILED");
}
return 0;
}