cpu/cc2538/periph/timer overhaul. support 16-bit and 32-bit modes

pr/spi.typo
Ian Martin 7 years ago
parent 39ecc12d9d
commit abae801105

@ -76,9 +76,9 @@ extern "C" {
* @name xtimer configuration
* @{
*/
#define XTIMER_DEV TIMER_0
#define XTIMER_DEV (0)
#define XTIMER_CHAN (0)
#define XTIMER_SHIFT (-4)
#define XTIMER_WIDTH (16)
#define XTIMER_BACKOFF (50)
#define XTIMER_ISR_BACKOFF (40)
/** @} */

@ -30,49 +30,32 @@ extern "C" {
* @name Timer peripheral configuration
* @{
*/
#define TIMER_NUMOF GPTIMER_NUMOF
#define TIMER_0_EN 1
#define TIMER_1_EN 1
#define TIMER_2_EN 1
#define TIMER_3_EN 1
static const timer_conf_t timer_config[] = {
{
.dev = GPTIMER0,
.channels = 2,
.cfg = GPTMCFG_16_BIT_TIMER, /* required for XTIMER */
},
{
.dev = GPTIMER1,
.channels = 1,
.cfg = GPTMCFG_32_BIT_TIMER,
},
{
.dev = GPTIMER2,
.channels = 1,
.cfg = GPTMCFG_32_BIT_TIMER,
},
{
.dev = GPTIMER3,
.channels = 1,
.cfg = GPTMCFG_32_BIT_TIMER,
},
};
#define TIMER_IRQ_PRIO 1
#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
/* Timer 0 configuration */
#define TIMER_0_DEV GPTIMER0
#define TIMER_0_CHANNELS 1
#define TIMER_0_MAX_VALUE 0xffffffff
#define TIMER_0_IRQn_1 GPTIMER_0A_IRQn
#define TIMER_0_IRQn_2 GPTIMER_0B_IRQn
#define TIMER_0_ISR_1 isr_timer0_chan0
#define TIMER_0_ISR_2 isr_timer0_chan1
/* Timer 1 configuration */
#define TIMER_1_DEV GPTIMER1
#define TIMER_1_CHANNELS 1
#define TIMER_1_MAX_VALUE 0xffffffff
#define TIMER_1_IRQn_1 GPTIMER_1A_IRQn
#define TIMER_1_IRQn_2 GPTIMER_1B_IRQn
#define TIMER_1_ISR_1 isr_timer1_chan0
#define TIMER_1_ISR_2 isr_timer1_chan1
/* Timer 2 configuration */
#define TIMER_2_DEV GPTIMER2
#define TIMER_2_CHANNELS 1
#define TIMER_2_MAX_VALUE 0xffffffff
#define TIMER_2_IRQn_1 GPTIMER_2A_IRQn
#define TIMER_2_IRQn_2 GPTIMER_2B_IRQn
#define TIMER_2_ISR_1 isr_timer2_chan0
#define TIMER_2_ISR_2 isr_timer2_chan1
/* Timer 3 configuration */
#define TIMER_3_DEV GPTIMER3
#define TIMER_3_CHANNELS 1
#define TIMER_3_MAX_VALUE 0xffffffff
#define TIMER_3_IRQn_1 GPTIMER_3A_IRQn
#define TIMER_3_IRQn_2 GPTIMER_3B_IRQn
#define TIMER_3_ISR_1 isr_timer3_chan0
#define TIMER_3_ISR_2 isr_timer3_chan1
#define TIMER_IRQ_PRIO 1
/** @} */

@ -64,9 +64,9 @@
* @name xtimer configuration
* @{
*/
#define XTIMER_DEV TIMER_0
#define XTIMER_DEV (0)
#define XTIMER_CHAN (0)
#define XTIMER_SHIFT (-4)
#define XTIMER_WIDTH (16)
#define XTIMER_BACKOFF (50)
#define XTIMER_ISR_BACKOFF (40)
/** @} */

@ -37,48 +37,31 @@
* @name Timer configuration
* @{
*/
#define TIMER_NUMOF (4U)
#define TIMER_0_EN 1
#define TIMER_1_EN 1
#define TIMER_2_EN 1
#define TIMER_3_EN 1
#define TIMER_IRQ_PRIO 1
static const timer_conf_t timer_config[] = {
{
.dev = GPTIMER0,
.channels = 2,
.cfg = GPTMCFG_16_BIT_TIMER, /* required for XTIMER */
},
{
.dev = GPTIMER1,
.channels = 1,
.cfg = GPTMCFG_32_BIT_TIMER,
},
{
.dev = GPTIMER2,
.channels = 1,
.cfg = GPTMCFG_32_BIT_TIMER,
},
{
.dev = GPTIMER3,
.channels = 1,
.cfg = GPTMCFG_32_BIT_TIMER,
},
};
/* Timer 0 configuration */
#define TIMER_0_DEV GPTIMER0
#define TIMER_0_CHANNELS 1
#define TIMER_0_MAX_VALUE 0xffffffff
#define TIMER_0_IRQn_1 GPTIMER_0A_IRQn
#define TIMER_0_IRQn_2 GPTIMER_0B_IRQn
#define TIMER_0_ISR_1 isr_timer0_chan0
#define TIMER_0_ISR_2 isr_timer0_chan1
/* Timer 1 configuration */
#define TIMER_1_DEV GPTIMER1
#define TIMER_1_CHANNELS 1
#define TIMER_1_MAX_VALUE 0xffffffff
#define TIMER_1_IRQn_1 GPTIMER_1A_IRQn
#define TIMER_1_IRQn_2 GPTIMER_1B_IRQn
#define TIMER_1_ISR_1 isr_timer1_chan0
#define TIMER_1_ISR_2 isr_timer1_chan1
/* Timer 2 configuration */
#define TIMER_2_DEV GPTIMER2
#define TIMER_2_CHANNELS 1
#define TIMER_2_MAX_VALUE 0xffffffff
#define TIMER_2_IRQn_1 GPTIMER_2A_IRQn
#define TIMER_2_IRQn_2 GPTIMER_2B_IRQn
#define TIMER_2_ISR_1 isr_timer2_chan0
#define TIMER_2_ISR_2 isr_timer2_chan1
/* Timer 3 configuration */
#define TIMER_3_DEV GPTIMER3
#define TIMER_3_CHANNELS 1
#define TIMER_3_MAX_VALUE 0xffffffff
#define TIMER_3_IRQn_1 GPTIMER_3A_IRQn
#define TIMER_3_IRQn_2 GPTIMER_3B_IRQn
#define TIMER_3_ISR_1 isr_timer3_chan0
#define TIMER_3_ISR_2 isr_timer3_chan1
#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
#define TIMER_IRQ_PRIO 1
/** @} */
/**

@ -77,9 +77,9 @@
* @name xtimer configuration
* @{
*/
#define XTIMER_DEV TIMER_0
#define XTIMER_DEV (0)
#define XTIMER_CHAN (0)
#define XTIMER_SHIFT (-4)
#define XTIMER_WIDTH (16)
#define XTIMER_BACKOFF (50)
#define XTIMER_ISR_BACKOFF (40)
/** @} */

@ -39,49 +39,32 @@
* @name Timer configuration
* @{
*/
#define TIMER_NUMOF (4U)
#define TIMER_0_EN 1
#define TIMER_1_EN 1
#define TIMER_2_EN 1
#define TIMER_3_EN 1
static const timer_conf_t timer_config[] = {
{
.dev = GPTIMER0,
.channels = 2,
.cfg = GPTMCFG_16_BIT_TIMER, /* required for XTIMER */
},
{
.dev = GPTIMER1,
.channels = 1,
.cfg = GPTMCFG_32_BIT_TIMER,
},
{
.dev = GPTIMER2,
.channels = 1,
.cfg = GPTMCFG_32_BIT_TIMER,
},
{
.dev = GPTIMER3,
.channels = 1,
.cfg = GPTMCFG_32_BIT_TIMER,
},
};
#define TIMER_IRQ_PRIO 1
/* Timer 0 configuration */
#define TIMER_0_DEV GPTIMER0
#define TIMER_0_CHANNELS 1
#define TIMER_0_MAX_VALUE 0xffffffff
#define TIMER_0_IRQn_1 GPTIMER_0A_IRQn
#define TIMER_0_IRQn_2 GPTIMER_0B_IRQn
#define TIMER_0_ISR_1 isr_timer0_chan0
#define TIMER_0_ISR_2 isr_timer0_chan1
/* Timer 1 configuration */
#define TIMER_1_DEV GPTIMER1
#define TIMER_1_CHANNELS 1
#define TIMER_1_MAX_VALUE 0xffffffff
#define TIMER_1_IRQn_1 GPTIMER_1A_IRQn
#define TIMER_1_IRQn_2 GPTIMER_1B_IRQn
#define TIMER_1_ISR_1 isr_timer1_chan0
#define TIMER_1_ISR_2 isr_timer1_chan1
#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
/* Timer 2 configuration */
#define TIMER_2_DEV GPTIMER2
#define TIMER_2_CHANNELS 1
#define TIMER_2_MAX_VALUE 0xffffffff
#define TIMER_2_IRQn_1 GPTIMER_2A_IRQn
#define TIMER_2_IRQn_2 GPTIMER_2B_IRQn
#define TIMER_2_ISR_1 isr_timer2_chan0
#define TIMER_2_ISR_2 isr_timer2_chan1
/* Timer 3 configuration */
#define TIMER_3_DEV GPTIMER3
#define TIMER_3_CHANNELS 1
#define TIMER_3_MAX_VALUE 0xffffffff
#define TIMER_3_IRQn_1 GPTIMER_3A_IRQn
#define TIMER_3_IRQn_2 GPTIMER_3B_IRQn
#define TIMER_3_ISR_1 isr_timer3_chan0
#define TIMER_3_ISR_2 isr_timer3_chan1
#define TIMER_IRQ_PRIO 1
/** @} */
/**

@ -21,6 +21,7 @@
#include <stdint.h>
#include "cc2538_gptimer.h"
#include "cc2538_ssi.h"
#include "cc2538_gpio.h"
@ -73,6 +74,15 @@ typedef struct {
gpio_t cs_pin; /**< pin used for CS */
} periph_spi_conf_t;
/**
* @brief Timer configuration data
*/
typedef struct {
cc2538_gptimer_t *dev; /**< timer device */
uint_fast8_t channels; /**< number of channels */
uint_fast8_t cfg; /**< timer config word */
} timer_conf_t;
#ifdef __cplusplus
}
#endif

@ -18,8 +18,8 @@
* @}
*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <stdint.h>
#include "board.h"
#include "cpu.h"
@ -28,17 +28,44 @@
#include "periph/timer.h"
#include "periph_conf.h"
#define TIMER_A_IRQ_MASK 0x000000ff
#define TIMER_B_IRQ_MASK 0x0000ff00
#define ENABLE_DEBUG (0)
#include "debug.h"
#define NUM_CHANNELS 1
#define LOAD_VALUE 0xffff
#define TIMER_A_IRQ_MASK 0x000000ff
#define TIMER_B_IRQ_MASK 0x0000ff00
#define BIT(n) ( 1UL << (n) )
/* GPTIMER_CTL Bits: */
#define TBEN BIT(8)
#define TAEN BIT(0)
/* GPTIMER_TnMR Bits: */
#define TnCMIE BIT(5)
#define TnCDIR BIT(4)
/* GPTIMER_IMR Bits: */
#define TBMIM BIT(11)
#define TAMIM BIT(4)
/* Convert a gptimer instance pointer to a GPTimer number */
#define GPTIMER_GET_NUM(gptimer) ( ((uintptr_t)(gptimer) >> 12) & 0x3 )
#define match_bit(chan) ( (chan)? TBMIM : TAMIM )
/**
* @brief Timer state memory
*/
static timer_isr_ctx_t config[TIMER_NUMOF];
static unsigned long config_freq[TIMER_NUMOF];
static timer_isr_ctx_t config[GPTIMER_NUMOF];
static const int IRQn_lut[GPTIMER_NUMOF] = {
GPTIMER_0A_IRQn,
GPTIMER_1A_IRQn,
GPTIMER_2A_IRQn,
GPTIMER_3A_IRQn
};
/**
* @brief Setup the given timer
@ -46,43 +73,22 @@ static unsigned long config_freq[TIMER_NUMOF];
*/
int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg)
{
cc2538_gptimer_t *gptimer;
cc2538_gptimer_t *gptimer = timer_config[dev].dev;
unsigned int gptimer_num;
uint32_t chan_mode;
/* select the timer and enable the timer specific peripheral clocks */
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
gptimer = TIMER_0_DEV;
break;
#endif
#if TIMER_1_EN
case TIMER_1:
gptimer = TIMER_1_DEV;
break;
#endif
#if TIMER_2_EN
case TIMER_2:
gptimer = TIMER_2_DEV;
break;
#endif
#if TIMER_3_EN
case TIMER_3:
gptimer = TIMER_3_DEV;
break;
#endif
DEBUG("%s(%u, %lu, %p, %p)\n", __FUNCTION__, dev, freq, cb, arg);
case TIMER_UNDEFINED:
default:
return -1;
if (dev >= TIMER_NUMOF) {
return -1;
}
gptimer_num = ((uintptr_t)gptimer - (uintptr_t)GPTIMER0) / 0x1000;
gptimer_num = GPTIMER_GET_NUM(gptimer);
/* Save the callback function: */
config[dev].cb = cb;
config[dev].arg = arg;
config_freq[dev] = freq;
assert(gptimer_num < GPTIMER_NUMOF);
config[gptimer_num].cb = cb;
config[gptimer_num].arg = arg;
/* Enable the clock for this timer: */
SYS_CTRL_RCGCGPT |= (1 << gptimer_num);
@ -90,155 +96,134 @@ int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg)
/* Disable this timer before configuring it: */
gptimer->cc2538_gptimer_ctl.CTL = 0;
gptimer->CFG = GPTMCFG_32_BIT_TIMER;
gptimer->cc2538_gptimer_tamr.TAMR = GPTIMER_PERIODIC_MODE;
gptimer->cc2538_gptimer_tamr.TAMRbits.TACDIR = 1; /**< Count up */
gptimer->cc2538_gptimer_tamr.TAMRbits.TAMIE = 1; /**< Enable the Timer A Match Interrupt */
if (timer_config[dev].cfg == GPTMCFG_32_BIT_TIMER) {
/* Count up in periodic mode */
chan_mode = TnCMIE | TnCDIR | GPTIMER_PERIODIC_MODE;
if (timer_config[dev].channels > 1) {
DEBUG("Invalid timer_config. Multiple channels are available only in 16-bit mode.");
return -1;
}
if (freq != sys_clock_freq()) {
DEBUG("In 32-bit mode, the GPTimer frequency must equal the system clock frequency (%u).", sys_clock_freq());
return -1;
}
} else {
/* Count down in periodic mode */
chan_mode = TnCMIE | GPTIMER_PERIODIC_MODE;
}
gptimer->CFG = timer_config[dev].cfg;
gptimer->cc2538_gptimer_tamr.TAMR = chan_mode;
switch (timer_config[dev].channels) {
case 1:
/* Enable the timer: */
gptimer->cc2538_gptimer_ctl.CTL = TAEN;
break;
case 2:
gptimer->cc2538_gptimer_tbmr.TBMR = chan_mode;
gptimer->TAILR = LOAD_VALUE;
gptimer->TBILR = LOAD_VALUE;
uint32_t prescaler = sys_clock_freq();
prescaler += freq / 2;
prescaler /= freq;
if (prescaler > 0) prescaler--;
if (prescaler > 255) prescaler = 255;
gptimer->TAPR = prescaler;
gptimer->TBPR = prescaler;
/* Enable the timer: */
gptimer->cc2538_gptimer_ctl.CTL = TBEN | TAEN;
break;
}
/* Enable interrupts for given timer: */
timer_irq_enable(dev);
/* Enable the timer: */
gptimer->cc2538_gptimer_ctl.CTLbits.TAEN = 1;
return 0;
}
int timer_set(tim_t dev, int channel, unsigned int timeout)
{
cc2538_gptimer_t *gptimer;
/* get timer base register address */
cc2538_gptimer_t *gptimer = timer_config[dev].dev;
if (channel >= NUM_CHANNELS) {
if ( (dev >= TIMER_NUMOF) || (channel >= timer_config[dev].channels) ) {
return -1;
}
/* get timer base register address */
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
gptimer = TIMER_0_DEV;
break;
#endif
#if TIMER_1_EN
case TIMER_1:
gptimer = TIMER_1_DEV;
break;
#endif
#if TIMER_2_EN
case TIMER_2:
gptimer = TIMER_2_DEV;
break;
#endif
#if TIMER_3_EN
case TIMER_3:
gptimer = TIMER_3_DEV;
break;
#endif
case TIMER_UNDEFINED:
default:
return -1;
}
switch (channel) {
case 0:
/* clear any pending match interrupts */
gptimer->ICR = TAMIM;
/* set timeout value */
gptimer->ICR = TIMER_A_IRQ_MASK; /**< Clear any pending interrupt status */
/* set timeout value */
gptimer->TAMATCHR = (gptimer->CFG == GPTMCFG_32_BIT_TIMER)? (gptimer->TAV + timeout) : (gptimer->TAV - timeout);
gptimer->cc2538_gptimer_imr.IMR |= TAMIM; /**< Enable the Timer A Match Interrupt */
break;
uint64_t scaled_value = timeout;
scaled_value *= RCOSC16M_FREQ;
scaled_value += config_freq[dev] / 2;
scaled_value /= config_freq[dev];
gptimer->TAMATCHR = gptimer->TAV + scaled_value;
case 1:
/* clear any pending match interrupts */
gptimer->ICR = TBMIM;
gptimer->cc2538_gptimer_imr.IMRbits.TAMIM = 1; /**< Enable the Timer A Match Interrupt */
/* set timeout value */
gptimer->TAMATCHR = (gptimer->CFG == GPTMCFG_32_BIT_TIMER)? (gptimer->TBV + timeout) : (gptimer->TBV - timeout);
gptimer->cc2538_gptimer_imr.IMR |= TBMIM; /**< Enable the Timer B Match Interrupt */
break;
}
return 1;
}
int timer_set_absolute(tim_t dev, int channel, unsigned int value)
{
cc2538_gptimer_t *gptimer;
DEBUG("%s(%u, %u, %u)\n", __FUNCTION__, dev, channel, value);
if (channel >= NUM_CHANNELS) {
/* get timer base register address */
cc2538_gptimer_t *gptimer = timer_config[dev].dev;
if ( (dev >= TIMER_NUMOF) || (channel >= timer_config[dev].channels) ) {
return -1;
}
/* get timer base register address */
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
gptimer = TIMER_0_DEV;
break;
#endif
#if TIMER_1_EN
case TIMER_1:
gptimer = TIMER_1_DEV;
break;
#endif
#if TIMER_2_EN
case TIMER_2:
gptimer = TIMER_2_DEV;
break;
#endif
#if TIMER_3_EN
case TIMER_3:
gptimer = TIMER_3_DEV;
break;
#endif
case TIMER_UNDEFINED:
default:
return -1;
}
switch (channel) {
case 0:
/* clear any pending match interrupts */
gptimer->ICR = TAMIM;
/* set timeout value */
gptimer->ICR = TIMER_A_IRQ_MASK; /**< Clear any pending interrupt status */
gptimer->TAMATCHR = (gptimer->CFG == GPTMCFG_32_BIT_TIMER)? value : (LOAD_VALUE - value);
gptimer->cc2538_gptimer_imr.IMR |= TAMIM; /**< Enable the Timer A Match Interrupt */
break;
uint64_t scaled_value = value;
scaled_value *= config_freq[dev];
scaled_value += RCOSC16M_FREQ / 2;
scaled_value /= RCOSC16M_FREQ;
gptimer->TAMATCHR = (scaled_value > UINT32_MAX)? UINT32_MAX : scaled_value;
case 1:
/* clear any pending match interrupts */
gptimer->ICR = TBMIM;
gptimer->cc2538_gptimer_imr.IMRbits.TAMIM = 1; /**< Enable the Timer A Match Interrupt */
gptimer->TBMATCHR = (gptimer->CFG == GPTMCFG_32_BIT_TIMER)? value : (LOAD_VALUE - value);
gptimer->cc2538_gptimer_imr.IMR |= TBMIM; /**< Enable the Timer B Match Interrupt */
break;
}
/* set timeout value */
return 1;
}
int timer_clear(tim_t dev, int channel)
{
cc2538_gptimer_t *gptimer;
DEBUG("%s(%u, %u)\n", __FUNCTION__, dev, channel);
if (channel >= NUM_CHANNELS) {
if ( (dev >= TIMER_NUMOF) || (channel >= timer_config[dev].channels) ) {
return -1;
}
/* get timer base register address */
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
gptimer = TIMER_0_DEV;
break;
#endif
#if TIMER_1_EN
case TIMER_1:
gptimer = TIMER_1_DEV;
break;
#endif
#if TIMER_2_EN
case TIMER_2:
gptimer = TIMER_2_DEV;
break;
#endif
#if TIMER_3_EN
case TIMER_3:
gptimer = TIMER_3_DEV;
break;
#endif
case TIMER_UNDEFINED:
default:
return -1;
}
gptimer->cc2538_gptimer_imr.IMR = 0;
timer_config[dev].dev->cc2538_gptimer_imr.IMR &= ~match_bit(channel);
return 1;
}
@ -249,27 +234,16 @@ int timer_clear(tim_t dev, int channel)
*/
unsigned int timer_read(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
return (uint64_t)TIMER_0_DEV->TAV * config_freq[TIMER_0] / RCOSC16M_FREQ;
#endif
#if TIMER_1_EN
case TIMER_1:
return (uint64_t)TIMER_1_DEV->TAV * config_freq[TIMER_1] / RCOSC16M_FREQ;
#endif
#if TIMER_2_EN
case TIMER_2:
return (uint64_t)TIMER_2_DEV->TAV * config_freq[TIMER_2] / RCOSC16M_FREQ;
#endif
#if TIMER_3_EN
case TIMER_3:
return (uint64_t)TIMER_3_DEV->TAV * config_freq[TIMER_3] / RCOSC16M_FREQ;
#endif
case TIMER_UNDEFINED:
default:
return 0;
if (dev >= TIMER_NUMOF) {
return 0;
}
cc2538_gptimer_t* gptimer = timer_config[dev].dev;
if (gptimer->CFG == GPTMCFG_32_BIT_TIMER) {
return gptimer->TAV;
}
else {
return LOAD_VALUE - (gptimer->TAV & 0xffff);
}
}
@ -278,200 +252,121 @@ unsigned int timer_read(tim_t dev)
*/
void timer_stop(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
TIMER_0_DEV->cc2538_gptimer_ctl.CTLbits.TAEN = 0;
break;
#endif
#if TIMER_1_EN
case TIMER_1:
TIMER_1_DEV->cc2538_gptimer_ctl.CTLbits.TAEN = 0;
break;
#endif
#if TIMER_2_EN
case TIMER_2:
TIMER_2_DEV->cc2538_gptimer_ctl.CTLbits.TAEN = 0;
break;
#endif
#if TIMER_3_EN
case TIMER_3:
TIMER_3_DEV->cc2538_gptimer_ctl.CTLbits.TAEN = 0;
break;
#endif
DEBUG("%s(%u)\n", __FUNCTION__, dev);
case TIMER_UNDEFINED:
break;
if (dev < TIMER_NUMOF) {
timer_config[dev].dev->cc2538_gptimer_ctl.CTL = 0;
}
}
void timer_start(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
TIMER_0_DEV->cc2538_gptimer_ctl.CTLbits.TAEN = 1;
break;
#endif
#if TIMER_1_EN
case TIMER_1:
TIMER_1_DEV->cc2538_gptimer_ctl.CTLbits.TAEN = 1;
break;
#endif
#if TIMER_2_EN
case TIMER_2:
TIMER_2_DEV->cc2538_gptimer_ctl.CTLbits.TAEN = 1;
break;
#endif
#if TIMER_3_EN
case TIMER_3:
TIMER_3_DEV->cc2538_gptimer_ctl.CTLbits.TAEN = 1;
break;
#endif
case TIMER_UNDEFINED:
break;
DEBUG("%s(%u)\n", __FUNCTION__, dev);
if (dev < TIMER_NUMOF) {
switch (timer_config[dev].channels) {
case 1:
timer_config[dev].dev->cc2538_gptimer_ctl.CTL = TAEN;
break;
case 2:
timer_config[dev].dev->cc2538_gptimer_ctl.CTL = TBEN | TAEN;
break;
}
}
}
void timer_irq_enable(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
NVIC_SetPriority(TIMER_0_IRQn_1, TIMER_IRQ_PRIO);
NVIC_SetPriority(TIMER_0_IRQn_2, TIMER_IRQ_PRIO);
NVIC_EnableIRQ(TIMER_0_IRQn_1);
NVIC_EnableIRQ(TIMER_0_IRQn_2);
break;
#endif
#if TIMER_1_EN
case TIMER_1:
NVIC_SetPriority(TIMER_1_IRQn_1, TIMER_IRQ_PRIO);
NVIC_SetPriority(TIMER_1_IRQn_2, TIMER_IRQ_PRIO);
NVIC_EnableIRQ(TIMER_1_IRQn_1);
NVIC_EnableIRQ(TIMER_1_IRQn_2);
break;
#endif
#if TIMER_2_EN
case TIMER_2:
NVIC_SetPriority(TIMER_2_IRQn_1, TIMER_IRQ_PRIO);
NVIC_SetPriority(TIMER_2_IRQn_2, TIMER_IRQ_PRIO);
NVIC_EnableIRQ(TIMER_2_IRQn_1);
NVIC_EnableIRQ(TIMER_2_IRQn_2);
break;
#endif
#if TIMER_3_EN
case TIMER_3:
NVIC_SetPriority(TIMER_3_IRQn_1, TIMER_IRQ_PRIO);
NVIC_SetPriority(TIMER_3_IRQn_2, TIMER_IRQ_PRIO);
NVIC_EnableIRQ(TIMER_3_IRQn_1);
NVIC_EnableIRQ(TIMER_3_IRQn_2);
break;
#endif
DEBUG("%s(%u)\n", __FUNCTION__, dev);
if (dev < TIMER_NUMOF) {
IRQn_Type irqn = IRQn_lut[GPTIMER_GET_NUM(timer_config[dev].dev)];
case TIMER_UNDEFINED:
default:
return;
NVIC_SetPriority(irqn, TIMER_IRQ_PRIO);
NVIC_EnableIRQ(irqn);
if (timer_config[dev].channels == 2) {
irqn++;
NVIC_SetPriority(irqn, TIMER_IRQ_PRIO);
NVIC_EnableIRQ(irqn);
}
}
}
void timer_irq_disable(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
NVIC_DisableIRQ(TIMER_0_IRQn_1);
NVIC_DisableIRQ(TIMER_0_IRQn_2);
break;
#endif
#if TIMER_1_EN
case TIMER_1:
NVIC_DisableIRQ(TIMER_1_IRQn_1);
NVIC_DisableIRQ(TIMER_1_IRQn_2);
break;
#endif
#if TIMER_2_EN
case TIMER_2:
NVIC_DisableIRQ(TIMER_2_IRQn_1);
NVIC_DisableIRQ(TIMER_2_IRQn_2);
break;
#endif
#if TIMER_3_EN
case TIMER_3:
NVIC_DisableIRQ(TIMER_3_IRQn_1);
NVIC_DisableIRQ(TIMER_3_IRQn_2);
break;
#endif
DEBUG("%s(%u)\n", __FUNCTION__, dev);
case TIMER_UNDEFINED:
default:
return;
if (dev < TIMER_NUMOF) {
IRQn_Type irqn = IRQn_lut[GPTIMER_GET_NUM(timer_config[dev].dev)];
NVIC_DisableIRQ(irqn);
if (timer_config[dev].channels == 2) {
irqn++;
NVIC_DisableIRQ(irqn);
}
}
}
static inline void irq_handler(int tim, int chan)
{
if (config[tim].cb != NULL) {
config[tim].cb(config[tim].arg, chan);
static cc2538_gptimer_t* GPTIMER = GPTIMER0;
static void irq_handler_a(int n) {
uint32_t mis;
/* Latch the active interrupt flags */
mis = GPTIMER[n].MIS & TIMER_A_IRQ_MASK;
/* Clear the latched interrupt flags */
GPTIMER[n].ICR = mis;
if (mis & TAMIM) {
/* This is a Timer A Match Interrupt */
/* Disable further match interrupts for this timer/channel */
GPTIMER[n].cc2538_gptimer_imr.IMR &= ~TAMIM;
/* Invoke the callback function */
assert(config[n].cb != NULL);
config[n].cb(config[n].arg, 0);
}
if (sched_context_switch_request) {
thread_yield();
}
}
#if TIMER_0_EN
void TIMER_0_ISR_1(void)
{
TIMER_0_DEV->ICR = TIMER_A_IRQ_MASK;
irq_handler(0, 0);
}
static void irq_handler_b(int n) {
uint32_t mis;
void TIMER_0_ISR_2(void)
{
TIMER_0_DEV->ICR = TIMER_B_IRQ_MASK;
irq_handler(0, 1);
}
#endif /* TIMER_0_EN */
/* Latch the active interrupt flags */
mis = GPTIMER[n].MIS & TIMER_B_IRQ_MASK;
#if TIMER_1_EN
void TIMER_1_ISR_1(void)
{
TIMER_1_DEV->ICR = TIMER_A_IRQ_MASK;
irq_handler(1, 0);
}
/* Clear the latched interrupt flags */
GPTIMER[n].ICR = mis;
void TIMER_1_ISR_2(void)
{
TIMER_1_DEV->ICR = TIMER_B_IRQ_MASK;
irq_handler(1, 1);
}
#endif /* TIMER_1_EN */
if (mis & TBMIM) {
/* This is a Timer B Match Interrupt */
#if TIMER_2_EN
void TIMER_2_ISR_1(void)
{
TIMER_2_DEV->ICR = TIMER_A_IRQ_MASK;
irq_handler(2, 0);
}
/* Disable further match interrupts for this timer/channel */
GPTIMER[n].cc2538_gptimer_imr.IMR &= ~TBMIM;
void TIMER_2_ISR_2(void)
{
TIMER_2_DEV->ICR = TIMER_B_IRQ_MASK;
irq_handler(2, 1);
}
#endif /* TIMER_2_EN */
/* Invoke the callback function */
assert(config[n].cb != NULL);
config[n].cb(config[n].arg, 1);
}
#if TIMER_3_EN
void TIMER_3_ISR_1(void)
{
TIMER_3_DEV->ICR = TIMER_A_IRQ_MASK;
irq_handler(3, 0);
if (sched_context_switch_request) {
thread_yield();
}
}
void TIMER_3_ISR_2(void)
{
TIMER_3_DEV->ICR = TIMER_B_IRQ_MASK;
irq_handler(3, 1);
}
#endif /* TIMER_3_EN */
void isr_timer0_chan0(void) {irq_handler_a(0);}
void isr_timer0_chan1(void) {irq_handler_b(0);}
void isr_timer1_chan0(void) {irq_handler_a(1);}
void isr_timer1_chan1(void) {irq_handler_b(1);}
void isr_timer2_chan0(void) {irq_handler_a(2);}
void isr_timer2_chan1(void) {irq_handler_b(2);}
void isr_timer3_chan0(void) {irq_handler_a(3);}
void isr_timer3_chan1(void) {irq_handler_b(3);}

Loading…
Cancel
Save