diff --git a/cpu/cc2538/include/cc2538_gptimer.h b/cpu/cc2538/include/cc2538_gptimer.h index 0b7d55033e3882a2c97957c5b1a75627e3c84dcb..15a8f90f6a7c2df882371f586691f60c2743fba1 100644 --- a/cpu/cc2538/include/cc2538_gptimer.h +++ b/cpu/cc2538/include/cc2538_gptimer.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Loci Controls Inc. + * 2018 HAW Hamburg * * 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 @@ -15,6 +16,7 @@ * @brief CC2538 General Purpose Timer (GPTIMER) driver * * @author Ian Martin <ian@locicontrols.com> + * @author Sebastian Meiling <s@mlng.net> */ #ifndef CC2538_GPTIMER_H @@ -28,15 +30,18 @@ extern "C" { #endif -#define GPTIMER_NUMOF 4 /**< The CC2538 has four general-purpose timer units. */ -#define NUM_CHANNELS_PER_GPTIMER 2 /**< Each G.P. timer unit has two channels: A and B. */ - +/** + * @brief Timer modes + */ enum { GPTIMER_ONE_SHOT_MODE = 1, /**< GPTIMER one-shot mode */ GPTIMER_PERIODIC_MODE = 2, /**< GPTIMER periodic mode */ GPTIMER_CAPTURE_MODE = 3, /**< GPTIMER capture mode */ }; +/** + * @brief Timer width configuration + */ enum { GPTMCFG_32_BIT_TIMER = 0, /**< 32-bit timer configuration */ GPTMCFG_32_BIT_REAL_TIME_CLOCK = 1, /**< 32-bit real-time clock */ @@ -48,95 +53,12 @@ enum { */ typedef struct { cc2538_reg_t CFG; /**< GPTIMER Configuration */ - - /** - * @brief Timer A - */ - union { - cc2538_reg_t TAMR; /**< GPTIMER Timer A mode */ - struct { - cc2538_reg_t TAMR2 : 2; /**< GPTM Timer A mode */ - cc2538_reg_t TACMR : 1; /**< GPTM Timer A capture mode */ - cc2538_reg_t TAAMS : 1; /**< GPTM Timer A alternate mode */ - cc2538_reg_t TACDIR : 1; /**< GPTM Timer A count direction */ - cc2538_reg_t TAMIE : 1; /**< GPTM Timer A match interrupt enable */ - cc2538_reg_t TAWOT : 1; /**< GPTM Timer A wait-on-trigger */ - cc2538_reg_t TASNAPS : 1; /**< GPTM Timer A snap shot mode */ - cc2538_reg_t TAILD : 1; /**< GPTM Timer A interval load write */ - cc2538_reg_t TAPWMIE : 1; /**< GPTM Timer A PWM interrupt enable */ - cc2538_reg_t TAMRSU : 1; /**< Timer A match register update mode */ - cc2538_reg_t TAPLO : 1; /**< Legacy PWM operation */ - cc2538_reg_t RESERVED5 : 20; /**< Reserved bits */ - } TAMRbits; - } cc2538_gptimer_tamr; - - /** - * @brief Timer B - */ - union { - cc2538_reg_t TBMR; /**< GPTIMER Timer B mode */ - struct { - cc2538_reg_t TBMR2 : 2; /**< GPTM Timer B mode */ - cc2538_reg_t TBCMR : 1; /**< GPTM Timer B capture mode */ - cc2538_reg_t TBAMS : 1; /**< GPTM Timer B alternate mode */ - cc2538_reg_t TBCDIR : 1; /**< GPTM Timer B count direction */ - cc2538_reg_t TBMIE : 1; /**< GPTM Timer B match interrupt enable */ - cc2538_reg_t TBWOT : 1; /**< GPTM Timer B wait-on-trigger */ - cc2538_reg_t TBSNAPS : 1; /**< GPTM Timer B snap shot mode */ - cc2538_reg_t TBILD : 1; /**< GPTM Timer B interval load write */ - cc2538_reg_t TBPWMIE : 1; /**< GPTM Timer B PWM interrupt enable */ - cc2538_reg_t TBMRSU : 1; /**< Timer B match register update mode */ - cc2538_reg_t TBPLO : 1; /**< Legacy PWM operation */ - cc2538_reg_t RESERVED6 : 20; /**< Reserved bits */ - } TBMRbits; - } cc2538_gptimer_tbmr; - - /** - * @brief Timer Control - */ - union { - cc2538_reg_t CTL; /**< GPTIMER Control */ - struct { - cc2538_reg_t TAEN : 1; /**< GPTM Timer A enable */ - cc2538_reg_t TASTALL : 1; /**< GPTM Timer A stall enable */ - cc2538_reg_t TAEVENT : 1; /**< GPTM Timer A event mode */ - cc2538_reg_t RESERVED1 : 1; /**< Reserved bits */ - cc2538_reg_t TAOTE : 1; /**< GPTM Timer A PWM output trigger enable */ - cc2538_reg_t TAPWML : 1; /**< GPTM Timer A PWM output level */ - cc2538_reg_t RESERVED2 : 1; /**< Reserved bits */ - cc2538_reg_t TBEN : 1; /**< GPTM Timer B enable */ - cc2538_reg_t TBSTALL : 1; /**< GPTM Timer B stall enable */ - cc2538_reg_t TBEVENT : 1; /**< GPTM Timer B event mode */ - cc2538_reg_t RESERVED3 : 1; /**< Reserved bits */ - cc2538_reg_t TBOTE : 1; /**< GPTM Timer B PWM output trigger enable */ - cc2538_reg_t TBPWML : 1; /**< GPTM Timer B PWM output level */ - cc2538_reg_t RESERVED4 : 17; /**< Reserved bits */ - } CTLbits; - } cc2538_gptimer_ctl; - + cc2538_reg_t TAMR; /**< GPTIMER Timer A mode */ + cc2538_reg_t TBMR; /**< GPTIMER Timer B mode */ + cc2538_reg_t CTL; /**< GPTIMER Control */ cc2538_reg_t SYNC; /**< GPTIMER Synchronize */ cc2538_reg_t RESERVED2; /**< Reserved word */ - - /** - * @brief Interrupt mask control - */ - union { - cc2538_reg_t IMR; /**< GPTIMER Interrupt Mask */ - struct { - cc2538_reg_t TATOIM : 1; /**< GPTM Timer A time-out interrupt mask */ - cc2538_reg_t CAMIM : 1; /**< GPTM Timer A capture match interrupt mask */ - cc2538_reg_t CAEIM : 1; /**< GPTM Timer A capture event interrupt mask */ - cc2538_reg_t RESERVED1 : 1; /**< Reserved bits */ - cc2538_reg_t TAMIM : 1; /**< GPTM Timer A match interrupt mask */ - cc2538_reg_t RESERVED2 : 3; /**< Reserved bits */ - cc2538_reg_t TBTOIM : 1; /**< GPTM Timer B time-out interrupt mask */ - cc2538_reg_t CBMIM : 1; /**< GPTM Timer B capture match interrupt mask */ - cc2538_reg_t CBEIM : 1; /**< GPTM Timer B capture event interrupt mask */ - cc2538_reg_t TBMIM : 1; /**< GPTM Timer B match interrupt mask */ - cc2538_reg_t RESERVED3 : 20; /**< Reserved bits */ - } IMRbits; - } cc2538_gptimer_imr; - + cc2538_reg_t IMR; /**< GPTIMER Interrupt Mask */ cc2538_reg_t RIS; /**< GPTIMER Raw Interrupt Status */ cc2538_reg_t MIS; /**< GPTIMER Masked Interrupt Status */ cc2538_reg_t ICR; /**< GPTIMER Interrupt Clear */ @@ -162,25 +84,6 @@ typedef struct { cc2538_reg_t RESERVED4[15]; /**< Reserved */ } cc2538_gptimer_t; -/** - * @brief Base address of general-purpose timers (GPT) - */ -#define GPTIMER_BASE (0x40030000) - -#define GPTIMER0 ( (cc2538_gptimer_t*)0x40030000 ) /**< GPTIMER0 Instance */ -#define GPTIMER1 ( (cc2538_gptimer_t*)0x40031000 ) /**< GPTIMER1 Instance */ -#define GPTIMER2 ( (cc2538_gptimer_t*)0x40032000 ) /**< GPTIMER2 Instance */ -#define GPTIMER3 ( (cc2538_gptimer_t*)0x40033000 ) /**< GPTIMER3 Instance */ - -void isr_timer0_chan0(void); /**< RIOT Timer 0 Channel 0 Interrupt Service Routine */ -void isr_timer0_chan1(void); /**< RIOT Timer 0 Channel 1 Interrupt Service Routine */ -void isr_timer1_chan0(void); /**< RIOT Timer 1 Channel 0 Interrupt Service Routine */ -void isr_timer1_chan1(void); /**< RIOT Timer 1 Channel 1 Interrupt Service Routine */ -void isr_timer2_chan0(void); /**< RIOT Timer 2 Channel 0 Interrupt Service Routine */ -void isr_timer2_chan1(void); /**< RIOT Timer 2 Channel 1 Interrupt Service Routine */ -void isr_timer3_chan0(void); /**< RIOT Timer 3 Channel 0 Interrupt Service Routine */ -void isr_timer3_chan1(void); /**< RIOT Timer 3 Channel 1 Interrupt Service Routine */ - #ifdef __cplusplus } /* end extern "C" */ #endif diff --git a/cpu/cc2538/periph/timer.c b/cpu/cc2538/periph/timer.c index f4c7e42077650e5367db7773190b9828bfeab3b7..703f24777a3365fdde9f7f926999b49ddc59144f 100644 --- a/cpu/cc2538/periph/timer.c +++ b/cpu/cc2538/periph/timer.c @@ -22,6 +22,9 @@ #include <assert.h> #include <stdint.h> +#include "vendor/hw_gptimer.h" +#include "vendor/hw_memmap.h" + #include "board.h" #include "cpu.h" #include "periph/timer.h" @@ -30,24 +33,18 @@ #define ENABLE_DEBUG (0) #include "debug.h" -#define LOAD_VALUE (0xffff) - -#define TIMER_A_IRQ_MASK (0x000000ff) -#define TIMER_B_IRQ_MASK (0x0000ff00) - -#define BIT(n) ( 1UL << (n) ) +#define LOAD_VALUE (0xffff) -/* GPTIMER_CTL Bits: */ -#define TBEN BIT(8) -#define TAEN BIT(0) +#define TIMER_A_IRQ_MASK (0x000000ff) +#define TIMER_B_IRQ_MASK (0x0000ff00) -/* GPTIMER_TnMR Bits: */ -#define TnCMIE BIT(5) -#define TnCDIR BIT(4) +/* GPTIMER_CTL Bits */ +#define TBEN GPTIMER_CTL_TBEN +#define TAEN GPTIMER_CTL_TAEN -/* GPTIMER_IMR Bits: */ -#define TBMIM BIT(11) -#define TAMIM BIT(4) +/* GPTIMER_TnMR Bits */ +#define TNMIE GPTIMER_TAMR_TAMIE +#define TNCDIR GPTIMER_TAMR_TACDIR typedef struct { uint16_t mask; @@ -55,15 +52,8 @@ typedef struct { } _isr_cfg_t; static const _isr_cfg_t chn_isr_cfg[] = { - { .mask = TIMER_A_IRQ_MASK, .flag = TAMIM }, - { .mask = TIMER_B_IRQ_MASK, .flag = TBMIM } -}; - -static const int irqn_cfg[] = { - GPTIMER_0A_IRQn, - GPTIMER_1A_IRQn, - GPTIMER_2A_IRQn, - GPTIMER_3A_IRQn + { .mask = TIMER_A_IRQ_MASK, .flag = GPTIMER_IMR_TAMIM }, + { .mask = TIMER_B_IRQ_MASK, .flag = GPTIMER_IMR_TBMIM } }; /** @@ -77,7 +67,7 @@ static inline void _irq_enable(tim_t tim) DEBUG("%s(%u)\n", __FUNCTION__, tim); if (tim < TIMER_NUMOF) { - IRQn_Type irqn = irqn_cfg[tim]; + IRQn_Type irqn = GPTIMER_0A_IRQn + (2 * tim); NVIC_SetPriority(irqn, TIMER_IRQ_PRIO); NVIC_EnableIRQ(irqn); @@ -94,7 +84,7 @@ static inline cc2538_gptimer_t *dev(tim_t tim) { assert(tim < TIMER_NUMOF); - return ((cc2538_gptimer_t *)(GPTIMER_BASE | (((uint32_t)tim) << 12))); + return ((cc2538_gptimer_t *)(GPTIMER0_BASE | (((uint32_t)tim) << 12))); } /** @@ -110,21 +100,20 @@ int timer_init(tim_t tim, unsigned long freq, timer_cb_t cb, void *arg) } /* Save the callback function: */ - assert(tim < TIMER_NUMOF); isr_ctx[tim].cb = cb; isr_ctx[tim].arg = arg; /* Enable the clock for this timer: */ - SYS_CTRL_RCGCGPT |= (1 << tim); + SYS_CTRL->RCGCGPT |= (1 << tim); /* Disable this timer before configuring it: */ - dev(tim)->cc2538_gptimer_ctl.CTL = 0; + dev(tim)->CTL = 0; uint32_t prescaler = 0; - uint32_t chan_mode = TnCMIE | GPTIMER_PERIODIC_MODE; + uint32_t chan_mode = TNMIE | GPTIMER_PERIODIC_MODE; if (timer_config[tim].cfg == GPTMCFG_32_BIT_TIMER) { /* Count up in periodic mode */ - chan_mode |= TnCDIR ; + chan_mode |= TNCDIR ; if (timer_config[tim].chn > 1) { DEBUG("Invalid timer_config. Multiple channels are available only in 16-bit mode."); @@ -153,15 +142,15 @@ int timer_init(tim_t tim, unsigned long freq, timer_cb_t cb, void *arg) } dev(tim)->CFG = timer_config[tim].cfg; - dev(tim)->cc2538_gptimer_ctl.CTL = TAEN; - dev(tim)->cc2538_gptimer_tamr.TAMR = chan_mode; + dev(tim)->CTL = TAEN; + dev(tim)->TAMR = chan_mode; if (timer_config[tim].chn > 1) { - dev(tim)->cc2538_gptimer_tbmr.TBMR = chan_mode; + dev(tim)->TBMR = chan_mode; dev(tim)->TBPR = prescaler; dev(tim)->TBILR = LOAD_VALUE; /* Enable the timer: */ - dev(tim)->cc2538_gptimer_ctl.CTL = TBEN | TAEN; + dev(tim)->CTL = TBEN | TAEN; } /* Enable interrupts for given timer: */ @@ -186,7 +175,7 @@ int timer_set_absolute(tim_t tim, int channel, unsigned int value) else { dev(tim)->TBMATCHR = (LOAD_VALUE - value); } - dev(tim)->cc2538_gptimer_imr.IMR |= chn_isr_cfg[channel].flag; + dev(tim)->IMR |= chn_isr_cfg[channel].flag; return 1; } @@ -199,7 +188,7 @@ int timer_clear(tim_t tim, int channel) return -1; } /* clear interupt flags */ - dev(tim)->cc2538_gptimer_imr.IMR &= ~(chn_isr_cfg[channel].flag); + dev(tim)->IMR &= ~(chn_isr_cfg[channel].flag); return 1; } @@ -232,7 +221,7 @@ void timer_stop(tim_t tim) DEBUG("%s(%u)\n", __FUNCTION__, tim); if (tim < TIMER_NUMOF) { - dev(tim)->cc2538_gptimer_ctl.CTL = 0; + dev(tim)->CTL = 0; } } @@ -242,10 +231,10 @@ void timer_start(tim_t tim) if (tim < TIMER_NUMOF) { if (timer_config[tim].chn == 1) { - dev(tim)->cc2538_gptimer_ctl.CTL = TAEN; + dev(tim)->CTL = TAEN; } else if (timer_config[tim].chn == 2) { - dev(tim)->cc2538_gptimer_ctl.CTL = TBEN | TAEN; + dev(tim)->CTL = TBEN | TAEN; } } } @@ -270,7 +259,7 @@ static void irq_handler(tim_t tim, int channel) if (mis & chn_isr_cfg[channel].flag) { /* Disable further match interrupts for this timer/channel */ - dev(tim)->cc2538_gptimer_imr.IMR &= ~chn_isr_cfg[channel].flag; + dev(tim)->IMR &= ~chn_isr_cfg[channel].flag; /* Invoke the callback function */ isr_ctx[tim].cb(isr_ctx[tim].arg, channel); }