4444
4545void board_init (void )
4646{
47+
48+
49+ #if !defined(CRYSTALLESS )
50+
4751 /* Set 1 Flash Wait State for 48MHz, cf tables 20.9 and 35.27 in SAMD21 Datasheet */
4852 NVMCTRL -> CTRLB .bit .RWS = NVMCTRL_CTRLB_RWS_HALF_Val ;
4953
5054 /* Turn on the digital interface clock */
5155 PM -> APBAMASK .reg |= PM_APBAMASK_GCLK ;
5256
57+
5358 /* ----------------------------------------------------------------------------------------------
5459 * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator)
5560 */
@@ -86,7 +91,7 @@ void board_init(void)
8691 /* Write Generic Clock Generator 1 configuration */
8792 GCLK -> GENCTRL .reg = GCLK_GENCTRL_ID ( GENERIC_CLOCK_GENERATOR_XOSC32K ) | // Generic Clock Generator 1
8893 GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator
89- // GCLK_GENCTRL_OE | // Output clock to a pin for tests
94+ // GCLK_GENCTRL_OE | // Output clock to a pin for tests
9095 GCLK_GENCTRL_GENEN ;
9196
9297 while ( GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY )
@@ -175,29 +180,6 @@ void board_init(void)
175180 /* Wait for synchronization */
176181 }
177182
178- #if 0
179- /* ----------------------------------------------------------------------------------------------
180- * 6) Modify PRESCaler value of OSC8M to have 8MHz
181- */
182- SYSCTRL -> OSC8M .bit .PRESC = SYSCTRL_OSC8M_PRESC_1_Val ;
183- SYSCTRL -> OSC8M .bit .ONDEMAND = 0 ;
184-
185- /* ----------------------------------------------------------------------------------------------
186- * 7) Put OSC8M as source for Generic Clock Generator 3
187- */
188- GCLK -> GENDIV .reg = GCLK_GENDIV_ID ( GENERIC_CLOCK_GENERATOR_OSC8M ); // Generic Clock Generator 3
189-
190- /* Write Generic Clock Generator 3 configuration */
191- GCLK -> GENCTRL .reg = GCLK_GENCTRL_ID ( GENERIC_CLOCK_GENERATOR_OSC8M ) | // Generic Clock Generator 3
192- GCLK_GENCTRL_SRC_OSC8M | // Selected source is RC OSC 8MHz (already enabled at reset)
193- // GCLK_GENCTRL_OE | // Output clock to a pin for tests
194- GCLK_GENCTRL_GENEN ;
195-
196- while ( GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY )
197- {
198- /* Wait for synchronization */
199- }
200- #endif //0
201183
202184 /*
203185 * Now that all system clocks are configured, we can set CPU and APBx BUS clocks.
@@ -207,4 +189,140 @@ void board_init(void)
207189 PM -> APBASEL .reg = PM_APBASEL_APBADIV_DIV1_Val ;
208190 PM -> APBBSEL .reg = PM_APBBSEL_APBBDIV_DIV1_Val ;
209191 PM -> APBCSEL .reg = PM_APBCSEL_APBCDIV_DIV1_Val ;
192+ #else
193+
194+ /////////////////////////////////////////
195+
196+ /* Set 1 Flash Wait State for 48MHz, cf tables 20.9 and 35.27 in SAMD21 Datasheet */
197+ NVMCTRL -> CTRLB .bit .RWS = NVMCTRL_CTRLB_RWS_HALF_Val ;
198+
199+ ////////////////////////////////////////
200+ uint32_t temp_genctrl_config = 0 ;
201+
202+ // ENABLE OUTPUT OF GENCLK 0 on D2 (PA14)
203+ // Write to the PINCFG register to enable the peripheral multiplexer
204+ PORT -> Group [0 ].PINCFG [14 ].reg = 1 ;
205+ // Enable peripheral function H for PA14, refer chapter I/O Multiplexing in the device datasheet
206+ PORT -> Group [0 ].PMUX [7 ].bit .PMUXE = 7 ;
207+
208+ // ENABLE OUTPUT OF GENCLK 1 on D5 (PA15)
209+ // Write to the PINCFG register to enable the peripheral multiplexer
210+ PORT -> Group [0 ].PINCFG [15 ].reg = 1 ;
211+ // Enable peripheral function H for PA15, refer chapter I/O Multiplexing in the device datasheet
212+ PORT -> Group [0 ].PMUX [7 ].bit .PMUXO = 7 ;
213+
214+ // ENABLE OUTPUT OF GENCLK 2 on D11 (PA16) - should be OSC8M @ 8MHz
215+ // Write to the PINCFG register to enable the peripheral multiplexer
216+ PORT -> Group [0 ].PINCFG [16 ].reg = 1 ;
217+ // Enable peripheral function H for PA16, refer chapter I/O Multiplexing in the device datasheet
218+ PORT -> Group [0 ].PMUX [8 ].bit .PMUXE = 7 ;
219+
220+
221+ /////////////////////////////////////////////////
222+
223+ /* Set OSC8M prescalar to divide by 1, now gclk0 is @ 8mhz */
224+ SYSCTRL -> OSC8M .bit .PRESC = 0 ;
225+
226+
227+ /* ----------------------------------------------------------------------------------------------
228+ * 1) Enable OSC32K clock (Internal 32.768Hz oscillator)
229+ */
230+
231+ uint32_t calib = (* ((uint32_t * ) SYSCTRL_FUSES_OSC32K_ADDR ) & SYSCTRL_FUSES_OSC32K_Msk ) >> SYSCTRL_FUSES_OSC32K_Pos ;
232+
233+ SYSCTRL -> OSC32K .reg = SYSCTRL_OSC32K_CALIB (calib ) | SYSCTRL_OSC32K_STARTUP ( 0x6u ) | // cf table 15.10 of product datasheet in chapter 15.8.6
234+ SYSCTRL_OSC32K_EN32K | SYSCTRL_OSC32K_ENABLE ;
235+
236+ while ( (SYSCTRL -> PCLKSR .reg & SYSCTRL_PCLKSR_OSC32KRDY ) == 0 ); // Wait for oscillator stabilization
237+
238+ /* ----------------------------------------------------------------------------------------------
239+ * 2) Put OSC32K as source of Generic Clock Generator 1
240+ */
241+
242+ GCLK_GENCTRL_Type genctrl = {0 };
243+ uint32_t temp_genctrl ;
244+
245+ GCLK -> GENCTRL .bit .ID = 1 ; // Read GENERATOR_ID - GCLK_GEN_1
246+
247+ while (GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY ); // wait for data to be ready
248+
249+ temp_genctrl = GCLK -> GENCTRL .reg ;
250+ genctrl .bit .SRC = GCLK_GENCTRL_SRC_OSC32K_Val ; // gclk 1 is now = osc32k
251+ genctrl .bit .GENEN = 1 ;
252+ genctrl .bit .RUNSTDBY = 0 ;
253+ genctrl .bit .OE = 1 ; // output on GCLK_IO[1] pin for debugging
254+
255+ GCLK -> GENCTRL .reg = (genctrl .reg | temp_genctrl ); // set it!
256+
257+ while (GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY );
258+
259+
260+ /* Configure OSC8M as source for GCLK_GEN 2 */
261+ GCLK -> GENCTRL .bit .ID = 2 ; // Read GENERATOR_ID - GCLK_GEN_2
262+
263+ while (GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY ); // wait for data to be ready
264+
265+ temp_genctrl = GCLK -> GENCTRL .reg ;
266+ genctrl .bit .SRC = GCLK_GENCTRL_SRC_OSC8M_Val ; // gclk 2 is now = osc8m
267+ genctrl .bit .GENEN = 1 ;
268+ genctrl .bit .RUNSTDBY = 0 ;
269+ genctrl .bit .OE = 1 ; // output on GCLK_IO[2] pin for debugging
270+ GCLK -> GENCTRL .reg = (genctrl .reg | temp_genctrl ); // set it!
271+
272+ while (GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY );
273+
274+ // Turn on DFLL
275+ SYSCTRL_DFLLCTRL_Type dfllctrl_conf = {0 };
276+ SYSCTRL_DFLLVAL_Type dfllval_conf = {0 };
277+ uint32_t coarse = ( * ((uint32_t * )(NVMCTRL_OTP4 )
278+ + (NVM_SW_CALIB_DFLL48M_COARSE_VAL / 32 ))
279+ >> (NVM_SW_CALIB_DFLL48M_COARSE_VAL % 32 ))
280+ & ((1 << 6 ) - 1 );
281+ if (coarse == 0x3f ) {
282+ coarse = 0x1f ;
283+ }
284+ uint32_t fine = ( * ((uint32_t * )(NVMCTRL_OTP4 )
285+ + (NVM_SW_CALIB_DFLL48M_FINE_VAL / 32 ))
286+ >> (NVM_SW_CALIB_DFLL48M_FINE_VAL % 32 ))
287+ & ((1 << 10 ) - 1 );
288+ if (fine == 0x3ff ) {
289+ fine = 0x1ff ;
290+ }
291+ dfllval_conf .bit .COARSE = coarse ;
292+ dfllval_conf .bit .FINE = fine ;
293+ dfllctrl_conf .bit .USBCRM = 1 ; // usb correction
294+ dfllctrl_conf .bit .BPLCKC = 0 ;
295+ dfllctrl_conf .bit .QLDIS = 0 ;
296+ dfllctrl_conf .bit .CCDIS = 1 ;
297+ dfllctrl_conf .bit .ENABLE = 1 ;
298+
299+ SYSCTRL -> DFLLCTRL .bit .ONDEMAND = 0 ;
300+ while (!(SYSCTRL -> PCLKSR .reg & SYSCTRL_PCLKSR_DFLLRDY ));
301+ SYSCTRL -> DFLLMUL .reg = 48000 ;
302+ SYSCTRL -> DFLLVAL .reg = dfllval_conf .reg ;
303+ SYSCTRL -> DFLLCTRL .reg = dfllctrl_conf .reg ;
304+
305+ //
306+ GCLK_CLKCTRL_Type clkctrl = {0 };
307+ uint16_t temp ;
308+ GCLK -> CLKCTRL .bit .ID = 2 ; // GCLK_ID - DFLL48M Reference
309+ temp = GCLK -> CLKCTRL .reg ;
310+ clkctrl .bit .CLKEN = 1 ;
311+ clkctrl .bit .WRTLOCK = 0 ;
312+ clkctrl .bit .GEN = GCLK_CLKCTRL_GEN_GCLK0_Val ;
313+ GCLK -> CLKCTRL .reg = (clkctrl .reg | temp );
314+
315+ // Configure DFLL48M as source for GCLK_GEN 0
316+ GCLK -> GENCTRL .bit .ID = 0 ; // GENERATOR_ID - GCLK_GEN_0
317+ while (GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY );
318+ temp_genctrl = GCLK -> GENCTRL .reg ;
319+ genctrl .bit .SRC = GCLK_GENCTRL_SRC_DFLL48M_Val ;
320+ genctrl .bit .GENEN = 1 ;
321+ genctrl .bit .RUNSTDBY = 0 ;
322+ genctrl .bit .OE = 1 ;
323+ GCLK -> GENCTRL .reg = (genctrl .reg | temp_genctrl );
324+ while (GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY );
325+
326+ #endif
327+
210328}
0 commit comments