@@ -51,6 +51,7 @@ void SystemInit( void )
5151 /* Turn on the digital interface clock */
5252 PM -> APBAMASK .reg |= PM_APBAMASK_GCLK ;
5353
54+ #if !defined(CRYSTALLESS )
5455 /* ----------------------------------------------------------------------------------------------
5556 * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator)
5657 */
@@ -193,6 +194,118 @@ void SystemInit( void )
193194// GCLK_GENCTRL_OE | // Output clock to a pin for tests
194195 GCLK_GENCTRL_GENEN ;
195196
197+ #else
198+
199+
200+ /* Set OSC8M prescalar to divide by 1, now gclk0 is @ 8mhz */
201+ SYSCTRL -> OSC8M .bit .PRESC = 0 ;
202+
203+ /* ----------------------------------------------------------------------------------------------
204+ * 1) Enable OSC32K clock (Internal 32.768Hz oscillator)
205+ */
206+
207+ uint32_t calib = (* ((uint32_t * ) SYSCTRL_FUSES_OSC32K_ADDR ) & SYSCTRL_FUSES_OSC32K_Msk ) >> SYSCTRL_FUSES_OSC32K_Pos ;
208+
209+ SYSCTRL -> OSC32K .reg = SYSCTRL_OSC32K_CALIB (calib ) | SYSCTRL_OSC32K_STARTUP ( 0x6u ) | // cf table 15.10 of product datasheet in chapter 15.8.6
210+ SYSCTRL_OSC32K_EN32K | SYSCTRL_OSC32K_ENABLE ;
211+
212+ while ( (SYSCTRL -> PCLKSR .reg & SYSCTRL_PCLKSR_OSC32KRDY ) == 0 ); // Wait for oscillator stabilization
213+
214+ /* ----------------------------------------------------------------------------------------------
215+ * 2) Put OSC32K as source of Generic Clock Generator 1
216+ */
217+
218+ GCLK_GENCTRL_Type genctrl = {0 };
219+ uint32_t temp_genctrl ;
220+
221+ GCLK -> GENCTRL .bit .ID = 1 ; // Read GENERATOR_ID - GCLK_GEN_1
222+
223+ while (GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY ); // wait for data to be ready
224+
225+ temp_genctrl = GCLK -> GENCTRL .reg ;
226+ genctrl .bit .SRC = GCLK_GENCTRL_SRC_OSC32K_Val ; // gclk 1 is now = osc32k
227+ genctrl .bit .GENEN = 1 ;
228+ genctrl .bit .RUNSTDBY = 0 ;
229+ genctrl .bit .OE = 1 ; // output on GCLK_IO[1] pin for debugging
230+
231+ GCLK -> GENCTRL .reg = (genctrl .reg | temp_genctrl ); // set it!
232+
233+ while (GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY );
234+
235+
236+ /* Configure OSC8M as source for GCLK_GEN 2 */
237+ GCLK -> GENCTRL .bit .ID = 2 ; // Read GENERATOR_ID - GCLK_GEN_2
238+
239+ while (GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY ); // wait for data to be ready
240+
241+ temp_genctrl = GCLK -> GENCTRL .reg ;
242+ genctrl .bit .SRC = GCLK_GENCTRL_SRC_OSC8M_Val ; // gclk 2 is now = osc8m
243+ genctrl .bit .GENEN = 1 ;
244+ genctrl .bit .RUNSTDBY = 0 ;
245+ genctrl .bit .OE = 1 ; // output on GCLK_IO[2] pin for debugging
246+ GCLK -> GENCTRL .reg = (genctrl .reg | temp_genctrl ); // set it!
247+
248+ while (GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY );
249+
250+
251+ #define NVM_SW_CALIB_DFLL48M_COARSE_VAL 58
252+ #define NVM_SW_CALIB_DFLL48M_FINE_VAL 64
253+
254+ // Turn on DFLL
255+ SYSCTRL_DFLLCTRL_Type dfllctrl_conf = {0 };
256+ SYSCTRL_DFLLVAL_Type dfllval_conf = {0 };
257+ uint32_t coarse = ( * ((uint32_t * )(NVMCTRL_OTP4 )
258+ + (NVM_SW_CALIB_DFLL48M_COARSE_VAL / 32 ))
259+ >> (NVM_SW_CALIB_DFLL48M_COARSE_VAL % 32 ))
260+ & ((1 << 6 ) - 1 );
261+ if (coarse == 0x3f ) {
262+ coarse = 0x1f ;
263+ }
264+ uint32_t fine = ( * ((uint32_t * )(NVMCTRL_OTP4 )
265+ + (NVM_SW_CALIB_DFLL48M_FINE_VAL / 32 ))
266+ >> (NVM_SW_CALIB_DFLL48M_FINE_VAL % 32 ))
267+ & ((1 << 10 ) - 1 );
268+ if (fine == 0x3ff ) {
269+ fine = 0x1ff ;
270+ }
271+ dfllval_conf .bit .COARSE = coarse ;
272+ dfllval_conf .bit .FINE = fine ;
273+ dfllctrl_conf .bit .USBCRM = 1 ; // usb correction
274+ dfllctrl_conf .bit .BPLCKC = 0 ;
275+ dfllctrl_conf .bit .QLDIS = 0 ;
276+ dfllctrl_conf .bit .CCDIS = 1 ;
277+ dfllctrl_conf .bit .ENABLE = 1 ;
278+
279+ SYSCTRL -> DFLLCTRL .bit .ONDEMAND = 0 ;
280+ while (!(SYSCTRL -> PCLKSR .reg & SYSCTRL_PCLKSR_DFLLRDY ));
281+ SYSCTRL -> DFLLMUL .reg = 48000 ;
282+ SYSCTRL -> DFLLVAL .reg = dfllval_conf .reg ;
283+ SYSCTRL -> DFLLCTRL .reg = dfllctrl_conf .reg ;
284+
285+ //
286+ GCLK_CLKCTRL_Type clkctrl = {0 };
287+ uint16_t temp ;
288+ GCLK -> CLKCTRL .bit .ID = 2 ; // GCLK_ID - DFLL48M Reference
289+ temp = GCLK -> CLKCTRL .reg ;
290+ clkctrl .bit .CLKEN = 1 ;
291+ clkctrl .bit .WRTLOCK = 0 ;
292+ clkctrl .bit .GEN = GCLK_CLKCTRL_GEN_GCLK0_Val ;
293+ GCLK -> CLKCTRL .reg = (clkctrl .reg | temp );
294+
295+ // Configure DFLL48M as source for GCLK_GEN 0
296+ GCLK -> GENCTRL .bit .ID = 0 ; // GENERATOR_ID - GCLK_GEN_0
297+ while (GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY );
298+ temp_genctrl = GCLK -> GENCTRL .reg ;
299+ genctrl .bit .SRC = GCLK_GENCTRL_SRC_DFLL48M_Val ;
300+ genctrl .bit .GENEN = 1 ;
301+ genctrl .bit .RUNSTDBY = 0 ;
302+ genctrl .bit .OE = 1 ;
303+ GCLK -> GENCTRL .reg = (genctrl .reg | temp_genctrl );
304+ while (GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY );
305+
306+
307+ #endif
308+
196309 while ( GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY )
197310 {
198311 /* Wait for synchronization */
0 commit comments