|
@@ -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
|
|