54
54
#endif
55
55
56
56
static frequencyio_frequencyin_obj_t * active_frequencyins [TC_INST_NUM ];
57
- volatile uint8_t reference_tc = 0xff ;
57
+ volatile uint8_t reference_tc ;
58
58
#ifdef SAM_D5X_E5X
59
59
static uint8_t dpll_gclk ;
60
+
61
+ #if !BOARD_HAS_CRYSTAL
62
+ static uint8_t osculp32k_gclk ;
63
+ #endif
64
+
60
65
#endif
61
66
62
- void frequencyin_emergency_cancel_capture (uint8_t index ) {
67
+ void frequencyin_reset (void ) {
68
+ for (uint8_t i = 0 ; i < TC_INST_NUM ; i ++ ) {
69
+ active_frequencyins [i ] = NULL ;
70
+ }
71
+
72
+ reference_tc = 0xff ;
73
+ #ifdef SAM_D5X_E5X
74
+ dpll_gclk = 0xff ;
75
+
76
+ #if !BOARD_HAS_CRYSTAL
77
+ osculp32k_gclk = 0xff ;
78
+ #endif
79
+
80
+ #endif
81
+ }
82
+
83
+ static void frequencyin_emergency_cancel_capture (uint8_t index ) {
63
84
frequencyio_frequencyin_obj_t * self = active_frequencyins [index ];
64
85
65
86
NVIC_DisableIRQ (self -> TC_IRQ );
@@ -93,7 +114,7 @@ void frequencyin_interrupt_handler(uint8_t index) {
93
114
94
115
uint64_t current_ns = common_hal_time_monotonic_ns ();
95
116
96
- for (uint8_t i = 0 ; i <= ( TC_INST_NUM - 1 ) ; i ++ ) {
117
+ for (uint8_t i = 0 ; i < TC_INST_NUM ; i ++ ) {
97
118
if (active_frequencyins [i ] != NULL ) {
98
119
frequencyio_frequencyin_obj_t * self = active_frequencyins [i ];
99
120
Tc * tc = tc_insts [self -> tc_index ];
@@ -143,7 +164,7 @@ void frequencyin_interrupt_handler(uint8_t index) {
143
164
ref_tc -> COUNT16 .INTFLAG .reg |= TC_INTFLAG_OVF ;
144
165
}
145
166
146
- void frequencyin_reference_tc_init () {
167
+ static void frequencyin_reference_tc_init (void ) {
147
168
if (reference_tc == 0xff ) {
148
169
return ;
149
170
}
@@ -154,9 +175,6 @@ void frequencyin_reference_tc_init() {
154
175
// use the DPLL we setup so that the reference_tc and freqin_tc(s)
155
176
// are using the same clock frequency.
156
177
#ifdef SAM_D5X_E5X
157
- if (dpll_gclk == 0xff ) {
158
- frequencyin_samd51_start_dpll ();
159
- }
160
178
set_timer_handler (true, reference_tc , TC_HANDLER_FREQUENCYIN );
161
179
turn_on_clocks (true, reference_tc , dpll_gclk );
162
180
#endif
@@ -178,15 +196,15 @@ void frequencyin_reference_tc_init() {
178
196
#endif
179
197
}
180
198
181
- bool frequencyin_reference_tc_enabled () {
199
+ static bool frequencyin_reference_tc_enabled (void ) {
182
200
if (reference_tc == 0xff ) {
183
201
return false;
184
202
}
185
203
Tc * tc = tc_insts [reference_tc ];
186
204
return tc -> COUNT16 .CTRLA .bit .ENABLE ;
187
205
}
188
206
189
- void frequencyin_reference_tc_enable (bool enable ) {
207
+ static void frequencyin_reference_tc_enable (bool enable ) {
190
208
if (reference_tc == 0xff ) {
191
209
return ;
192
210
}
@@ -195,56 +213,69 @@ void frequencyin_reference_tc_enable(bool enable) {
195
213
}
196
214
197
215
#ifdef SAM_D5X_E5X
198
- void frequencyin_samd51_start_dpll () {
216
+ static bool frequencyin_samd51_start_dpll (void ) {
199
217
if (clock_get_enabled (0 , GCLK_SOURCE_DPLL1 )) {
200
- return ;
218
+ return true ;
201
219
}
202
220
203
- uint8_t free_gclk = find_free_gclk (1 );
204
- if (free_gclk == 0xff ) {
205
- dpll_gclk = 0xff ;
206
- return ;
221
+ dpll_gclk = find_free_gclk (1 );
222
+ if (dpll_gclk == 0xff ) {
223
+ return false;
207
224
}
208
225
209
- GCLK -> PCHCTRL [OSCCTRL_GCLK_ID_FDPLL1 ].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN (free_gclk );
210
226
// TC4-7 can only have a max of 100MHz source
211
227
// DPLL1 frequency equation with [X]OSC32K as source: 98.304MHz = 32768(2999 + 1 + 0/32)
212
228
// Will also enable the Lock Bypass due to low-frequency sources causing DPLL unlocks
213
229
// as outlined in the Errata (1.12.1)
214
230
OSCCTRL -> Dpll [1 ].DPLLRATIO .reg = OSCCTRL_DPLLRATIO_LDRFRAC (0 ) | OSCCTRL_DPLLRATIO_LDR (2999 );
231
+
215
232
#if BOARD_HAS_CRYSTAL
216
- // we can use XOSC32K directly as the source
217
- OSC32KCTRL -> XOSC32K . bit . EN32K = 1 ;
218
- OSCCTRL -> Dpll [ 1 ]. DPLLCTRLB . reg = OSCCTRL_DPLLCTRLB_REFCLK (1 ) | OSCCTRL_DPLLCTRLB_LBYPASS ;
233
+ // we can use XOSC32K directly as the source. It has already been initialized in clocks.c
234
+ OSCCTRL -> Dpll [ 1 ]. DPLLCTRLB . reg =
235
+ OSCCTRL_DPLLCTRLB_REFCLK (OSCCTRL_DPLLCTRLB_REFCLK_XOSC32_Val ) | OSCCTRL_DPLLCTRLB_LBYPASS ;
219
236
#else
220
- // can't use OSCULP32K directly; need to setup a GCLK as a reference,
221
- // which must be done in samd/clocks.c to avoid waiting for sync
222
- return ;
223
- //OSC32KCTRL->OSCULP32K.bit.EN32K = 1;
224
- //OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK(0);
237
+ // We can't use OSCULP32K directly. Set up a GCLK controlled by it
238
+ // Then use that GCLK as the reference oscillator for the DPLL.
239
+ osculp32k_gclk = find_free_gclk (1 );
240
+ if (osculp32k_gclk == 0xff ) {
241
+ return false;
242
+ }
243
+ enable_clock_generator (osculp32k_gclk , GCLK_GENCTRL_SRC_OSCULP32K_Val , 1 );
244
+ GCLK -> PCHCTRL [OSCCTRL_GCLK_ID_FDPLL1 ].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN (OSCCTRL_GCLK_ID_FDPLL1 );
245
+ OSCCTRL -> Dpll [1 ].DPLLCTRLB .reg =
246
+ OSCCTRL_DPLLCTRLB_REFCLK (OSCCTRL_DPLLCTRLB_REFCLK_GCLK_Val ) | OSCCTRL_DPLLCTRLB_LBYPASS ;
225
247
#endif
226
- OSCCTRL -> Dpll [1 ].DPLLCTRLA .reg = OSCCTRL_DPLLCTRLA_ENABLE ;
227
248
249
+ OSCCTRL -> Dpll [1 ].DPLLCTRLA .reg = OSCCTRL_DPLLCTRLA_ENABLE ;
228
250
while (!(OSCCTRL -> Dpll [1 ].DPLLSTATUS .bit .LOCK || OSCCTRL -> Dpll [1 ].DPLLSTATUS .bit .CLKRDY )) {}
229
- enable_clock_generator (free_gclk , GCLK_GENCTRL_SRC_DPLL1_Val , 1 );
230
- dpll_gclk = free_gclk ;
251
+
252
+ enable_clock_generator (dpll_gclk , GCLK_GENCTRL_SRC_DPLL1_Val , 1 );
253
+ return true;
231
254
}
232
255
233
- void frequencyin_samd51_stop_dpll () {
256
+ static void frequencyin_samd51_stop_dpll (void ) {
234
257
if (!clock_get_enabled (0 , GCLK_SOURCE_DPLL1 )) {
235
258
return ;
236
259
}
237
260
238
- disable_clock_generator (dpll_gclk );
261
+ if (dpll_gclk != 0xff ) {
262
+ disable_clock_generator (dpll_gclk );
263
+ dpll_gclk = 0xff ;
264
+ }
265
+
266
+ #if !BOARD_HAS_CRYSTAL
267
+ if (osculp32k_gclk != 0xff ) {
268
+ disable_clock_generator (osculp32k_gclk );
269
+ osculp32k_gclk = 0xff ;
270
+ }
271
+ #endif
239
272
240
273
GCLK -> PCHCTRL [OSCCTRL_GCLK_ID_FDPLL1 ].reg = 0 ;
241
274
OSCCTRL -> Dpll [1 ].DPLLCTRLA .reg = 0 ;
242
275
OSCCTRL -> Dpll [1 ].DPLLRATIO .reg = 0 ;
243
276
OSCCTRL -> Dpll [1 ].DPLLCTRLB .reg = 0 ;
244
-
245
277
while (OSCCTRL -> Dpll [1 ].DPLLSYNCBUSY .bit .ENABLE ) {
246
278
}
247
- dpll_gclk = 0xff ;
248
279
}
249
280
#endif
250
281
@@ -421,7 +452,7 @@ void common_hal_frequencyio_frequencyin_deinit(frequencyio_frequencyin_obj_t* se
421
452
self -> pin = NO_PIN ;
422
453
423
454
bool check_active = false;
424
- for (uint8_t i = 0 ; i <= ( TC_INST_NUM - 1 ) ; i ++ ) {
455
+ for (uint8_t i = 0 ; i < TC_INST_NUM ; i ++ ) {
425
456
if (active_frequencyins [i ] != NULL ) {
426
457
check_active = true;
427
458
}
0 commit comments