mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-17 05:32:45 +01:00
cpu/lm4f120: Update timer macros to timer_config_t
This commit is contained in:
parent
db6355fb13
commit
7c3082a7a3
@ -40,35 +40,32 @@ extern "C" {
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Timer configuration
|
||||
* @name Timer configuration
|
||||
* @{
|
||||
*/
|
||||
#define TIMER_NUMOF (2U)
|
||||
#define TIMER_0_EN 1
|
||||
#define TIMER_1_EN 1
|
||||
#define TIMER_IRQ_PRIO 1
|
||||
static const timer_conf_t timer_config[] = {
|
||||
{
|
||||
.dev = WTIMER0_BASE,
|
||||
.max = 0xffffffff,
|
||||
.irqn = Timer0A_IRQn,
|
||||
.sysctl = SYSCTL_PERIPH_WTIMER0,
|
||||
.intbase = INT_WTIMER0A,
|
||||
.channels = 1
|
||||
},
|
||||
{
|
||||
.dev = WTIMER1_BASE,
|
||||
.max = 0xffffffff,
|
||||
.irqn = Timer1A_IRQn,
|
||||
.sysctl = SYSCTL_PERIPH_WTIMER1,
|
||||
.intbase = INT_WTIMER1A,
|
||||
.channels = 1
|
||||
},
|
||||
};
|
||||
|
||||
#define TIMER_NUMOF ARRAY_SIZE(timer_config)
|
||||
|
||||
/* Timer 0 configuration
|
||||
*
|
||||
* WTIMER0 is a 32/64bits timer.
|
||||
* We use timer_a as TIMER_0
|
||||
*/
|
||||
#define TIMER_0_CHANNELS 1
|
||||
#define TIMER_0_MAX_VALUE (0xffffffff)
|
||||
#define TIMER_0_ISR isr_wtimer0a
|
||||
#define TIMER_0_IRQ_CHAN Timer0A_IRQn
|
||||
|
||||
/* Timer 1 configuration
|
||||
*
|
||||
* WTIMER1 is a 32/64bits timer.
|
||||
* We use timer_a as TIMER_1
|
||||
*/
|
||||
|
||||
#define TIMER_1_CHANNELS 1
|
||||
#define TIMER_1_MAX_VALUE (0xffffffff)
|
||||
#define TIMER_1_ISR isr_wtimer1a
|
||||
#define TIMER_1_IRQ_CHAN Timer1A_IRQn
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name UART configuration
|
||||
|
@ -21,7 +21,6 @@
|
||||
#ifndef PERIPH_CPU_H
|
||||
#define PERIPH_CPU_H
|
||||
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -34,7 +33,7 @@ extern "C" {
|
||||
*/
|
||||
#define HAVE_GPIO_T
|
||||
typedef uint32_t gpio_t;
|
||||
#define GPIO_PIN(x,y) ((gpio_t)((x<<4) | y))
|
||||
#define GPIO_PIN(x, y) ((gpio_t)((x<<4) | y))
|
||||
/** @} */
|
||||
|
||||
#ifndef DOXYGEN
|
||||
@ -106,6 +105,18 @@ typedef enum {
|
||||
} adc_res_t;
|
||||
#endif /* ndef DOXYGEN */
|
||||
|
||||
/**
|
||||
* @brief Define timer configuration values
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t dev; /**< Address of timer base */
|
||||
uint32_t max; /**< Max tick value of timer */
|
||||
int irqn; /**< Number of the higher timer IRQ channel */
|
||||
uint32_t sysctl; /**< Address of timer system control */
|
||||
uint32_t intbase; /**< Interrupt base of timer */
|
||||
int channels; /**< Number of channels for the timer */
|
||||
} timer_conf_t;
|
||||
|
||||
/**
|
||||
* @brief Override SPI hardware chip select macro
|
||||
*
|
||||
|
@ -30,315 +30,190 @@
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* @brief Struct holding the configuration data
|
||||
* @brief Interrupt context for each configured timer
|
||||
* @{
|
||||
*/
|
||||
typedef struct {
|
||||
timer_cb_t cb; /**< timeout callback */
|
||||
void *arg; /**< argument to the callback */
|
||||
unsigned int divisor; /**< software clock divisor */
|
||||
} timer_conf_t;
|
||||
|
||||
static timer_conf_t config[TIMER_NUMOF];
|
||||
static timer_isr_ctx_t isr_ctx[TIMER_NUMOF];
|
||||
static uint32_t isr_divisor[TIMER_NUMOF];
|
||||
/**@}*/
|
||||
|
||||
#include "hw_timer.h"
|
||||
|
||||
/* enable timer interrupts */
|
||||
static inline void _irq_enable(tim_t dev);
|
||||
static inline void _irq_enable(tim_t tim);
|
||||
|
||||
/* Missing from driverlib */
|
||||
static inline unsigned long
|
||||
PRIV_TimerPrescaleSnapshotGet(unsigned long ulbase, unsigned long ultimer) {
|
||||
return((ultimer == TIMER_A) ? HWREG(ulbase + TIMER_O_TAPS) :
|
||||
HWREG(ulbase + TIMER_O_TBPS));
|
||||
return ((ultimer == TIMER_A) ? HWREG(ulbase + TIMER_O_TAPS) :
|
||||
HWREG(ulbase + TIMER_O_TBPS));
|
||||
}
|
||||
|
||||
static inline unsigned long long _scaled_to_ll_value(unsigned int uncorrected, unsigned int divisor)
|
||||
static inline uint64_t _scaled_to_ll_value(uint32_t uncorrected,
|
||||
uint32_t divisor)
|
||||
{
|
||||
const unsigned long long scaledv = (unsigned long long) uncorrected * divisor;
|
||||
const uint64_t scaledv = (uint64_t) uncorrected * divisor;
|
||||
return scaledv;
|
||||
}
|
||||
|
||||
static inline unsigned int _llvalue_to_scaled_value(unsigned long long corrected, unsigned int divisor)
|
||||
static inline uint32_t _llvalue_to_scaled_value(uint64_t corrected,
|
||||
uint32_t divisor)
|
||||
{
|
||||
const unsigned long long scaledv = corrected / divisor;
|
||||
const uint64_t scaledv = corrected / divisor;
|
||||
return scaledv;
|
||||
}
|
||||
|
||||
int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg)
|
||||
int timer_init(tim_t tim, unsigned long freq, timer_cb_t cb, void *arg)
|
||||
{
|
||||
if (dev >= TIMER_NUMOF){
|
||||
if (tim >= TIMER_NUMOF){
|
||||
return -1;
|
||||
}
|
||||
const timer_conf_t *cfg = &timer_config[tim];
|
||||
|
||||
config[dev].cb = cb;
|
||||
config[dev].arg = arg;
|
||||
config[dev].divisor = ROM_SysCtlClockGet() / freq;
|
||||
isr_ctx[tim].cb = cb;
|
||||
isr_ctx[tim].arg = arg;
|
||||
isr_divisor[tim] = ROM_SysCtlClockGet() / freq;
|
||||
|
||||
unsigned int sysctl_timer;
|
||||
unsigned int timer_base;
|
||||
unsigned int timer_side = TIMER_A;
|
||||
unsigned int timer_cfg = TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC_UP | TIMER_TAMR_TAMIE;
|
||||
unsigned int timer_max_val = 0;
|
||||
unsigned int timer_cfg = TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC_UP |
|
||||
TIMER_TAMR_TAMIE;
|
||||
unsigned int timer_intbit = TIMER_TIMA_TIMEOUT | TIMER_TIMA_MATCH;
|
||||
|
||||
switch(dev){
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
sysctl_timer = SYSCTL_PERIPH_WTIMER0;
|
||||
timer_base = WTIMER0_BASE;
|
||||
timer_max_val = TIMER_0_MAX_VALUE;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
sysctl_timer = SYSCTL_PERIPH_WTIMER1;
|
||||
timer_base = WTIMER1_BASE;
|
||||
timer_max_val = TIMER_1_MAX_VALUE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return -1; /* unreachable */
|
||||
}
|
||||
ROM_SysCtlPeripheralEnable(cfg->sysctl);
|
||||
|
||||
ROM_TimerDisable(cfg->dev, timer_side);
|
||||
ROM_TimerConfigure(cfg->dev, timer_cfg);
|
||||
|
||||
ROM_SysCtlPeripheralEnable(sysctl_timer);
|
||||
uint64_t val_max = _scaled_to_ll_value(cfg->max, isr_divisor[tim]);
|
||||
|
||||
ROM_TimerDisable(timer_base, timer_side);
|
||||
ROM_TimerConfigure(timer_base, timer_cfg);
|
||||
ROM_TimerPrescaleSet(cfg->dev, timer_side, val_max >> 32);
|
||||
ROM_TimerLoadSet(cfg->dev, timer_side, val_max & 0xFFFFFFFF);
|
||||
ROM_TimerIntClear(cfg->dev, timer_intbit);
|
||||
|
||||
unsigned long long lltimer_val_max = _scaled_to_ll_value(timer_max_val, config[dev].divisor);
|
||||
ROM_TimerIntEnable(cfg->dev, timer_intbit);
|
||||
|
||||
ROM_TimerPrescaleSet(timer_base, timer_side, lltimer_val_max >> 32);
|
||||
ROM_TimerLoadSet(timer_base, timer_side, lltimer_val_max & 0xFFFFFFFF);
|
||||
ROM_TimerIntClear(timer_base, timer_intbit);
|
||||
|
||||
ROM_TimerIntEnable(timer_base, timer_intbit);
|
||||
|
||||
_irq_enable(dev);
|
||||
timer_start(dev);
|
||||
_irq_enable(tim);
|
||||
timer_start(tim);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_set_absolute(tim_t dev, int channel, unsigned int value)
|
||||
int timer_set_absolute(tim_t tim, int channel, unsigned int value)
|
||||
{
|
||||
(void) channel;
|
||||
if (tim >= TIMER_NUMOF || channel >= timer_config[tim].channels) {
|
||||
return -1;
|
||||
}
|
||||
const timer_conf_t *cfg = &timer_config[tim];
|
||||
|
||||
unsigned int timer_base;
|
||||
unsigned int timer_side = TIMER_A;
|
||||
unsigned long long scaledv;
|
||||
|
||||
if (dev >= TIMER_NUMOF){
|
||||
return -1;
|
||||
}
|
||||
ROM_TimerDisable(cfg->dev, timer_side);
|
||||
|
||||
switch(dev){
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
timer_base = WTIMER0_BASE;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
timer_base = WTIMER1_BASE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return -1; /* unreachable */
|
||||
break;
|
||||
}
|
||||
ROM_TimerDisable(timer_base, timer_side);
|
||||
|
||||
scaledv = _scaled_to_ll_value(value, config[dev].divisor);
|
||||
scaledv = _scaled_to_ll_value(value, isr_divisor[tim]);
|
||||
|
||||
if (scaledv>>32){
|
||||
ROM_TimerPrescaleMatchSet(timer_base, timer_side, scaledv >> 32);
|
||||
ROM_TimerPrescaleMatchSet(cfg->dev, timer_side, scaledv >> 32);
|
||||
}
|
||||
else {
|
||||
ROM_TimerPrescaleMatchSet(timer_base, timer_side, 0);
|
||||
ROM_TimerPrescaleMatchSet(cfg->dev, timer_side, 0);
|
||||
}
|
||||
|
||||
ROM_TimerMatchSet(timer_base, timer_side, (unsigned long) (scaledv & 0xFFFFFFFF));
|
||||
ROM_TimerEnable(timer_base, timer_side);
|
||||
ROM_TimerMatchSet(cfg->dev, timer_side, (uint32_t) (scaledv & 0xFFFFFFFF));
|
||||
ROM_TimerEnable(cfg->dev, timer_side);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_clear(tim_t dev, int channel)
|
||||
int timer_clear(tim_t tim, int channel)
|
||||
{
|
||||
(void) channel;
|
||||
|
||||
unsigned int timer_intbit = TIMER_TIMA_TIMEOUT;
|
||||
unsigned int timer_base;
|
||||
|
||||
if (dev >= TIMER_NUMOF){
|
||||
if (tim >= TIMER_NUMOF || channel >= timer_config[tim].channels) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(dev){
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
timer_base = WTIMER0_BASE;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
timer_base = WTIMER1_BASE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return -1; /* unreachable */
|
||||
break;
|
||||
}
|
||||
|
||||
ROM_TimerIntClear(timer_base, timer_intbit);
|
||||
ROM_TimerIntClear(timer_config[tim].dev, TIMER_TIMA_TIMEOUT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int timer_read(tim_t dev)
|
||||
unsigned int timer_read(tim_t tim)
|
||||
{
|
||||
unsigned int timer_base;
|
||||
unsigned int timer_side = TIMER_A;
|
||||
unsigned long long high_bits, high_bits_dup;
|
||||
unsigned long long low_bits;
|
||||
unsigned long long total;
|
||||
unsigned int scaled_value;
|
||||
|
||||
if (dev >= TIMER_NUMOF){
|
||||
if (tim >= TIMER_NUMOF){
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(dev){
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
timer_base = WTIMER0_BASE;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
timer_base = WTIMER1_BASE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return -1; /* unreachable */
|
||||
break;
|
||||
}
|
||||
const timer_conf_t *cfg = &timer_config[tim];
|
||||
|
||||
/* handle overflow happening between the 2 register reads */
|
||||
do {
|
||||
high_bits = ((unsigned long long)PRIV_TimerPrescaleSnapshotGet(timer_base, timer_side)) << 32;
|
||||
low_bits = (unsigned long long)ROM_TimerValueGet(timer_base, timer_side);
|
||||
high_bits_dup = ((unsigned long long)PRIV_TimerPrescaleSnapshotGet(timer_base, timer_side)) << 32;
|
||||
high_bits = ((uint64_t)PRIV_TimerPrescaleSnapshotGet(cfg->dev,
|
||||
timer_side)) << 32;
|
||||
low_bits = (uint64_t)ROM_TimerValueGet(cfg->dev, timer_side);
|
||||
high_bits_dup = ((uint64_t)PRIV_TimerPrescaleSnapshotGet(cfg->dev,
|
||||
timer_side)) << 32;
|
||||
} while (high_bits != high_bits_dup);
|
||||
|
||||
total = high_bits + low_bits;
|
||||
DEBUG("Combined %lx:%lx\n", (unsigned long) (total>>32), (unsigned long) (total & 0xFFFFFFFF));
|
||||
DEBUG("Combined %lx:%lx\n", (uint32_t)(total>>32),
|
||||
(uint32_t)(total & 0xFFFFFFFF));
|
||||
|
||||
scaled_value = _llvalue_to_scaled_value(total, config[dev].divisor);
|
||||
scaled_value = _llvalue_to_scaled_value(total, isr_divisor[tim]);
|
||||
|
||||
return scaled_value;
|
||||
}
|
||||
|
||||
void timer_start(tim_t dev)
|
||||
void timer_start(tim_t tim)
|
||||
{
|
||||
unsigned int timer_base;
|
||||
unsigned int timer_side = TIMER_A;
|
||||
|
||||
if (dev >= TIMER_NUMOF){
|
||||
return ;
|
||||
}
|
||||
|
||||
switch(dev){
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
timer_base = WTIMER0_BASE;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
timer_base = WTIMER1_BASE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return; /* unreachable */
|
||||
}
|
||||
|
||||
ROM_TimerEnable(timer_base, timer_side);
|
||||
}
|
||||
|
||||
void timer_stop(tim_t dev)
|
||||
{
|
||||
unsigned int timer_base;
|
||||
unsigned int timer_side = TIMER_A;
|
||||
|
||||
if (dev >= TIMER_NUMOF){
|
||||
if (tim >= TIMER_NUMOF){
|
||||
return;
|
||||
}
|
||||
|
||||
switch(dev){
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
timer_base = WTIMER0_BASE;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
timer_base = WTIMER1_BASE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return; /* unreachable */
|
||||
}
|
||||
|
||||
ROM_TimerDisable(timer_base, timer_side);
|
||||
ROM_TimerEnable(timer_config[tim].dev, TIMER_A);
|
||||
}
|
||||
|
||||
static inline void _irq_enable(tim_t dev)
|
||||
void timer_stop(tim_t tim)
|
||||
{
|
||||
unsigned int timer_intbase;
|
||||
|
||||
if (dev >= TIMER_NUMOF){
|
||||
if (tim >= TIMER_NUMOF){
|
||||
return;
|
||||
}
|
||||
|
||||
switch(dev){
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
timer_intbase = INT_WTIMER0A;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
timer_intbase = INT_WTIMER1A;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return; /* unreachable */
|
||||
}
|
||||
|
||||
ROM_IntPrioritySet(timer_intbase, 32);
|
||||
ROM_IntEnable(timer_intbase);
|
||||
ROM_TimerDisable(timer_config[tim].dev, TIMER_A);
|
||||
}
|
||||
|
||||
#if TIMER_0_EN
|
||||
void isr_wtimer0a(void)
|
||||
static inline void _irq_enable(tim_t tim)
|
||||
{
|
||||
if (tim >= TIMER_NUMOF){
|
||||
return;
|
||||
}
|
||||
|
||||
ROM_IntPrioritySet(timer_config[tim].intbase, 32);
|
||||
ROM_IntEnable(timer_config[tim].intbase);
|
||||
}
|
||||
|
||||
void _isr_timer(tim_t tim)
|
||||
{
|
||||
/* Clears both IT */
|
||||
ROM_TimerIntClear(WTIMER0_BASE, TIMER_TIMA_TIMEOUT | TIMER_TIMA_MATCH);
|
||||
config[TIMER_0].cb(config[TIMER_0].arg, 0);
|
||||
ROM_TimerIntClear(timer_config[tim].dev,
|
||||
TIMER_TIMA_TIMEOUT | TIMER_TIMA_MATCH);
|
||||
isr_ctx[tim].cb(isr_ctx[tim].arg, 0);
|
||||
cortexm_isr_end();
|
||||
}
|
||||
#endif /* TIMER_0_EN */
|
||||
|
||||
#if TIMER_1_EN
|
||||
void isr_wtimer1a(void)
|
||||
#ifdef TIMER_0_ISR
|
||||
void TIMER_0_ISR(void)
|
||||
{
|
||||
ROM_TimerIntClear(WTIMER1_BASE, TIMER_TIMA_TIMEOUT | TIMER_TIMA_MATCH);
|
||||
|
||||
config[TIMER_1].cb(config[TIMER_0].arg, 0);
|
||||
cortexm_isr_end();
|
||||
_isr_timer(0);
|
||||
}
|
||||
#endif /* TIMER_1_EN */
|
||||
#endif /* TIMER_0_ISR */
|
||||
|
||||
#ifdef TIMER_1_ISR
|
||||
void TIMER_1_ISR(void)
|
||||
{
|
||||
_isr_timer(1);
|
||||
}
|
||||
#endif /* TIMER_1_ISR */
|
||||
/** @} */
|
||||
|
Loading…
Reference in New Issue
Block a user