@@ -52,7 +52,7 @@ uint32_t get_peripheral_freq(void) {
52
52
53
53
void set_cpu_freq (uint32_t cpu_freq_arg ) {
54
54
55
- // Set 1 waitstate to be safe
55
+ // Set 1 wait state to be safe
56
56
NVMCTRL -> CTRLB .reg = NVMCTRL_CTRLB_MANW | NVMCTRL_CTRLB_RWS (1 );
57
57
58
58
int div = MAX (DFLL48M_FREQ / cpu_freq_arg , 1 );
@@ -75,7 +75,7 @@ void set_cpu_freq(uint32_t cpu_freq_arg) {
75
75
while (GCLK -> STATUS .bit .SYNCBUSY ) {
76
76
}
77
77
// configure the FDPLL96
78
- // CtrlB: Set the ref ource to GCLK, set the Wakup -Fast Flag.
78
+ // CtrlB: Set the ref source to GCLK, set the Wakeup -Fast Flag.
79
79
SYSCTRL -> DPLLCTRLB .reg = SYSCTRL_DPLLCTRLB_REFCLK_GCLK | SYSCTRL_DPLLCTRLB_WUF ;
80
80
// Set the FDPLL ratio and enable the DPLL.
81
81
int ldr = cpu_freq / FDPLL_REF_FREQ ;
@@ -106,25 +106,36 @@ void set_cpu_freq(uint32_t cpu_freq_arg) {
106
106
while (GCLK -> STATUS .bit .SYNCBUSY ) {
107
107
}
108
108
}
109
- // Set 0 waitstates for slower CPU clock
109
+ // Set 0 wait states for slower CPU clock
110
110
NVMCTRL -> CTRLB .reg = NVMCTRL_CTRLB_MANW | NVMCTRL_CTRLB_RWS (cpu_freq > 24000000 ? 1 : 0 );
111
111
SysTick_Config (cpu_freq / 1000 );
112
112
}
113
113
114
114
void check_usb_recovery_mode (void ) {
115
115
#if !MICROPY_HW_XOSC32K
116
- mp_hal_delay_ms (500 );
117
- // Check USB status. If not connected, switch DFLL48M back to open loop
118
- if (USB -> DEVICE .DeviceEndpoint [0 ].EPCFG .reg == 0 ) {
119
- // Set/keep the open loop mode of the device.
120
- SYSCTRL -> DFLLVAL .reg = dfll48m_calibration ;
121
- SYSCTRL -> DFLLCTRL .reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_ENABLE ;
116
+ // Check USB status for up to 1 second. If not connected,
117
+ // switch DFLL48M back to open loop
118
+ for (int i = 0 ; i < 100 ; i ++ ) {
119
+ if (USB -> DEVICE .DeviceEndpoint [0 ].EPCFG .reg != 0 ) {
120
+ return ;
121
+ }
122
+ mp_hal_delay_ms (10 );
122
123
}
124
+ // Set/keep the open loop mode of the device.
125
+ SYSCTRL -> DFLLVAL .reg = dfll48m_calibration ;
126
+ SYSCTRL -> DFLLCTRL .reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_ENABLE ;
123
127
#endif // MICROPY_HW_XOSC32K
124
128
}
125
129
126
130
// Purpose of the #defines for the clock configuration.
127
131
//
132
+ // The CPU is either driven by the FDPLL96 oscillator for f >= 48MHz,
133
+ // or by the DFLL48M for lower frequencies. The FDPLL96 takes 32768 Hz
134
+ // as reference frequency, supplied through GCLK1.
135
+ //
136
+ // DFLL48M is used for the peripheral clock, e.g. for PWM, UART, SPI, I2C.
137
+ // DFLL48M is either free running, or controlled by the 32kHz crystal, or
138
+ // Synchronized with the USB clock.
128
139
// Both CPU and peripheral devices are clocked by the DFLL48M clock.
129
140
// DFLL48M is either free running, or controlled by the 32kHz crystal, or
130
141
// Synchronized with the USB clock.
@@ -136,18 +147,18 @@ void check_usb_recovery_mode(void) {
136
147
// The crystal is used, unless MICROPY_HW_MCU_OSC32KULP is set.
137
148
// In that case GCLK1 (and the CPU clock) is driven by the 32K Low power oscillator.
138
149
// The reason for offering this option is a design flaw of the Adafruit
139
- // Feather boards, where the RGB Led and Debug signals interfere with the
150
+ // Feather boards, where the RGB LED and Debug signals interfere with the
140
151
// crystal, causing the CPU to fail if it is driven by the crystal.
141
152
//
142
153
// If MICROPY_HW_XOSC32K = 0, the 32kHz signal for GCLK1 (and the CPU) is
143
154
// created by dividing the 48MHz clock of DFLL48M, but not used otherwise.
144
155
//
145
156
// If MICROPY_HW_DFLL_USB_SYNC = 0, the DFLL48M oscillator is free running using
146
157
// the pre-configured trim values. In that mode, the peripheral clock is
147
- // not exactly 48Mhz and has a substantional temperature drift.
158
+ // not exactly 48Mhz and has a substitutional temperature drift.
148
159
//
149
160
// If MICROPY_HW_DFLL_USB_SYNC = 1, the DFLL48 is synchronized with the 1 kHz USB sync
150
- // signal. If after boot there is no USB sync within 500ms , the configuration falls
161
+ // signal. If after boot there is no USB sync within 1000 ms , the configuration falls
151
162
// back to a free running 48Mhz oscillator.
152
163
//
153
164
// In all modes, the 48MHz signal has a substantial jitter, largest when
@@ -181,7 +192,7 @@ void init_clocks(uint32_t cpu_freq) {
181
192
NVMCTRL -> CTRLB .bit .RWS = 1 ; // 1 read wait state for 48MHz
182
193
183
194
#if MICROPY_HW_XOSC32K
184
- // Set up OSC32K according datasheet 17.6.3
195
+ // Set up OSC32K according data sheet 17.6.3
185
196
SYSCTRL -> XOSC32K .reg = SYSCTRL_XOSC32K_STARTUP (0x3 ) | SYSCTRL_XOSC32K_EN32K |
186
197
SYSCTRL_XOSC32K_XTALEN ;
187
198
SYSCTRL -> XOSC32K .bit .ENABLE = 1 ;
@@ -211,12 +222,12 @@ void init_clocks(uint32_t cpu_freq) {
211
222
while (GCLK -> STATUS .bit .SYNCBUSY ) {
212
223
}
213
224
214
- // Enable access to the DFLLCTRL reg acc. to Errata 1.2.1
225
+ // Enable access to the DFLLCTRL register according to Errata 1.2.1
215
226
SYSCTRL -> DFLLCTRL .reg = SYSCTRL_DFLLCTRL_ENABLE ;
216
227
while (SYSCTRL -> PCLKSR .bit .DFLLRDY == 0 ) {
217
228
}
218
229
// Step 2: Set the coarse and fine values.
219
- // Get the coarse value from the calib data. In case it is not set,
230
+ // Get the coarse value from the calibration data. In case it is not set,
220
231
// set a midrange value.
221
232
uint32_t coarse = (* ((uint32_t * )FUSES_DFLL48M_COARSE_CAL_ADDR ) & FUSES_DFLL48M_COARSE_CAL_Msk )
222
233
>> FUSES_DFLL48M_COARSE_CAL_Pos ;
0 commit comments