Move SAMD51 Temperature timer to RTC (#16868)
This commit is contained in:
		| @@ -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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user