3838// Constants for Clock generators
3939#define GENERIC_CLOCK_GENERATOR_MAIN (0u)
4040#define GENERIC_CLOCK_GENERATOR_XOSC32K (1u)
41+ #define GENERIC_CLOCK_GENERATOR_OSC32K (1u)
4142#define GENERIC_CLOCK_GENERATOR_OSCULP32K (2u) /* Initialized at reset for WDT */
4243#define GENERIC_CLOCK_GENERATOR_OSC8M (3u)
4344// Constants for Clock multiplexers
@@ -51,6 +52,24 @@ void SystemInit( void )
5152 /* Turn on the digital interface clock */
5253 PM -> APBAMASK .reg |= PM_APBAMASK_GCLK ;
5354
55+
56+ #if defined(CRYSTALLESS )
57+
58+ /* ----------------------------------------------------------------------------------------------
59+ * 1) Enable OSC32K clock (Internal 32.768Hz oscillator)
60+ */
61+
62+ uint32_t calib = (* ((uint32_t * ) SYSCTRL_FUSES_OSC32K_ADDR ) & SYSCTRL_FUSES_OSC32K_Msk ) >> SYSCTRL_FUSES_OSC32K_Pos ;
63+
64+ SYSCTRL -> OSC32K .reg = SYSCTRL_OSC32K_CALIB (calib ) |
65+ SYSCTRL_OSC32K_STARTUP ( 0x6u ) | // cf table 15.10 of product datasheet in chapter 15.8.6
66+ SYSCTRL_OSC32K_EN32K |
67+ SYSCTRL_OSC32K_ENABLE ;
68+
69+ while ( (SYSCTRL -> PCLKSR .reg & SYSCTRL_PCLKSR_OSC32KRDY ) == 0 ); // Wait for oscillator stabilization
70+
71+ #else // has crystal
72+
5473 /* ----------------------------------------------------------------------------------------------
5574 * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator)
5675 */
@@ -63,6 +82,8 @@ void SystemInit( void )
6382 /* Wait for oscillator stabilization */
6483 }
6584
85+ #endif
86+
6687 /* Software reset the module to ensure it is re-initialized correctly */
6788 /* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete.
6889 * CTRL.SWRST and STATUS.SYNCBUSY will both be cleared when the reset is complete, as described in chapter 13.8.1
@@ -85,8 +106,12 @@ void SystemInit( void )
85106 }
86107
87108 /* Write Generic Clock Generator 1 configuration */
88- GCLK -> GENCTRL .reg = GCLK_GENCTRL_ID ( GENERIC_CLOCK_GENERATOR_XOSC32K ) | // Generic Clock Generator 1
109+ GCLK -> GENCTRL .reg = GCLK_GENCTRL_ID ( GENERIC_CLOCK_GENERATOR_OSC32K ) | // Generic Clock Generator 1
110+ #if defined(CRYSTALLESS )
111+ GCLK_GENCTRL_SRC_OSC32K | // Selected source is Internal 32KHz Oscillator
112+ #else
89113 GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator
114+ #endif
90115// GCLK_GENCTRL_OE | // Output clock to a pin for tests
91116 GCLK_GENCTRL_GENEN ;
92117
@@ -130,6 +155,43 @@ void SystemInit( void )
130155 /* Wait for synchronization */
131156 }
132157
158+ #if defined(CRYSTALLESS )
159+
160+ #define NVM_SW_CALIB_DFLL48M_COARSE_VAL 58
161+ #define NVM_SW_CALIB_DFLL48M_FINE_VAL 64
162+
163+ // Turn on DFLL
164+ SYSCTRL_DFLLVAL_Type dfllval_conf = {0 };
165+ uint32_t coarse = ( * ((uint32_t * )(NVMCTRL_OTP4 ) + (NVM_SW_CALIB_DFLL48M_COARSE_VAL / 32 )) >> (NVM_SW_CALIB_DFLL48M_COARSE_VAL % 32 ) )
166+ & ((1 << 6 ) - 1 );
167+ if (coarse == 0x3f ) {
168+ coarse = 0x1f ;
169+ }
170+ uint32_t fine = ( * ((uint32_t * )(NVMCTRL_OTP4 ) + (NVM_SW_CALIB_DFLL48M_FINE_VAL / 32 )) >> (NVM_SW_CALIB_DFLL48M_FINE_VAL % 32 ) )
171+ & ((1 << 10 ) - 1 );
172+ if (fine == 0x3ff ) {
173+ fine = 0x1ff ;
174+ }
175+ dfllval_conf .bit .COARSE = coarse ;
176+ dfllval_conf .bit .FINE = fine ;
177+
178+ SYSCTRL -> DFLLVAL .reg = dfllval_conf .reg ;
179+ /* Write full configuration to DFLL control register */
180+ SYSCTRL -> DFLLCTRL .reg = SYSCTRL_DFLLCTRL_USBCRM | /* USB correction */
181+ SYSCTRL_DFLLCTRL_CCDIS |
182+ SYSCTRL_DFLLCTRL_WAITLOCK |
183+ SYSCTRL_DFLLCTRL_QLDIS ; /* Disable Quick lock */
184+
185+ while ( (SYSCTRL -> PCLKSR .reg & SYSCTRL_PCLKSR_DFLLRDY ) == 0 )
186+ {
187+ /* Wait for synchronization */
188+ }
189+
190+ /* Enable the DFLL */
191+ SYSCTRL -> DFLLCTRL .reg |= SYSCTRL_DFLLCTRL_ENABLE ;
192+
193+ #else // has crystal
194+
133195 /* Write full configuration to DFLL control register */
134196 SYSCTRL -> DFLLCTRL .reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */
135197 SYSCTRL_DFLLCTRL_WAITLOCK |
@@ -149,6 +211,8 @@ void SystemInit( void )
149211 /* Wait for locks flags */
150212 }
151213
214+ #endif
215+
152216 while ( (SYSCTRL -> PCLKSR .reg & SYSCTRL_PCLKSR_DFLLRDY ) == 0 )
153217 {
154218 /* Wait for synchronization */
0 commit comments