Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move SAMD51 temp timer to RTC #16868

Merged
merged 1 commit into from
Feb 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 69 additions & 37 deletions Marlin/src/HAL/HAL_SAMD51/timers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

// --------------------------------------------------------------------------
Expand All @@ -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;

// 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
tc->COUNT32.INTENCLR.reg = TC_INTENCLR_OVF; // disable overflow interrupt

// 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);
// 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);

// Set compare value
tc->COUNT32.COUNT.reg = tc->COUNT32.CC[0].reg = (HAL_TIMER_RATE) / frequency;
// Stop timer, just in case, to be able to reconfigure it
tc->COUNT32.CTRLA.bit.ENABLE = false;
SYNC(tc->COUNT32.SYNCBUSY.bit.ENABLE);

// And start timer
tc->COUNT32.CTRLA.bit.ENABLE = true;
SYNC(tc->COUNT32.SYNCBUSY.bit.ENABLE);
// Reset timer
tc->COUNT32.CTRLA.bit.SWRST = true;
SYNC(tc->COUNT32.SYNCBUSY.bit.SWRST);

// Enable interrupt on RC compare
tc->COUNT32.INTENSET.reg = TC_INTENCLR_OVF; // enable overflow interrupt
// 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);
}

Expand Down
38 changes: 28 additions & 10 deletions Marlin/src/HAL/HAL_SAMD51/timers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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;
Expand All @@ -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
thinkyhead marked this conversation as resolved.
Show resolved Hide resolved
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;
Expand All @@ -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)