Move SAMD51 Temperature timer to RTC (#16868)

This commit is contained in:
Giuliano Zaro 2020-02-16 05:45:52 +01:00 committed by GitHub
parent 4360142bd1
commit 199a1ba0e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 97 additions and 47 deletions

View file

@ -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,49 +67,80 @@ 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);
// Disable timer interrupt if (timer_num == RTC_TIMER_NUM) {
tc->COUNT32.INTENCLR.reg = TC_INTENCLR_OVF; // disable overflow interrupt Rtc * const rtc = TimerConfig[timer_num].pRtc;
// TCn clock setup // Disable timer interrupt
const uint8_t clockID = GCLK_CLKCTRL_IDs[TCC_INST_NUM + timer_num]; rtc->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP0;
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 // RTC clock setup
tc->COUNT32.CTRLA.bit.ENABLE = false; OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC32K; // External 32.768KHz oscillator
SYNC(tc->COUNT32.SYNCBUSY.bit.ENABLE);
// Reset timer // Stop timer, just in case, to be able to reconfigure it
tc->COUNT32.CTRLA.bit.SWRST = true; rtc->MODE0.CTRLA.bit.ENABLE = false;
SYNC(tc->COUNT32.SYNCBUSY.bit.SWRST); 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) // Set compare value
tc->COUNT32.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ; rtc->MODE0.COMP[0].reg = (32768 + frequency / 2) / frequency;
tc->COUNT32.CTRLA.reg = TC_CTRLA_MODE_COUNT32 | TC_CTRLA_PRESCALER_DIV1; SYNC(rtc->MODE0.SYNCBUSY.bit.COMP0);
tc->COUNT32.CTRLBSET.reg = TC_CTRLBCLR_DIR;
SYNC(tc->COUNT32.SYNCBUSY.bit.CTRLB);
// Set compare value // Enable interrupt on compare
tc->COUNT32.COUNT.reg = tc->COUNT32.CC[0].reg = (HAL_TIMER_RATE) / frequency; 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 // And start timer
tc->COUNT32.CTRLA.bit.ENABLE = true; rtc->MODE0.CTRLA.bit.ENABLE = true;
SYNC(tc->COUNT32.SYNCBUSY.bit.ENABLE); SYNC(rtc->MODE0.SYNCBUSY.bit.ENABLE);
}
else {
Tc * const tc = TimerConfig[timer_num].pTc;
// Enable interrupt on RC compare // Disable timer interrupt
tc->COUNT32.INTENSET.reg = TC_INTENCLR_OVF; // enable overflow 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 // Finally, enable IRQ
NVIC_SetPriority(irq, TimerConfig[timer_num].priority);
NVIC_EnableIRQ(irq); NVIC_EnableIRQ(irq);
} }

View file

@ -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) {
// Clear interrupt flag Rtc * const rtc = TimerConfig[timer_num].pRtc;
tc->COUNT32.INTFLAG.reg = TC_INTFLAG_OVF; // 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) #define HAL_timer_isr_epilogue(timer_num)