Move SAMD51 Temperature timer to RTC (#16868)
This commit is contained in:
parent
4360142bd1
commit
199a1ba0e5
|
@ -37,15 +37,16 @@
|
|||
// Private Variables
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
const tTimerConfig TimerConfig[NUM_HARDWARE_TIMERS] = {
|
||||
{ TC0, TC0_IRQn, TC_PRIORITY(0) },
|
||||
{ TC1, TC1_IRQn, TC_PRIORITY(1) },
|
||||
{ TC2, TC2_IRQn, TC_PRIORITY(2) }, // Reserved by framework tone function
|
||||
{ TC3, TC3_IRQn, TC_PRIORITY(3) }, // Reserved by servo library
|
||||
{ TC4, TC4_IRQn, TC_PRIORITY(4) },
|
||||
{ TC5, TC5_IRQn, TC_PRIORITY(5) },
|
||||
{ TC6, TC6_IRQn, TC_PRIORITY(6) },
|
||||
{ TC7, TC7_IRQn, TC_PRIORITY(7) }
|
||||
const tTimerConfig TimerConfig[NUM_HARDWARE_TIMERS+1] = {
|
||||
{ {.pTc=TC0}, TC0_IRQn, TC_PRIORITY(0) }, // 0 - stepper
|
||||
{ {.pTc=TC1}, TC1_IRQn, TC_PRIORITY(1) }, // 1 - stepper (needed by 32 bit timers)
|
||||
{ {.pTc=TC2}, TC2_IRQn, TC_PRIORITY(2) }, // 2 - tone (framework)
|
||||
{ {.pTc=TC3}, TC3_IRQn, TC_PRIORITY(3) }, // 3 - servo
|
||||
{ {.pTc=TC4}, TC4_IRQn, TC_PRIORITY(4) },
|
||||
{ {.pTc=TC5}, TC5_IRQn, TC_PRIORITY(5) },
|
||||
{ {.pTc=TC6}, TC6_IRQn, TC_PRIORITY(6) },
|
||||
{ {.pTc=TC7}, TC7_IRQn, TC_PRIORITY(7) },
|
||||
{ {.pRtc=RTC}, RTC_IRQn, TC_PRIORITY(8) } // 8 - temperature
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
@ -66,49 +67,80 @@ FORCE_INLINE void Disable_Irq(IRQn_Type irq) {
|
|||
// --------------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
|
||||
// Disable interrupt, just in case it was already enabled
|
||||
Disable_Irq(irq);
|
||||
|
||||
// Disable timer interrupt
|
||||
tc->COUNT32.INTENCLR.reg = TC_INTENCLR_OVF; // disable overflow interrupt
|
||||
if (timer_num == RTC_TIMER_NUM) {
|
||||
Rtc * const rtc = TimerConfig[timer_num].pRtc;
|
||||
|
||||
// TCn clock setup
|
||||
const uint8_t clockID = GCLK_CLKCTRL_IDs[TCC_INST_NUM + timer_num];
|
||||
GCLK->PCHCTRL[clockID].bit.CHEN = false;
|
||||
SYNC(GCLK->PCHCTRL[clockID].bit.CHEN);
|
||||
GCLK->PCHCTRL[clockID].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN; // 120MHz startup code programmed
|
||||
SYNC(!GCLK->PCHCTRL[clockID].bit.CHEN);
|
||||
// Disable timer interrupt
|
||||
rtc->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP0;
|
||||
|
||||
// Stop timer, just in case, to be able to reconfigure it
|
||||
tc->COUNT32.CTRLA.bit.ENABLE = false;
|
||||
SYNC(tc->COUNT32.SYNCBUSY.bit.ENABLE);
|
||||
// RTC clock setup
|
||||
OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC32K; // External 32.768KHz oscillator
|
||||
|
||||
// Reset timer
|
||||
tc->COUNT32.CTRLA.bit.SWRST = true;
|
||||
SYNC(tc->COUNT32.SYNCBUSY.bit.SWRST);
|
||||
// Stop timer, just in case, to be able to reconfigure it
|
||||
rtc->MODE0.CTRLA.bit.ENABLE = false;
|
||||
SYNC(rtc->MODE0.SYNCBUSY.bit.ENABLE);
|
||||
|
||||
NVIC_SetPriority(irq, TimerConfig[timer_num].priority);
|
||||
// Mode, reset counter on match
|
||||
rtc->MODE0.CTRLA.reg = RTC_MODE0_CTRLA_MODE_COUNT32 | RTC_MODE0_CTRLA_MATCHCLR;
|
||||
|
||||
// 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.CTRLA.reg = TC_CTRLA_MODE_COUNT32 | TC_CTRLA_PRESCALER_DIV1;
|
||||
tc->COUNT32.CTRLBSET.reg = TC_CTRLBCLR_DIR;
|
||||
SYNC(tc->COUNT32.SYNCBUSY.bit.CTRLB);
|
||||
// Set compare value
|
||||
rtc->MODE0.COMP[0].reg = (32768 + frequency / 2) / frequency;
|
||||
SYNC(rtc->MODE0.SYNCBUSY.bit.COMP0);
|
||||
|
||||
// Set compare value
|
||||
tc->COUNT32.COUNT.reg = tc->COUNT32.CC[0].reg = (HAL_TIMER_RATE) / frequency;
|
||||
// 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
|
||||
tc->COUNT32.CTRLA.bit.ENABLE = true;
|
||||
SYNC(tc->COUNT32.SYNCBUSY.bit.ENABLE);
|
||||
// And start timer
|
||||
rtc->MODE0.CTRLA.bit.ENABLE = true;
|
||||
SYNC(rtc->MODE0.SYNCBUSY.bit.ENABLE);
|
||||
}
|
||||
else {
|
||||
Tc * const tc = TimerConfig[timer_num].pTc;
|
||||
|
||||
// Enable interrupt on RC compare
|
||||
tc->COUNT32.INTENSET.reg = TC_INTENCLR_OVF; // enable overflow interrupt
|
||||
// Disable timer interrupt
|
||||
tc->COUNT32.INTENCLR.reg = TC_INTENCLR_OVF; // disable overflow interrupt
|
||||
|
||||
// TCn clock setup
|
||||
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;
|
||||
SYNC(GCLK->PCHCTRL[clockID].bit.CHEN);
|
||||
GCLK->PCHCTRL[clockID].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN; // 120MHz startup code programmed
|
||||
SYNC(!GCLK->PCHCTRL[clockID].bit.CHEN);
|
||||
|
||||
// Stop timer, just in case, to be able to reconfigure it
|
||||
tc->COUNT32.CTRLA.bit.ENABLE = false;
|
||||
SYNC(tc->COUNT32.SYNCBUSY.bit.ENABLE);
|
||||
|
||||
// Reset timer
|
||||
tc->COUNT32.CTRLA.bit.SWRST = true;
|
||||
SYNC(tc->COUNT32.SYNCBUSY.bit.SWRST);
|
||||
|
||||
// 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.CTRLA.reg = TC_CTRLA_MODE_COUNT32 | TC_CTRLA_PRESCALER_DIV1;
|
||||
tc->COUNT32.CTRLBSET.reg = TC_CTRLBCLR_DIR;
|
||||
SYNC(tc->COUNT32.SYNCBUSY.bit.CTRLB);
|
||||
|
||||
// Set compare value
|
||||
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
|
||||
tc->COUNT32.CTRLA.bit.ENABLE = true;
|
||||
SYNC(tc->COUNT32.SYNCBUSY.bit.ENABLE);
|
||||
}
|
||||
|
||||
// Finally, enable IRQ
|
||||
NVIC_SetPriority(irq, TimerConfig[timer_num].priority);
|
||||
NVIC_EnableIRQ(irq);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
// --------------------------------------------------------------------------
|
||||
// Defines
|
||||
// --------------------------------------------------------------------------
|
||||
#define RTC_TIMER_NUM 8 // This is not a TC but a RTC
|
||||
|
||||
typedef uint32_t hal_timer_t;
|
||||
#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 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 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 PULSE_TIMER_RATE STEPPER_TIMER_RATE
|
||||
|
@ -62,14 +63,21 @@ typedef uint32_t hal_timer_t;
|
|||
#if STEP_TIMER_NUM != PULSE_TIMER_NUM
|
||||
#define HAL_PULSE_TIMER_ISR() TC_HANDLER(PULSE_TIMER_NUM)
|
||||
#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
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
typedef struct {
|
||||
Tc *pTimer;
|
||||
union {
|
||||
Tc *pTc;
|
||||
Rtc *pRtc;
|
||||
};
|
||||
IRQn_Type IRQ_Id;
|
||||
uint8_t priority;
|
||||
} tTimerConfig;
|
||||
|
@ -87,17 +95,20 @@ extern const tTimerConfig TimerConfig[];
|
|||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
SYNC(tc->COUNT32.SYNCBUSY.bit.CTRLB || tc->COUNT32.SYNCBUSY.bit.COUNT);
|
||||
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);
|
||||
|
||||
FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
|
||||
Tc * const tc = TimerConfig[timer_num].pTimer;
|
||||
// Clear interrupt flag
|
||||
tc->COUNT32.INTFLAG.reg = TC_INTFLAG_OVF;
|
||||
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
|
||||
tc->COUNT32.INTFLAG.reg = TC_INTFLAG_OVF;
|
||||
}
|
||||
}
|
||||
|
||||
#define HAL_timer_isr_epilogue(timer_num)
|
||||
|
|
Loading…
Reference in a new issue