mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-28 16:01:18 +01:00
cpu/sam3: reworked timer driver
This commit is contained in:
parent
6b9088aa11
commit
af5ba0b5da
@ -60,6 +60,16 @@ typedef uint32_t gpio_t;
|
||||
*/
|
||||
#define CPUID_LEN (16U)
|
||||
|
||||
/**
|
||||
* @brief All SAM3 timers are 32-bit wide
|
||||
*/
|
||||
#define TIMER_MAX_VAL (0xffffffff)
|
||||
|
||||
/**
|
||||
* @brief We use 3 channels for each defined timer
|
||||
*/
|
||||
#define TIMER_CHANNELS (3)
|
||||
|
||||
/**
|
||||
* @brief Override values for pull register configuration
|
||||
* @{
|
||||
@ -102,6 +112,14 @@ typedef enum {
|
||||
GPIO_MUX_B = 1, /**< alternate function B */
|
||||
} gpio_mux_t;
|
||||
|
||||
/**
|
||||
* @brief Timer configuration data
|
||||
*/
|
||||
typedef struct {
|
||||
Tc *dev; /**< timer device */
|
||||
uint8_t id_ch0; /**< ID of the timer's first channel */
|
||||
} timer_conf_t;
|
||||
|
||||
/**
|
||||
* @brief UART configuration data
|
||||
*/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
* Copyright (C) 2014-2016 Freie Universität Berlin
|
||||
*
|
||||
* 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
|
||||
@ -7,11 +7,11 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup driver_periph
|
||||
* @ingroup cpu_sam3
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level timer driver implementation for the SAM3X8E CPU
|
||||
* @brief Low-level timer driver implementation
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
@ -28,473 +28,186 @@
|
||||
#include "periph/timer.h"
|
||||
#include "periph_conf.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
void (*cb)(int);
|
||||
} timer_conf_t;
|
||||
|
||||
/**
|
||||
* @brief Timer state memory
|
||||
* @brief Memory to store the interrupt context
|
||||
*/
|
||||
static timer_conf_t timer_config[TIMER_NUMOF];
|
||||
|
||||
static timer_isr_ctx_t isr_ctx[TIMER_NUMOF];
|
||||
|
||||
/**
|
||||
* @brief Setup the given timer
|
||||
* @brief Enable the clock for the selected timer channels
|
||||
*/
|
||||
static inline void clk_en(tim_t tim)
|
||||
{
|
||||
uint8_t id = timer_config[tim].id_ch0;
|
||||
|
||||
if (id < 32) {
|
||||
PMC->PMC_PCER0 = ((1 << id) | (1 << (id + 1)));
|
||||
} else {
|
||||
id -= 32;
|
||||
PMC->PMC_PCER1 = ((1 << id) | (1 << (id + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the timer ID from the timer's base address
|
||||
*/
|
||||
static inline Tc *dev(tim_t tim)
|
||||
{
|
||||
return timer_config[tim].dev;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Setup the given timer
|
||||
*
|
||||
* The SAM3X8E has 3 timers. Each timer has 3 independent channels.
|
||||
* RIOT uses the timers in WAVE mode with the following clock chaining:
|
||||
* The SAM3X8E has 3 timers build of 3 independent channels. Each of these
|
||||
* channels has 3 capture compare outputs (A-C).
|
||||
*
|
||||
* RIOT uses the 2 of the channels in WAVE mode with the following clock
|
||||
* chaining:
|
||||
*
|
||||
* ---------- ----------
|
||||
* | | | |-> IRQ-compareA
|
||||
* | TCx[2] | ---- TIOA2 --->| TCx[0] |-> IRQ-compareB
|
||||
* | | | | |-> IRQ-compareC
|
||||
* ---------- | ----------
|
||||
* ^ |
|
||||
* | | ----------
|
||||
* | | | |-> IRQ-compareA
|
||||
* TIMER_CLOCK1 ------->| TCx[1] |-> IRQ-compareB
|
||||
* | |-> IRQ-compareC
|
||||
* ----------
|
||||
* | TCx[1] | ---- TIOA1 --->| TCx[0] |-> IRQ-compareB
|
||||
* | | | |-> IRQ-compareC
|
||||
* ---------- ----------
|
||||
* ^
|
||||
* TIMER_CLOCK1
|
||||
*
|
||||
* For each timer, channel 0 is used to implement a prescaler. Channel 0 is
|
||||
* For each timer, channel 1 is used to implement a prescaler. Channel 1 is
|
||||
* driven by the MCK / 2 (42MHz) (TIMER_CLOCK1).
|
||||
*/
|
||||
int timer_init(tim_t dev, unsigned long freq, void (*callback)(int))
|
||||
int timer_init(tim_t tim, unsigned long freq, void (*callback)(int))
|
||||
{
|
||||
Tc *tim;
|
||||
|
||||
/* select the timer and enable the timer specific peripheral clocks */
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
tim = TIMER_0_DEV;
|
||||
PMC->PMC_PCER0 = (1 << ID_TC0) | (1 << ID_TC1) | (1 << ID_TC2);
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
tim = TIMER_1_DEV;
|
||||
PMC->PMC_PCER0 = (1 << ID_TC3) | (1 << ID_TC4);
|
||||
PMC->PMC_PCER1 = (1 << (ID_TC5 - 32));
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_2_EN
|
||||
case TIMER_2:
|
||||
tim = TIMER_2_DEV;
|
||||
PMC->PMC_PCER1 = (1 << (ID_TC6 - 32)) | (1 << (ID_TC7 - 32)) | (1 << (ID_TC8 - 32));
|
||||
break;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
default:
|
||||
return -1;
|
||||
/* check if device is valid */
|
||||
if (tim >= TIMER_NUMOF) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* enable the device clock */
|
||||
clk_en(tim);
|
||||
|
||||
/* save callback */
|
||||
timer_config[dev].cb = callback;
|
||||
isr_ctx[tim].cb = callback;
|
||||
|
||||
/* configure the timer block by connecting TIOA2 to XC0 and XC1 */
|
||||
tim->TC_BMR = TC_BMR_TC0XC0S_TIOA2 | TC_BMR_TC1XC1S_TIOA2;
|
||||
/* configure the timer block by connecting TIOA1 to XC0 */
|
||||
dev(tim)->TC_BMR = TC_BMR_TC0XC0S_TIOA1;
|
||||
/* configure and enable channel 0 to use XC0 as input */
|
||||
dev(tim)->TC_CHANNEL[0].TC_CMR = (TC_CMR_TCCLKS_XC0 |
|
||||
TC_CMR_WAVE | TC_CMR_EEVT_XC0);
|
||||
dev(tim)->TC_CHANNEL[0].TC_CCR = (TC_CCR_CLKEN | TC_CCR_SWTRG);
|
||||
|
||||
/* configure and enable channels 0 and 1 to use XC0 and XC1 as input */
|
||||
tim->TC_CHANNEL[0].TC_CMR = TC_CMR_TCCLKS_XC0 | TC_CMR_WAVE | TC_CMR_EEVT_XC0;
|
||||
tim->TC_CHANNEL[1].TC_CMR = TC_CMR_TCCLKS_XC1 | TC_CMR_WAVE | TC_CMR_EEVT_XC0;
|
||||
tim->TC_CHANNEL[0].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; /* and start */
|
||||
tim->TC_CHANNEL[1].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; /* and start */
|
||||
|
||||
/* configure channel 2:
|
||||
/* configure channel 1:
|
||||
* - select wave mode
|
||||
* - set input clock to TIMER_CLOCK1 (MCK/2)
|
||||
* - reload on TC_CV == TC_RC
|
||||
* - let TIOA2 signal be toggled when TC_CV == TC_RC
|
||||
*/
|
||||
tim->TC_CHANNEL[2].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | TC_CMR_WAVE
|
||||
| TC_CMR_WAVSEL_UP_RC | TC_CMR_ACPC_TOGGLE;
|
||||
dev(tim)->TC_CHANNEL[1].TC_CMR = (TC_CMR_TCCLKS_TIMER_CLOCK1 | TC_CMR_WAVE |
|
||||
TC_CMR_WAVSEL_UP_RC | TC_CMR_ACPC_TOGGLE);
|
||||
|
||||
/* configure the frequency of channel 2 to freq * 4
|
||||
/* configure the frequency of channel 1 to freq * 4
|
||||
*
|
||||
* note: as channels 0 and 1 are only incremented on rising edges of TIOA2 line and
|
||||
* channel 2 toggles this line on each timer tick, the actual frequency driving ch0/1
|
||||
* is f_ch2 / 2 --> f_ch0/1 = (MCK / 2) / 2 / freq.
|
||||
* note: as channel 0 is only incremented on rising edges of TIOA1 line and
|
||||
* channel 1 toggles this line on each timer tick, the actual frequency
|
||||
* driving channel 0 is f_ch2 / 2 --> f_ch0/1 = (MCK / 2) / 2 / freq.
|
||||
*/
|
||||
tim->TC_CHANNEL[2].TC_RC = (CLOCK_CORECLOCK / 4) / freq;
|
||||
dev(tim)->TC_CHANNEL[1].TC_R[2] = (CLOCK_CORECLOCK / 4) / freq;
|
||||
|
||||
/* start channel 2 */
|
||||
tim->TC_CHANNEL[2].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG;
|
||||
/* start channel 1 */
|
||||
dev(tim)->TC_CHANNEL[1].TC_CCR = (TC_CCR_CLKEN | TC_CCR_SWTRG);
|
||||
|
||||
/* enable interrupts for given timer */
|
||||
timer_irq_enable(dev);
|
||||
/* enable global interrupts for given timer */
|
||||
timer_irq_enable(tim);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_set(tim_t dev, int channel, unsigned int timeout)
|
||||
int timer_set(tim_t tim, int channel, unsigned int timeout)
|
||||
{
|
||||
return timer_set_absolute(dev, channel, timer_read(dev) + timeout);
|
||||
return timer_set_absolute(tim, channel, timer_read(tim) + timeout);
|
||||
}
|
||||
|
||||
int timer_set_absolute(tim_t dev, int channel, unsigned int value)
|
||||
int timer_set_absolute(tim_t tim, int channel, unsigned int value)
|
||||
{
|
||||
Tc *tim;
|
||||
|
||||
/* get timer base register address */
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
tim = TIMER_0_DEV;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
tim = TIMER_1_DEV;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_2_EN
|
||||
case TIMER_2:
|
||||
tim = TIMER_2_DEV;
|
||||
break;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
default:
|
||||
return -1;
|
||||
if (channel >=TIMER_CHANNELS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set timeout value */
|
||||
switch (channel) {
|
||||
case 0:
|
||||
tim->TC_CHANNEL[0].TC_RA = value;
|
||||
tim->TC_CHANNEL[0].TC_IER = TC_IER_CPAS;
|
||||
break;
|
||||
case 1:
|
||||
tim->TC_CHANNEL[0].TC_RB = value;
|
||||
tim->TC_CHANNEL[0].TC_IER = TC_IER_CPBS;
|
||||
break;
|
||||
case 2:
|
||||
tim->TC_CHANNEL[0].TC_RC = value;
|
||||
tim->TC_CHANNEL[0].TC_IER = TC_IER_CPCS;
|
||||
break;
|
||||
case 3:
|
||||
tim->TC_CHANNEL[1].TC_RA = value;
|
||||
tim->TC_CHANNEL[1].TC_IER = TC_IER_CPAS;
|
||||
break;
|
||||
case 4:
|
||||
tim->TC_CHANNEL[1].TC_RB = value;
|
||||
tim->TC_CHANNEL[1].TC_IER = TC_IER_CPBS;
|
||||
break;
|
||||
case 5:
|
||||
tim->TC_CHANNEL[1].TC_RC = value;
|
||||
tim->TC_CHANNEL[1].TC_IER = TC_IER_CPCS;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
dev(tim)->TC_CHANNEL[0].TC_R[channel] = value;
|
||||
dev(tim)->TC_CHANNEL[0].TC_IER = (TC_IER_CPAS << channel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_clear(tim_t tim, int channel)
|
||||
{
|
||||
if (channel >= TIMER_CHANNELS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev(tim)->TC_CHANNEL[0].TC_IDR = (TC_IDR_CPAS << channel);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int timer_clear(tim_t dev, int channel)
|
||||
unsigned int timer_read(tim_t tim)
|
||||
{
|
||||
Tc *tim;
|
||||
|
||||
/* get timer base register address */
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
tim = TIMER_0_DEV;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
tim = TIMER_1_DEV;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_2_EN
|
||||
case TIMER_2:
|
||||
tim = TIMER_2_DEV;
|
||||
break;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* disable the channels interrupt */
|
||||
switch (channel) {
|
||||
case 0:
|
||||
tim->TC_CHANNEL[0].TC_IDR = TC_IDR_CPAS;
|
||||
break;
|
||||
case 1:
|
||||
tim->TC_CHANNEL[0].TC_IDR = TC_IDR_CPBS;
|
||||
break;
|
||||
case 2:
|
||||
tim->TC_CHANNEL[0].TC_IDR = TC_IDR_CPCS;
|
||||
break;
|
||||
case 3:
|
||||
tim->TC_CHANNEL[1].TC_IDR = TC_IDR_CPAS;
|
||||
break;
|
||||
case 4:
|
||||
tim->TC_CHANNEL[1].TC_IDR = TC_IDR_CPBS;
|
||||
break;
|
||||
case 5:
|
||||
tim->TC_CHANNEL[1].TC_IDR = TC_IDR_CPCS;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return dev(tim)->TC_CHANNEL[0].TC_CV;
|
||||
}
|
||||
|
||||
/*
|
||||
* The timer channels 1 and 2 are configured to run with the same speed and
|
||||
* have the same value (they run in parallel), so only on of them is returned.
|
||||
*/
|
||||
unsigned int timer_read(tim_t dev)
|
||||
void timer_start(tim_t tim)
|
||||
{
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
return TIMER_0_DEV->TC_CHANNEL[0].TC_CV;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
return TIMER_1_DEV->TC_CHANNEL[0].TC_CV;
|
||||
#endif
|
||||
#if TIMER_2_EN
|
||||
case TIMER_2:
|
||||
return TIMER_2_DEV->TC_CHANNEL[0].TC_CV;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
dev(tim)->TC_CHANNEL[1].TC_CCR = (TC_CCR_CLKEN | TC_CCR_SWTRG);
|
||||
}
|
||||
|
||||
/*
|
||||
* For stopping the counting of channels 1 + 2, channel 0 is disabled.
|
||||
*/
|
||||
void timer_stop(tim_t dev)
|
||||
void timer_stop(tim_t tim)
|
||||
{
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
TIMER_0_DEV->TC_CHANNEL[2].TC_CCR = TC_CCR_CLKDIS;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
TIMER_1_DEV->TC_CHANNEL[2].TC_CCR = TC_CCR_CLKDIS;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_2_EN
|
||||
case TIMER_2:
|
||||
TIMER_2_DEV->TC_CHANNEL[2].TC_CCR = TC_CCR_CLKDIS;
|
||||
break;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
break;
|
||||
}
|
||||
dev(tim)->TC_CHANNEL[1].TC_CCR = TC_CCR_CLKDIS;
|
||||
}
|
||||
|
||||
void timer_start(tim_t dev)
|
||||
void timer_irq_enable(tim_t tim)
|
||||
{
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
TIMER_0_DEV->TC_CHANNEL[2].TC_CCR = TC_CCR_CLKEN;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
TIMER_1_DEV->TC_CHANNEL[2].TC_CCR = TC_CCR_CLKEN;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_2_EN
|
||||
case TIMER_2:
|
||||
TIMER_2_DEV->TC_CHANNEL[2].TC_CCR = TC_CCR_CLKEN;
|
||||
break;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
break;
|
||||
}
|
||||
NVIC_EnableIRQ(timer_config[tim].id_ch0);
|
||||
}
|
||||
|
||||
void timer_irq_enable(tim_t dev)
|
||||
void timer_irq_disable(tim_t tim)
|
||||
{
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
NVIC_EnableIRQ(TC0_IRQn);
|
||||
NVIC_EnableIRQ(TC1_IRQn);
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
NVIC_EnableIRQ(TC3_IRQn);
|
||||
NVIC_EnableIRQ(TC4_IRQn);
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_2_EN
|
||||
case TIMER_2:
|
||||
NVIC_EnableIRQ(TC6_IRQn);
|
||||
NVIC_EnableIRQ(TC7_IRQn);
|
||||
break;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
break;
|
||||
}
|
||||
NVIC_DisableIRQ(timer_config[tim].id_ch0);
|
||||
}
|
||||
|
||||
void timer_irq_disable(tim_t dev)
|
||||
static inline void isr_handler(tim_t tim)
|
||||
{
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
NVIC_DisableIRQ(TC0_IRQn);
|
||||
NVIC_DisableIRQ(TC1_IRQn);
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
NVIC_DisableIRQ(TC3_IRQn);
|
||||
NVIC_DisableIRQ(TC4_IRQn);
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_2_EN
|
||||
case TIMER_2:
|
||||
NVIC_DisableIRQ(TC6_IRQn);
|
||||
NVIC_DisableIRQ(TC7_IRQn);
|
||||
break;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint32_t status = dev(tim)->TC_CHANNEL[0].TC_SR;
|
||||
|
||||
#if TIMER_0_EN
|
||||
void TIMER_0_ISR1(void)
|
||||
{
|
||||
uint32_t status = TIMER_0_DEV->TC_CHANNEL[0].TC_SR;
|
||||
if (status & TC_SR_CPAS) {
|
||||
TIMER_0_DEV->TC_CHANNEL[0].TC_IDR = TC_IDR_CPAS;
|
||||
timer_config[TIMER_0].cb(0);
|
||||
}
|
||||
else if (status & TC_SR_CPBS) {
|
||||
TIMER_0_DEV->TC_CHANNEL[0].TC_IDR = TC_IDR_CPBS;
|
||||
timer_config[TIMER_0].cb(1);
|
||||
}
|
||||
else if (status & TC_SR_CPCS) {
|
||||
TIMER_0_DEV->TC_CHANNEL[0].TC_IDR = TC_IDR_CPCS;
|
||||
timer_config[TIMER_0].cb(2);
|
||||
for (int i = 0; i < TIMER_CHANNELS; i++) {
|
||||
if (status & (TC_SR_CPAS << i)) {
|
||||
dev(tim)->TC_CHANNEL[0].TC_IDR = (TC_IDR_CPAS << i);
|
||||
isr_ctx[tim].cb(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (sched_context_switch_request) {
|
||||
thread_yield();
|
||||
}
|
||||
}
|
||||
|
||||
void TIMER_0_ISR2(void)
|
||||
#ifdef TIMER_0_ISR
|
||||
void TIMER_0_ISR(void)
|
||||
{
|
||||
uint32_t status = TIMER_0_DEV->TC_CHANNEL[1].TC_SR;
|
||||
if (status & TC_SR_CPAS) {
|
||||
TIMER_0_DEV->TC_CHANNEL[1].TC_IDR = TC_IDR_CPAS;
|
||||
timer_config[TIMER_0].cb(3);
|
||||
}
|
||||
else if (status & TC_SR_CPBS) {
|
||||
TIMER_0_DEV->TC_CHANNEL[1].TC_IDR = TC_IDR_CPBS;
|
||||
timer_config[TIMER_0].cb(4);
|
||||
}
|
||||
else if (status & TC_SR_CPCS) {
|
||||
TIMER_0_DEV->TC_CHANNEL[1].TC_IDR = TC_IDR_CPCS;
|
||||
timer_config[TIMER_0].cb(5);
|
||||
}
|
||||
if (sched_context_switch_request) {
|
||||
thread_yield();
|
||||
}
|
||||
isr_handler(0);
|
||||
}
|
||||
#endif /* TIMER_0_EN */
|
||||
#endif
|
||||
|
||||
|
||||
#if TIMER_1_EN
|
||||
void TIMER_1_ISR1(void)
|
||||
#ifdef TIMER_1_ISR
|
||||
void TIMER_1_ISR(void)
|
||||
{
|
||||
uint32_t status = TIMER_1_DEV->TC_CHANNEL[0].TC_SR;
|
||||
if (status & TC_SR_CPAS) {
|
||||
TIMER_1_DEV->TC_CHANNEL[0].TC_IDR = TC_IDR_CPAS;
|
||||
timer_config[TIMER_1].cb(0);
|
||||
}
|
||||
if (status & TC_SR_CPBS) {
|
||||
TIMER_1_DEV->TC_CHANNEL[0].TC_IDR = TC_IDR_CPBS;
|
||||
timer_config[TIMER_1].cb(1);
|
||||
}
|
||||
if (status & TC_SR_CPCS) {
|
||||
TIMER_1_DEV->TC_CHANNEL[0].TC_IDR = TC_IDR_CPCS;
|
||||
timer_config[TIMER_1].cb(2);
|
||||
}
|
||||
if (sched_context_switch_request) {
|
||||
thread_yield();
|
||||
}
|
||||
isr_handler(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
void TIMER_1_ISR2(void)
|
||||
#ifdef TIMER_2_ISR
|
||||
void TIMER_2_ISR(void)
|
||||
{
|
||||
uint32_t status = TIMER_1_DEV->TC_CHANNEL[1].TC_SR;
|
||||
if (status & TC_SR_CPAS) {
|
||||
TIMER_1_DEV->TC_CHANNEL[1].TC_IDR = TC_IDR_CPAS;
|
||||
timer_config[TIMER_1].cb(3);
|
||||
}
|
||||
if (status & TC_SR_CPBS) {
|
||||
TIMER_1_DEV->TC_CHANNEL[1].TC_IDR = TC_IDR_CPBS;
|
||||
timer_config[TIMER_1].cb(4);
|
||||
}
|
||||
if (status & TC_SR_CPCS) {
|
||||
TIMER_1_DEV->TC_CHANNEL[1].TC_IDR = TC_IDR_CPCS;
|
||||
timer_config[TIMER_1].cb(5);
|
||||
}
|
||||
if (sched_context_switch_request) {
|
||||
thread_yield();
|
||||
}
|
||||
isr_handler(2);
|
||||
}
|
||||
#endif /* TIMER_1_EN */
|
||||
|
||||
|
||||
#if TIMER_2_EN
|
||||
void TIMER_2_ISR1(void)
|
||||
{
|
||||
uint32_t status = TIMER_2_DEV->TC_CHANNEL[0].TC_SR;
|
||||
if (status & TC_SR_CPAS) {
|
||||
TIMER_2_DEV->TC_CHANNEL[0].TC_IDR = TC_IDR_CPAS;
|
||||
timer_config[TIMER_2].cb(0);
|
||||
}
|
||||
else if (status & TC_SR_CPBS) {
|
||||
TIMER_2_DEV->TC_CHANNEL[0].TC_IDR = TC_IDR_CPBS;
|
||||
timer_config[TIMER_2].cb(1);
|
||||
}
|
||||
else if (status & TC_SR_CPCS) {
|
||||
TIMER_2_DEV->TC_CHANNEL[0].TC_IDR = TC_IDR_CPCS;
|
||||
timer_config[TIMER_2].cb(2);
|
||||
}
|
||||
if (sched_context_switch_request) {
|
||||
thread_yield();
|
||||
}
|
||||
}
|
||||
|
||||
void TIMER_2_ISR2(void)
|
||||
{
|
||||
uint32_t status = TIMER_2_DEV->TC_CHANNEL[1].TC_SR;
|
||||
if (status & TC_SR_CPAS) {
|
||||
TIMER_2_DEV->TC_CHANNEL[1].TC_IDR = TC_IDR_CPAS;
|
||||
timer_config[TIMER_2].cb(3);
|
||||
}
|
||||
else if (status & TC_SR_CPBS) {
|
||||
TIMER_2_DEV->TC_CHANNEL[1].TC_IDR = TC_IDR_CPBS;
|
||||
timer_config[TIMER_2].cb(4);
|
||||
}
|
||||
else if (status & TC_SR_CPCS) {
|
||||
TIMER_2_DEV->TC_CHANNEL[1].TC_IDR = TC_IDR_CPCS;
|
||||
timer_config[TIMER_2].cb(5);
|
||||
}
|
||||
if (sched_context_switch_request) {
|
||||
thread_yield();
|
||||
}
|
||||
}
|
||||
#endif /* TIMER_2_EN */
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user