diff --git a/cpu/nrf51822/include/hwtimer_cpu.h b/cpu/nrf51822/include/hwtimer_cpu.h index 03b94a8698c2..75c085b58a0a 100644 --- a/cpu/nrf51822/include/hwtimer_cpu.h +++ b/cpu/nrf51822/include/hwtimer_cpu.h @@ -9,10 +9,10 @@ /** * @ingroup cpu_nrf51822 * @{ - * + * * @file * @brief CPU specific hwtimer configuration options - * + * * @author Hauke Petersen */ @@ -26,7 +26,7 @@ #define HWTIMER_MAXTIMERS 3 /**< the CPU implementation supports 3 HW timers */ #define HWTIMER_SPEED 1000000 /**< the HW timer runs with 1MHz */ -#define HWTIMER_MAXTICKS (0xFFFFFFFF) /**< 32-bit timer */ +#define HWTIMER_MAXTICKS (0xFFFFFF) /**< 24-bit timer -> see PAN note */ /** @} */ diff --git a/cpu/nrf51822/periph/timer.c b/cpu/nrf51822/periph/timer.c index 94716544c15f..e4d860e390f7 100644 --- a/cpu/nrf51822/periph/timer.c +++ b/cpu/nrf51822/periph/timer.c @@ -20,55 +20,79 @@ * @} */ -#include -#include - #include "cpu.h" #include "board.h" #include "sched.h" #include "thread.h" #include "periph_conf.h" #include "periph/timer.h" -#include "nrf51.h" -#include "nrf51_bitfields.h" +/** + * @name Flags to mark active channels + * @{ + */ +#define TIMER_CH0 0x01 +#define TIMER_CH1 0x02 +#define TIMER_CH2 0x04 +/** @} */ + +/** + * @brief struct for keeping track of a timer's state + */ typedef struct { void (*cb)(int); + uint8_t flags; } timer_conf_t; /** - * timer state memory + * @brief timer state memory */ static timer_conf_t timer_config[TIMER_NUMOF]; +/** + * @brief static timer mapping + */ +static NRF_TIMER_Type *const timer[] = { +#if TIMER_0_EN + TIMER_0_DEV, +#endif +#if TIMER_1_EN + TIMER_1_DEV, +#endif +#if TIMER_2_EN + TIMER_2_DEV +#endif +}; + int timer_init(tim_t dev, unsigned int ticks_per_us, void (*callback)(int)) { - NRF_TIMER_Type *timer; + if (dev >= TIMER_NUMOF) { + return -1; + } + + /* save callback */ + timer_config[dev].cb = callback; + /* power on timer */ + timer[dev]->POWER = 1; switch (dev) { #if TIMER_0_EN case TIMER_0: - timer = TIMER_0_DEV; - timer->POWER = 1; - timer->BITMODE = TIMER_0_BITMODE; + TIMER_0_DEV->BITMODE = TIMER_0_BITMODE; NVIC_SetPriority(TIMER_0_IRQ, TIMER_IRQ_PRIO); NVIC_EnableIRQ(TIMER_0_IRQ); break; #endif #if TIMER_1_EN case TIMER_1: - timer = TIMER_1_DEV; - timer->POWER = 1; - timer->BITMODE = TIEMR_1_BITMODE; + TIMER_1_DEV->BITMODE = TIEMR_1_BITMODE; NVIC_SetPriority(TIMER_1_IRQ, TIMER_IRQ_PRIO); NVIC_EnableIRQ(TIMER_1_IRQ); break; #endif #if TIMER_2_EN case TIMER_2: - timer = TIMER_2_DEV; - timer->POWER = 1; - timer->BITMODE = TIMER_2_BITMODE; + TIMER_2_DEV->BITMODE = TIMER_2_BITMODE; NVIC_SetPriority(TIMER_2_IRQ, TIMER_IRQ_PRIO); NVIC_EnableIRQ(TIMER_2_IRQ); break; @@ -77,43 +101,37 @@ int timer_init(tim_t dev, unsigned int ticks_per_us, void (*callback)(int)) return -1; } - /* save callback */ - timer_config[dev].cb = callback; - - timer->TASKS_STOP = 1; - - timer->MODE = TIMER_MODE_MODE_Timer; /* set the timer in Timer Mode. */ - timer->TASKS_CLEAR = 1; /* clear the task first to be usable for later. */ + timer[dev]->TASKS_STOP = 1; + timer[dev]->MODE = TIMER_MODE_MODE_Timer; /* set the timer in Timer Mode. */ + timer[dev]->TASKS_CLEAR = 1; /* clear the task first to be usable for later. */ switch (ticks_per_us) { case 1: - timer->PRESCALER = 4; + timer[dev]->PRESCALER = 4; break; case 2: - timer->PRESCALER = 5; + timer[dev]->PRESCALER = 5; break; case 4: - timer->PRESCALER = 6; + timer[dev]->PRESCALER = 6; break; case 8: - timer->PRESCALER = 7; + timer[dev]->PRESCALER = 7; break; case 16: - timer->PRESCALER = 8; + timer[dev]->PRESCALER = 8; break; default: return -1; } - /* clear all compare channels */ - timer->SHORTS = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos); - timer->SHORTS = (TIMER_SHORTS_COMPARE1_CLEAR_Enabled << TIMER_SHORTS_COMPARE1_CLEAR_Pos); - timer->SHORTS = (TIMER_SHORTS_COMPARE2_CLEAR_Enabled << TIMER_SHORTS_COMPARE2_CLEAR_Pos); - timer->SHORTS = (TIMER_SHORTS_COMPARE3_CLEAR_Enabled << TIMER_SHORTS_COMPARE3_CLEAR_Pos); + /* reset compare state */ + timer[dev]->EVENTS_COMPARE[0] = 0; + timer[dev]->EVENTS_COMPARE[1] = 0; + timer[dev]->EVENTS_COMPARE[2] = 0; /* start the timer */ - timer->TASKS_START = 1; - + timer[dev]->TASKS_START = 1; return 0; } @@ -125,41 +143,25 @@ int timer_set(tim_t dev, int channel, unsigned int timeout) int timer_set_absolute(tim_t dev, int channel, unsigned int value) { - volatile NRF_TIMER_Type * timer; - - /* get timer base register address */ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - timer = TIMER_0_DEV; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - timer = TIMER_1_DEV; - break; -#endif -#if TIMER_2_EN - case TIMER_2: - timer = TIMER_2_DEV; - break; -#endif - case TIMER_UNDEFINED: + if (dev >= TIMER_NUMOF) { return -1; } switch (channel) { case 0: - timer->CC[0] = value; - timer->INTENSET |= TIMER_INTENSET_COMPARE0_Msk; + timer[dev]->CC[0] = value; + timer_config[dev].flags |= TIMER_CH0; + timer[dev]->INTENSET |= TIMER_INTENSET_COMPARE0_Msk; break; case 1: - timer->CC[1] = value; - timer->INTENSET |= TIMER_INTENSET_COMPARE1_Msk; + timer[dev]->CC[1] = value; + timer_config[dev].flags |= TIMER_CH1; + timer[dev]->INTENSET |= TIMER_INTENSET_COMPARE1_Msk; break; case 2: - timer->CC[2] = value; - timer->INTENSET |= TIMER_INTENSET_COMPARE2_Msk; + timer[dev]->CC[2] = value; + timer_config[dev].flags |= TIMER_CH2; + timer[dev]->INTENSET |= TIMER_INTENSET_COMPARE2_Msk; break; default: return -2; @@ -170,38 +172,23 @@ int timer_set_absolute(tim_t dev, int channel, unsigned int value) int timer_clear(tim_t dev, int channel) { - NRF_TIMER_Type *timer; - - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - timer = TIMER_0_DEV; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - timer = TIMER_1_DEV; - break; -#endif -#if TIMER_2_EN - case TIMER_2: - timer = TIMER_2_DEV; - break; -#endif - case TIMER_UNDEFINED: - return -1; + if (dev >= TIMER_NUMOF) { + return -1; } /* set timeout value */ switch (channel) { case 0: - timer->INTENCLR = TIMER_INTENCLR_COMPARE0_Msk; + timer_config[dev].flags &= ~TIMER_CH0; + timer[dev]->INTENCLR = TIMER_INTENCLR_COMPARE0_Msk; break; case 1: - timer->INTENCLR = TIMER_INTENCLR_COMPARE1_Msk; + timer_config[dev].flags &= ~TIMER_CH1; + timer[dev]->INTENCLR = TIMER_INTENCLR_COMPARE1_Msk; break; case 2: - timer->INTENCLR = TIMER_INTENCLR_COMPARE2_Msk; + timer_config[dev].flags &= ~TIMER_CH2; + timer[dev]->INTENCLR = TIMER_INTENCLR_COMPARE2_Msk; break; default: return -2; @@ -212,70 +199,25 @@ int timer_clear(tim_t dev, int channel) unsigned int timer_read(tim_t dev) { - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - TIMER_0_DEV->TASKS_CAPTURE[3] = 1; - return TIMER_0_DEV->CC[3]; -#endif -#if TIMER_1_EN - case TIMER_1: - TIMER_1_DEV->TASKS_CAPTURE[3] = 1; - return TIMER_1_DEV->CC[3]; -#endif -#if TIMER_2_EN - case TIMER_2: - TIMER_2_DEV->TASKS_CAPTURE[3] = 1; - return TIMER_2_DEV->CC[3]; -#endif - case TIMER_UNDEFINED: - default: - return 0; + if (dev >= TIMER_NUMOF) { + return 0; } + + timer[dev]->TASKS_CAPTURE[3] = 1; + return timer[dev]->CC[3]; } void timer_start(tim_t dev) { - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - TIMER_0_DEV->TASKS_START = 1; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - TIMER_1_DEV->TASKS_START = 1; - break; -#endif -#if TIMER_2_EN - case TIMER_2: - TIMER_2_DEV->TASKS_START = 1; - break; -#endif - case TIMER_UNDEFINED: - break; + if (dev < TIMER_NUMOF) { + timer[dev]->TASKS_START = 1; } } -void timer_stop(tim_t dev) { - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - TIMER_0_DEV->TASKS_STOP = 1; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - TIMER_1_DEV->TASKS_STOP = 1; - break; -#endif -#if TIMER_2_EN - case TIMER_2: - TIMER_2_DEV->TASKS_STOP = 1; - break; -#endif - case TIMER_UNDEFINED: - break; +void timer_stop(tim_t dev) +{ + if (dev < TIMER_NUMOF) { + timer[dev]->TASKS_STOP = 1; } } @@ -327,24 +269,8 @@ void timer_irq_disable(tim_t dev) void timer_reset(tim_t dev) { - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - TIMER_0_DEV->TASKS_CLEAR = 1; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - TIMER_1_DEV->TASKS_CLEAR = 1; - break; -#endif -#if TIMER_2_EN - case TIMER_2: - TIMER_2_DEV->TASKS_CLEAR = 1; - break; -#endif - case TIMER_UNDEFINED: - break; + if (dev < TIMER_NUMOF) { + timer[dev]->TASKS_CLEAR = 1; } } @@ -354,8 +280,11 @@ void TIMER_0_ISR(void) for(int i = 0; i < TIMER_0_CHANNELS; i++){ if(TIMER_0_DEV->EVENTS_COMPARE[i] == 1){ TIMER_0_DEV->EVENTS_COMPARE[i] = 0; - TIMER_0_DEV->INTENCLR = (1 << (16 + i)); - timer_config[TIMER_0].cb(i); + if (timer_config[TIMER_0].flags & (1 << i)) { + timer_config[TIMER_0].flags &= ~(1 << i); + TIMER_0_DEV->INTENCLR = (1 << (16 + i)); + timer_config[TIMER_0].cb(i); + } } } if (sched_context_switch_request) { @@ -370,8 +299,11 @@ void TIMER_1_ISR(void) for(int i = 0; i < TIMER_1_CHANNELS; i++){ if(TIMER_1_DEV->EVENTS_COMPARE[i] == 1){ TIMER_1_DEV->EVENTS_COMPARE[i] = 0; - TIMER_1_DEV->INTENCLR = (1 << (16 + i)); - timer_config[TIMER_1].cb(i); + if (timer_config[TIMER_1].flags & (1 << i)) { + timer_config[TIMER_1].flags &= ~(1 << i); + TIMER_1_DEV->INTENCLR = (1 << (16 + i)); + timer_config[TIMER_1].cb(i); + } } } if (sched_context_switch_request) { @@ -386,8 +318,11 @@ void TIMER_2_ISR(void) for(int i = 0; i < TIMER_2_CHANNELS; i++){ if(TIMER_2_DEV->EVENTS_COMPARE[i] == 1){ TIMER_2_DEV->EVENTS_COMPARE[i] = 0; - TIMER_2_DEV->INTENCLR = (1 << (16 + i)); - timer_config[TIMER_2].cb(i); + if (timer_config[TIMER_2].flags & (1 << i)) { + timer_config[TIMER_2].flags &= ~(1 << i); + TIMER_2_DEV->INTENCLR = (1 << (16 + i)); + timer_config[TIMER_2].cb(i); + } } } if (sched_context_switch_request) {