Move SAMD51 Temperature timer to RTC (#16868)
This commit is contained in:
parent
4360142bd1
commit
199a1ba0e5
2 changed files with 97 additions and 47 deletions
|
@ -37,15 +37,16 @@
|
||||||
// Private Variables
|
// Private Variables
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
const tTimerConfig TimerConfig[NUM_HARDWARE_TIMERS] = {
|
const tTimerConfig TimerConfig[NUM_HARDWARE_TIMERS+1] = {
|
||||||
{ TC0, TC0_IRQn, TC_PRIORITY(0) },
|
{ {.pTc=TC0}, TC0_IRQn, TC_PRIORITY(0) }, // 0 - stepper
|
||||||
{ TC1, TC1_IRQn, TC_PRIORITY(1) },
|
{ {.pTc=TC1}, TC1_IRQn, TC_PRIORITY(1) }, // 1 - stepper (needed by 32 bit timers)
|
||||||
{ TC2, TC2_IRQn, TC_PRIORITY(2) }, // Reserved by framework tone function
|
{ {.pTc=TC2}, TC2_IRQn, TC_PRIORITY(2) }, // 2 - tone (framework)
|
||||||
{ TC3, TC3_IRQn, TC_PRIORITY(3) }, // Reserved by servo library
|
{ {.pTc=TC3}, TC3_IRQn, TC_PRIORITY(3) }, // 3 - servo
|
||||||
{ TC4, TC4_IRQn, TC_PRIORITY(4) },
|
{ {.pTc=TC4}, TC4_IRQn, TC_PRIORITY(4) },
|
||||||
{ TC5, TC5_IRQn, TC_PRIORITY(5) },
|
{ {.pTc=TC5}, TC5_IRQn, TC_PRIORITY(5) },
|
||||||
{ TC6, TC6_IRQn, TC_PRIORITY(6) },
|
{ {.pTc=TC6}, TC6_IRQn, TC_PRIORITY(6) },
|
||||||
{ TC7, TC7_IRQn, TC_PRIORITY(7) }
|
{ {.pTc=TC7}, TC7_IRQn, TC_PRIORITY(7) },
|
||||||
|
{ {.pRtc=RTC}, RTC_IRQn, TC_PRIORITY(8) } // 8 - temperature
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
@ -66,17 +67,47 @@ FORCE_INLINE void Disable_Irq(IRQn_Type irq) {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
|
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
|
||||||
Tc * const tc = TimerConfig[timer_num].pTimer;
|
|
||||||
IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
|
IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
|
||||||
|
|
||||||
// Disable interrupt, just in case it was already enabled
|
// Disable interrupt, just in case it was already enabled
|
||||||
Disable_Irq(irq);
|
Disable_Irq(irq);
|
||||||
|
|
||||||
|
if (timer_num == RTC_TIMER_NUM) {
|
||||||
|
Rtc * const rtc = TimerConfig[timer_num].pRtc;
|
||||||
|
|
||||||
|
// Disable timer interrupt
|
||||||
|
rtc->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP0;
|
||||||
|
|
||||||
|
// RTC clock setup
|
||||||
|
OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC32K; // External 32.768KHz oscillator
|
||||||
|
|
||||||
|
// Stop timer, just in case, to be able to reconfigure it
|
||||||
|
rtc->MODE0.CTRLA.bit.ENABLE = false;
|
||||||
|
SYNC(rtc->MODE0.SYNCBUSY.bit.ENABLE);
|
||||||
|
|
||||||
|
// Mode, reset counter on match
|
||||||
|
rtc->MODE0.CTRLA.reg = RTC_MODE0_CTRLA_MODE_COUNT32 | RTC_MODE0_CTRLA_MATCHCLR;
|
||||||
|
|
||||||
|
// Set compare value
|
||||||
|
rtc->MODE0.COMP[0].reg = (32768 + frequency / 2) / frequency;
|
||||||
|
SYNC(rtc->MODE0.SYNCBUSY.bit.COMP0);
|
||||||
|
|
||||||
|
// Enable interrupt on compare
|
||||||
|
rtc->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0; // reset pending interrupt
|
||||||
|
rtc->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_CMP0; // enable compare 0 interrupt
|
||||||
|
|
||||||
|
// And start timer
|
||||||
|
rtc->MODE0.CTRLA.bit.ENABLE = true;
|
||||||
|
SYNC(rtc->MODE0.SYNCBUSY.bit.ENABLE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Tc * const tc = TimerConfig[timer_num].pTc;
|
||||||
|
|
||||||
// Disable timer interrupt
|
// Disable timer interrupt
|
||||||
tc->COUNT32.INTENCLR.reg = TC_INTENCLR_OVF; // disable overflow interrupt
|
tc->COUNT32.INTENCLR.reg = TC_INTENCLR_OVF; // disable overflow interrupt
|
||||||
|
|
||||||
// TCn clock setup
|
// TCn clock setup
|
||||||
const uint8_t clockID = GCLK_CLKCTRL_IDs[TCC_INST_NUM + timer_num];
|
const uint8_t clockID = GCLK_CLKCTRL_IDs[TCC_INST_NUM + timer_num]; // TC clock are preceeded by TCC ones
|
||||||
GCLK->PCHCTRL[clockID].bit.CHEN = false;
|
GCLK->PCHCTRL[clockID].bit.CHEN = false;
|
||||||
SYNC(GCLK->PCHCTRL[clockID].bit.CHEN);
|
SYNC(GCLK->PCHCTRL[clockID].bit.CHEN);
|
||||||
GCLK->PCHCTRL[clockID].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN; // 120MHz startup code programmed
|
GCLK->PCHCTRL[clockID].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN; // 120MHz startup code programmed
|
||||||
|
@ -90,8 +121,6 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
|
||||||
tc->COUNT32.CTRLA.bit.SWRST = true;
|
tc->COUNT32.CTRLA.bit.SWRST = true;
|
||||||
SYNC(tc->COUNT32.SYNCBUSY.bit.SWRST);
|
SYNC(tc->COUNT32.SYNCBUSY.bit.SWRST);
|
||||||
|
|
||||||
NVIC_SetPriority(irq, TimerConfig[timer_num].priority);
|
|
||||||
|
|
||||||
// Wave mode, reset counter on overflow on 0 (I use count down to prevent double buffer use)
|
// Wave mode, reset counter on overflow on 0 (I use count down to prevent double buffer use)
|
||||||
tc->COUNT32.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ;
|
tc->COUNT32.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ;
|
||||||
tc->COUNT32.CTRLA.reg = TC_CTRLA_MODE_COUNT32 | TC_CTRLA_PRESCALER_DIV1;
|
tc->COUNT32.CTRLA.reg = TC_CTRLA_MODE_COUNT32 | TC_CTRLA_PRESCALER_DIV1;
|
||||||
|
@ -101,14 +130,17 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
|
||||||
// Set compare value
|
// Set compare value
|
||||||
tc->COUNT32.COUNT.reg = tc->COUNT32.CC[0].reg = (HAL_TIMER_RATE) / frequency;
|
tc->COUNT32.COUNT.reg = tc->COUNT32.CC[0].reg = (HAL_TIMER_RATE) / frequency;
|
||||||
|
|
||||||
|
// Enable interrupt on compare
|
||||||
|
tc->COUNT32.INTFLAG.reg = TC_INTFLAG_OVF; // reset pending interrupt
|
||||||
|
tc->COUNT32.INTENSET.reg = TC_INTENSET_OVF; // enable overflow interrupt
|
||||||
|
|
||||||
// And start timer
|
// And start timer
|
||||||
tc->COUNT32.CTRLA.bit.ENABLE = true;
|
tc->COUNT32.CTRLA.bit.ENABLE = true;
|
||||||
SYNC(tc->COUNT32.SYNCBUSY.bit.ENABLE);
|
SYNC(tc->COUNT32.SYNCBUSY.bit.ENABLE);
|
||||||
|
}
|
||||||
// Enable interrupt on RC compare
|
|
||||||
tc->COUNT32.INTENSET.reg = TC_INTENCLR_OVF; // enable overflow interrupt
|
|
||||||
|
|
||||||
// Finally, enable IRQ
|
// Finally, enable IRQ
|
||||||
|
NVIC_SetPriority(irq, TimerConfig[timer_num].priority);
|
||||||
NVIC_EnableIRQ(irq);
|
NVIC_EnableIRQ(irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// Defines
|
// Defines
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
#define RTC_TIMER_NUM 8 // This is not a TC but a RTC
|
||||||
|
|
||||||
typedef uint32_t hal_timer_t;
|
typedef uint32_t hal_timer_t;
|
||||||
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
|
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
|
||||||
|
@ -33,12 +34,12 @@ typedef uint32_t hal_timer_t;
|
||||||
|
|
||||||
#define STEP_TIMER_NUM 0 // index of timer to use for stepper (also +1 for 32bits counter)
|
#define STEP_TIMER_NUM 0 // index of timer to use for stepper (also +1 for 32bits counter)
|
||||||
#define PULSE_TIMER_NUM STEP_TIMER_NUM
|
#define PULSE_TIMER_NUM STEP_TIMER_NUM
|
||||||
#define TEMP_TIMER_NUM 4 // index of timer to use for temperature (also +1 for 32bits counter)
|
#define TEMP_TIMER_NUM RTC_TIMER_NUM // index of timer to use for temperature
|
||||||
|
|
||||||
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
|
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
|
||||||
|
|
||||||
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
|
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
|
||||||
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
|
#define STEPPER_TIMER_TICKS_PER_US (STEPPER_TIMER_RATE / 1000000) // stepper timer ticks per µs
|
||||||
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
|
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
|
||||||
|
|
||||||
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE
|
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE
|
||||||
|
@ -62,14 +63,21 @@ typedef uint32_t hal_timer_t;
|
||||||
#if STEP_TIMER_NUM != PULSE_TIMER_NUM
|
#if STEP_TIMER_NUM != PULSE_TIMER_NUM
|
||||||
#define HAL_PULSE_TIMER_ISR() TC_HANDLER(PULSE_TIMER_NUM)
|
#define HAL_PULSE_TIMER_ISR() TC_HANDLER(PULSE_TIMER_NUM)
|
||||||
#endif
|
#endif
|
||||||
#define HAL_TEMP_TIMER_ISR() TC_HANDLER(TEMP_TIMER_NUM)
|
#if TEMP_TIMER_NUM == RTC_TIMER_NUM
|
||||||
|
#define HAL_TEMP_TIMER_ISR() void RTC_Handler()
|
||||||
|
#else
|
||||||
|
#define HAL_TEMP_TIMER_ISR() TC_HANDLER(TEMP_TIMER_NUM)
|
||||||
|
#endif
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// Types
|
// Types
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Tc *pTimer;
|
union {
|
||||||
|
Tc *pTc;
|
||||||
|
Rtc *pRtc;
|
||||||
|
};
|
||||||
IRQn_Type IRQ_Id;
|
IRQn_Type IRQ_Id;
|
||||||
uint8_t priority;
|
uint8_t priority;
|
||||||
} tTimerConfig;
|
} tTimerConfig;
|
||||||
|
@ -87,17 +95,20 @@ extern const tTimerConfig TimerConfig[];
|
||||||
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
|
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
|
||||||
|
|
||||||
FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) {
|
FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) {
|
||||||
Tc * const tc = TimerConfig[timer_num].pTimer;
|
// Should never be called with timer RTC_TIMER_NUM
|
||||||
|
Tc * const tc = TimerConfig[timer_num].pTc;
|
||||||
tc->COUNT32.CC[0].reg = HAL_TIMER_TYPE_MAX - compare;
|
tc->COUNT32.CC[0].reg = HAL_TIMER_TYPE_MAX - compare;
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
|
FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
|
||||||
Tc * const tc = TimerConfig[timer_num].pTimer;
|
// Should never be called with timer RTC_TIMER_NUM
|
||||||
|
Tc * const tc = TimerConfig[timer_num].pTc;
|
||||||
return (hal_timer_t)(HAL_TIMER_TYPE_MAX - tc->COUNT32.CC[0].reg);
|
return (hal_timer_t)(HAL_TIMER_TYPE_MAX - tc->COUNT32.CC[0].reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
|
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
|
||||||
Tc * const tc = TimerConfig[timer_num].pTimer;
|
// Should never be called with timer RTC_TIMER_NUM
|
||||||
|
Tc * const tc = TimerConfig[timer_num].pTc;
|
||||||
tc->COUNT32.CTRLBSET.reg = TC_CTRLBCLR_CMD_READSYNC;
|
tc->COUNT32.CTRLBSET.reg = TC_CTRLBCLR_CMD_READSYNC;
|
||||||
SYNC(tc->COUNT32.SYNCBUSY.bit.CTRLB || tc->COUNT32.SYNCBUSY.bit.COUNT);
|
SYNC(tc->COUNT32.SYNCBUSY.bit.CTRLB || tc->COUNT32.SYNCBUSY.bit.COUNT);
|
||||||
return HAL_TIMER_TYPE_MAX - tc->COUNT32.COUNT.reg;
|
return HAL_TIMER_TYPE_MAX - tc->COUNT32.COUNT.reg;
|
||||||
|
@ -108,9 +119,16 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num);
|
||||||
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
|
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
|
||||||
|
|
||||||
FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
|
FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
|
||||||
Tc * const tc = TimerConfig[timer_num].pTimer;
|
if (timer_num == RTC_TIMER_NUM) {
|
||||||
|
Rtc * const rtc = TimerConfig[timer_num].pRtc;
|
||||||
|
// Clear interrupt flag
|
||||||
|
rtc->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Tc * const tc = TimerConfig[timer_num].pTc;
|
||||||
// Clear interrupt flag
|
// Clear interrupt flag
|
||||||
tc->COUNT32.INTFLAG.reg = TC_INTFLAG_OVF;
|
tc->COUNT32.INTFLAG.reg = TC_INTFLAG_OVF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HAL_timer_isr_epilogue(timer_num)
|
#define HAL_timer_isr_epilogue(timer_num)
|
||||||
|
|
Reference in a new issue