Skip to content

Commit

Permalink
cpu/nrf51822: fixed timers
Browse files Browse the repository at this point in the history
- changed TIMER_0 to be a 24-bit timer -> see Nordic PAN #32
- cleaned up timer initialization code
- added check if an interrupt channel was active
  • Loading branch information
haukepetersen committed Oct 17, 2014
1 parent 69ddd09 commit b8fa89f
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 26 deletions.
6 changes: 3 additions & 3 deletions cpu/nrf51822/include/hwtimer_cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
/**
* @ingroup cpu_nrf51822
* @{
*
*
* @file hwtimer_cpu.h
* @brief CPU specific hwtimer configuration options
*
*
* @author Hauke Petersen <hauke.peterse@fu-berlin.de>
*/

Expand All @@ -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 */
/** @} */


Expand Down
78 changes: 55 additions & 23 deletions cpu/nrf51822/periph/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,21 @@
#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;

/**
Expand All @@ -44,31 +57,29 @@ static timer_conf_t timer_config[TIMER_NUMOF];
int timer_init(tim_t dev, unsigned int ticks_per_us, void (*callback)(int))
{
NRF_TIMER_Type *timer;
uint32_t bitmode;

switch (dev) {
#if TIMER_0_EN
case TIMER_0:
timer = TIMER_0_DEV;
timer->POWER = 1;
timer->BITMODE = TIMER_0_BITMODE;
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;
bitmode = TIMER_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;
bitmode = TIMER_2_BITMODE;
NVIC_SetPriority(TIMER_2_IRQ, TIMER_IRQ_PRIO);
NVIC_EnableIRQ(TIMER_2_IRQ);
break;
Expand All @@ -79,12 +90,17 @@ int timer_init(tim_t dev, unsigned int ticks_per_us, void (*callback)(int))

/* save callback */
timer_config[dev].cb = callback;

timer_config[dev].flags = 0;
/* power on timer */
timer->POWER = 1;
/* stop and reset timer for configuration */
timer->TASKS_STOP = 1;

timer->TASKS_CLEAR = 1;
timer->SHORTS = 0;
/* define mode and counter width */
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->BITMODE = bitmode;
/* set prescaler, only some preconfigured values possible for now */
switch (ticks_per_us) {
case 1:
timer->PRESCALER = 4;
Expand All @@ -104,13 +120,6 @@ int timer_init(tim_t dev, unsigned int ticks_per_us, void (*callback)(int))
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);

/* start the timer */
timer->TASKS_START = 1;

Expand All @@ -126,22 +135,26 @@ 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;
uint8_t *flags;

/* get timer base register address */
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
timer = TIMER_0_DEV;
flags = &(timer_config[TIMER_0].flags);
break;
#endif
#if TIMER_1_EN
case TIMER_1:
timer = TIMER_1_DEV;
flags = &(timer_config[TIMER_1].flags);
break;
#endif
#if TIMER_2_EN
case TIMER_2:
timer = TIMER_2_DEV;
flags = &(timer_config[TIMER_2].flags);
break;
#endif
case TIMER_UNDEFINED:
Expand All @@ -151,14 +164,17 @@ int timer_set_absolute(tim_t dev, int channel, unsigned int value)
switch (channel) {
case 0:
timer->CC[0] = value;
*flags = (*flags) | TIMER_CH0;
timer->INTENSET |= TIMER_INTENSET_COMPARE0_Msk;
break;
case 1:
timer->CC[1] = value;
*flags = (*flags) | TIMER_CH1;
timer->INTENSET |= TIMER_INTENSET_COMPARE1_Msk;
break;
case 2:
timer->CC[2] = value;
*flags = (*flags) | TIMER_CH2;
timer->INTENSET |= TIMER_INTENSET_COMPARE2_Msk;
break;
default:
Expand All @@ -171,21 +187,25 @@ int timer_set_absolute(tim_t dev, int channel, unsigned int value)
int timer_clear(tim_t dev, int channel)
{
NRF_TIMER_Type *timer;
uint8_t *flags;

switch (dev) {
#if TIMER_0_EN
case TIMER_0:
timer = TIMER_0_DEV;
flags = &(timer_config[TIMER_0].flags);
break;
#endif
#if TIMER_1_EN
case TIMER_1:
timer = TIMER_1_DEV;
flags = &(timer_config[TIMER_1].flags);
break;
#endif
#if TIMER_2_EN
case TIMER_2:
timer = TIMER_2_DEV;
flags = &(timer_config[TIMER_2].flags);
break;
#endif
case TIMER_UNDEFINED:
Expand All @@ -195,12 +215,15 @@ int timer_clear(tim_t dev, int channel)
/* set timeout value */
switch (channel) {
case 0:
*flags = (*flags) & ~TIMER_CH0;
timer->INTENCLR = TIMER_INTENCLR_COMPARE0_Msk;
break;
case 1:
*flags = (*flags) & ~TIMER_CH0;
timer->INTENCLR = TIMER_INTENCLR_COMPARE1_Msk;
break;
case 2:
*flags = (*flags) & ~TIMER_CH0;
timer->INTENCLR = TIMER_INTENCLR_COMPARE2_Msk;
break;
default:
Expand Down Expand Up @@ -354,8 +377,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) {
Expand All @@ -370,8 +396,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) {
Expand All @@ -386,8 +415,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) {
Expand Down

0 comments on commit b8fa89f

Please sign in to comment.