Browse Source

Move SAMD51 Temperature timer to RTC (#16868)

Giuliano Zaro 4 years ago
parent
commit
199a1ba0e5
No account linked to committer's email address
2 changed files with 97 additions and 47 deletions
  1. 69
    37
      Marlin/src/HAL/HAL_SAMD51/timers.cpp
  2. 28
    10
      Marlin/src/HAL/HAL_SAMD51/timers.h

+ 69
- 37
Marlin/src/HAL/HAL_SAMD51/timers.cpp View File

@@ -37,15 +37,16 @@
37 37
 // Private Variables
38 38
 // --------------------------------------------------------------------------
39 39
 
40
-const tTimerConfig TimerConfig[NUM_HARDWARE_TIMERS] = {
41
-  { TC0, TC0_IRQn, TC_PRIORITY(0) },
42
-  { TC1, TC1_IRQn, TC_PRIORITY(1) },
43
-  { TC2, TC2_IRQn, TC_PRIORITY(2) },  // Reserved by framework tone function
44
-  { TC3, TC3_IRQn, TC_PRIORITY(3) },  // Reserved by servo library
45
-  { TC4, TC4_IRQn, TC_PRIORITY(4) },
46
-  { TC5, TC5_IRQn, TC_PRIORITY(5) },
47
-  { TC6, TC6_IRQn, TC_PRIORITY(6) },
48
-  { TC7, TC7_IRQn, TC_PRIORITY(7) }
40
+const tTimerConfig TimerConfig[NUM_HARDWARE_TIMERS+1] = {
41
+  { {.pTc=TC0},  TC0_IRQn, TC_PRIORITY(0) },  // 0 - stepper
42
+  { {.pTc=TC1},  TC1_IRQn, TC_PRIORITY(1) },  // 1 - stepper (needed by 32 bit timers)
43
+  { {.pTc=TC2},  TC2_IRQn, TC_PRIORITY(2) },  // 2 - tone (framework)
44
+  { {.pTc=TC3},  TC3_IRQn, TC_PRIORITY(3) },  // 3 - servo
45
+  { {.pTc=TC4},  TC4_IRQn, TC_PRIORITY(4) },
46
+  { {.pTc=TC5},  TC5_IRQn, TC_PRIORITY(5) },
47
+  { {.pTc=TC6},  TC6_IRQn, TC_PRIORITY(6) },
48
+  { {.pTc=TC7},  TC7_IRQn, TC_PRIORITY(7) },
49
+  { {.pRtc=RTC}, RTC_IRQn, TC_PRIORITY(8) }   // 8 - temperature
49 50
 };
50 51
 
51 52
 // --------------------------------------------------------------------------
@@ -66,49 +67,80 @@ FORCE_INLINE void Disable_Irq(IRQn_Type irq) {
66 67
 // --------------------------------------------------------------------------
67 68
 
68 69
 void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
69
-  Tc * const tc = TimerConfig[timer_num].pTimer;
70 70
   IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
71 71
 
72 72
   // Disable interrupt, just in case it was already enabled
73 73
   Disable_Irq(irq);
74 74
 
75
-  // Disable timer interrupt
76
-  tc->COUNT32.INTENCLR.reg = TC_INTENCLR_OVF; // disable overflow interrupt
75
+  if (timer_num == RTC_TIMER_NUM) {
76
+    Rtc * const rtc = TimerConfig[timer_num].pRtc;
77 77
 
78
-  // TCn clock setup
79
-  const uint8_t clockID = GCLK_CLKCTRL_IDs[TCC_INST_NUM + timer_num];
80
-  GCLK->PCHCTRL[clockID].bit.CHEN = false;
81
-  SYNC(GCLK->PCHCTRL[clockID].bit.CHEN);
82
-  GCLK->PCHCTRL[clockID].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN;   // 120MHz startup code programmed
83
-  SYNC(!GCLK->PCHCTRL[clockID].bit.CHEN);
78
+    // Disable timer interrupt
79
+    rtc->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP0;
84 80
 
85
-  // Stop timer, just in case, to be able to reconfigure it
86
-  tc->COUNT32.CTRLA.bit.ENABLE = false;
87
-  SYNC(tc->COUNT32.SYNCBUSY.bit.ENABLE);
81
+    // RTC clock setup
82
+    OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC32K;  // External 32.768KHz oscillator
88 83
 
89
-  // Reset timer
90
-  tc->COUNT32.CTRLA.bit.SWRST = true;
91
-  SYNC(tc->COUNT32.SYNCBUSY.bit.SWRST);
84
+    // Stop timer, just in case, to be able to reconfigure it
85
+    rtc->MODE0.CTRLA.bit.ENABLE = false;
86
+    SYNC(rtc->MODE0.SYNCBUSY.bit.ENABLE);
92 87
 
93
-  NVIC_SetPriority(irq, TimerConfig[timer_num].priority);
88
+    // Mode, reset counter on match
89
+    rtc->MODE0.CTRLA.reg = RTC_MODE0_CTRLA_MODE_COUNT32 | RTC_MODE0_CTRLA_MATCHCLR;
90
+
91
+    // Set compare value
92
+    rtc->MODE0.COMP[0].reg = (32768 + frequency / 2) / frequency;
93
+    SYNC(rtc->MODE0.SYNCBUSY.bit.COMP0);
94
+
95
+    // Enable interrupt on compare
96
+    rtc->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0;    // reset pending interrupt
97
+    rtc->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_CMP0;  // enable compare 0 interrupt
98
+
99
+    // And start timer
100
+    rtc->MODE0.CTRLA.bit.ENABLE = true;
101
+    SYNC(rtc->MODE0.SYNCBUSY.bit.ENABLE);
102
+  }
103
+  else {
104
+    Tc * const tc = TimerConfig[timer_num].pTc;
105
+
106
+    // Disable timer interrupt
107
+    tc->COUNT32.INTENCLR.reg = TC_INTENCLR_OVF; // disable overflow interrupt
94 108
 
95
-  // Wave mode, reset counter on overflow on 0 (I use count down to prevent double buffer use)
96
-  tc->COUNT32.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ;
97
-  tc->COUNT32.CTRLA.reg = TC_CTRLA_MODE_COUNT32 | TC_CTRLA_PRESCALER_DIV1;
98
-  tc->COUNT32.CTRLBSET.reg = TC_CTRLBCLR_DIR;
99
-  SYNC(tc->COUNT32.SYNCBUSY.bit.CTRLB);
109
+    // TCn clock setup
110
+    const uint8_t clockID = GCLK_CLKCTRL_IDs[TCC_INST_NUM + timer_num];   // TC clock are preceeded by TCC ones
111
+    GCLK->PCHCTRL[clockID].bit.CHEN = false;
112
+    SYNC(GCLK->PCHCTRL[clockID].bit.CHEN);
113
+    GCLK->PCHCTRL[clockID].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN;   // 120MHz startup code programmed
114
+    SYNC(!GCLK->PCHCTRL[clockID].bit.CHEN);
100 115
 
101
-  // Set compare value
102
-  tc->COUNT32.COUNT.reg = tc->COUNT32.CC[0].reg = (HAL_TIMER_RATE) / frequency;
116
+    // Stop timer, just in case, to be able to reconfigure it
117
+    tc->COUNT32.CTRLA.bit.ENABLE = false;
118
+    SYNC(tc->COUNT32.SYNCBUSY.bit.ENABLE);
103 119
 
104
-  // And start timer
105
-  tc->COUNT32.CTRLA.bit.ENABLE = true;
106
-  SYNC(tc->COUNT32.SYNCBUSY.bit.ENABLE);
120
+    // Reset timer
121
+    tc->COUNT32.CTRLA.bit.SWRST = true;
122
+    SYNC(tc->COUNT32.SYNCBUSY.bit.SWRST);
107 123
 
108
-  // Enable interrupt on RC compare
109
-  tc->COUNT32.INTENSET.reg = TC_INTENCLR_OVF; // enable overflow interrupt
124
+    // Wave mode, reset counter on overflow on 0 (I use count down to prevent double buffer use)
125
+    tc->COUNT32.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ;
126
+    tc->COUNT32.CTRLA.reg = TC_CTRLA_MODE_COUNT32 | TC_CTRLA_PRESCALER_DIV1;
127
+    tc->COUNT32.CTRLBSET.reg = TC_CTRLBCLR_DIR;
128
+    SYNC(tc->COUNT32.SYNCBUSY.bit.CTRLB);
129
+
130
+    // Set compare value
131
+    tc->COUNT32.COUNT.reg = tc->COUNT32.CC[0].reg = (HAL_TIMER_RATE) / frequency;
132
+
133
+    // Enable interrupt on compare
134
+    tc->COUNT32.INTFLAG.reg = TC_INTFLAG_OVF;   // reset pending interrupt
135
+    tc->COUNT32.INTENSET.reg = TC_INTENSET_OVF; // enable overflow interrupt
136
+
137
+    // And start timer
138
+    tc->COUNT32.CTRLA.bit.ENABLE = true;
139
+    SYNC(tc->COUNT32.SYNCBUSY.bit.ENABLE);
140
+  }
110 141
 
111 142
   // Finally, enable IRQ
143
+  NVIC_SetPriority(irq, TimerConfig[timer_num].priority);
112 144
   NVIC_EnableIRQ(irq);
113 145
 }
114 146
 

+ 28
- 10
Marlin/src/HAL/HAL_SAMD51/timers.h View File

@@ -25,6 +25,7 @@
25 25
 // --------------------------------------------------------------------------
26 26
 // Defines
27 27
 // --------------------------------------------------------------------------
28
+#define RTC_TIMER_NUM       8   // This is not a TC but a RTC
28 29
 
29 30
 typedef uint32_t hal_timer_t;
30 31
 #define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
@@ -33,12 +34,12 @@ typedef uint32_t hal_timer_t;
33 34
 
34 35
 #define STEP_TIMER_NUM      0  // index of timer to use for stepper (also +1 for 32bits counter)
35 36
 #define PULSE_TIMER_NUM     STEP_TIMER_NUM
36
-#define TEMP_TIMER_NUM      4  // index of timer to use for temperature (also +1 for 32bits counter)
37
+#define TEMP_TIMER_NUM      RTC_TIMER_NUM  // index of timer to use for temperature
37 38
 
38 39
 #define TEMP_TIMER_FREQUENCY   1000 // temperature interrupt frequency
39 40
 
40 41
 #define STEPPER_TIMER_RATE          HAL_TIMER_RATE   // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
41
-#define STEPPER_TIMER_TICKS_PER_US  ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
42
+#define STEPPER_TIMER_TICKS_PER_US  (STEPPER_TIMER_RATE / 1000000) // stepper timer ticks per µs
42 43
 #define STEPPER_TIMER_PRESCALE      (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
43 44
 
44 45
 #define PULSE_TIMER_RATE          STEPPER_TIMER_RATE
@@ -62,14 +63,21 @@ typedef uint32_t hal_timer_t;
62 63
 #if STEP_TIMER_NUM != PULSE_TIMER_NUM
63 64
   #define HAL_PULSE_TIMER_ISR()  TC_HANDLER(PULSE_TIMER_NUM)
64 65
 #endif
65
-#define HAL_TEMP_TIMER_ISR()  TC_HANDLER(TEMP_TIMER_NUM)
66
+#if TEMP_TIMER_NUM == RTC_TIMER_NUM
67
+  #define HAL_TEMP_TIMER_ISR()  void RTC_Handler()
68
+#else
69
+  #define HAL_TEMP_TIMER_ISR()  TC_HANDLER(TEMP_TIMER_NUM)
70
+#endif
66 71
 
67 72
 // --------------------------------------------------------------------------
68 73
 // Types
69 74
 // --------------------------------------------------------------------------
70 75
 
71 76
 typedef struct {
72
-  Tc          *pTimer;
77
+  union {
78
+    Tc  *pTc;
79
+    Rtc *pRtc;
80
+  };
73 81
   IRQn_Type   IRQ_Id;
74 82
   uint8_t     priority;
75 83
 } tTimerConfig;
@@ -87,17 +95,20 @@ extern const tTimerConfig TimerConfig[];
87 95
 void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
88 96
 
89 97
 FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) {
90
-  Tc * const tc = TimerConfig[timer_num].pTimer;
98
+  // Should never be called with timer RTC_TIMER_NUM
99
+  Tc * const tc = TimerConfig[timer_num].pTc;
91 100
   tc->COUNT32.CC[0].reg = HAL_TIMER_TYPE_MAX - compare;
92 101
 }
93 102
 
94 103
 FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
95
-  Tc * const tc = TimerConfig[timer_num].pTimer;
104
+  // Should never be called with timer RTC_TIMER_NUM
105
+  Tc * const tc = TimerConfig[timer_num].pTc;
96 106
   return (hal_timer_t)(HAL_TIMER_TYPE_MAX - tc->COUNT32.CC[0].reg);
97 107
 }
98 108
 
99 109
 FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
100
-  Tc * const tc = TimerConfig[timer_num].pTimer;
110
+  // Should never be called with timer RTC_TIMER_NUM
111
+  Tc * const tc = TimerConfig[timer_num].pTc;
101 112
   tc->COUNT32.CTRLBSET.reg = TC_CTRLBCLR_CMD_READSYNC;
102 113
   SYNC(tc->COUNT32.SYNCBUSY.bit.CTRLB || tc->COUNT32.SYNCBUSY.bit.COUNT);
103 114
   return HAL_TIMER_TYPE_MAX - tc->COUNT32.COUNT.reg;
@@ -108,9 +119,16 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num);
108 119
 bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
109 120
 
110 121
 FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
111
-  Tc * const tc = TimerConfig[timer_num].pTimer;
112
-  // Clear interrupt flag
113
-  tc->COUNT32.INTFLAG.reg = TC_INTFLAG_OVF;
122
+  if (timer_num == RTC_TIMER_NUM) {
123
+    Rtc * const rtc = TimerConfig[timer_num].pRtc;
124
+    // Clear interrupt flag
125
+    rtc->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0;
126
+  }
127
+  else {
128
+    Tc * const tc = TimerConfig[timer_num].pTc;
129
+    // Clear interrupt flag
130
+    tc->COUNT32.INTFLAG.reg = TC_INTFLAG_OVF;
131
+  }
114 132
 }
115 133
 
116 134
 #define HAL_timer_isr_epilogue(timer_num)

Loading…
Cancel
Save