@@ -50,6 +50,23 @@ void board_init(void)
50
50
/* Turn on the digital interface clock */
51
51
PM -> APBAMASK .reg |= PM_APBAMASK_GCLK ;
52
52
53
+ #if defined(CRYSTALLESS )
54
+
55
+ /* ----------------------------------------------------------------------------------------------
56
+ * 1) Enable OSC32K clock (Internal 32.768Hz oscillator)
57
+ */
58
+
59
+ uint32_t calib = (* ((uint32_t * ) FUSES_OSC32K_CAL_ADDR ) & FUSES_OSC32K_CAL_Msk ) >> FUSES_OSC32K_CAL_Pos ;
60
+
61
+ SYSCTRL -> OSC32K .reg = SYSCTRL_OSC32K_CALIB (calib ) |
62
+ SYSCTRL_OSC32K_STARTUP ( 0x6u ) | // cf table 15.10 of product datasheet in chapter 15.8.6
63
+ SYSCTRL_OSC32K_EN32K |
64
+ SYSCTRL_OSC32K_ENABLE ;
65
+
66
+ while ( (SYSCTRL -> PCLKSR .reg & SYSCTRL_PCLKSR_OSC32KRDY ) == 0 ); // Wait for oscillator stabilization
67
+
68
+ #else
69
+
53
70
/* ----------------------------------------------------------------------------------------------
54
71
* 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator)
55
72
*/
@@ -62,6 +79,8 @@ void board_init(void)
62
79
/* Wait for oscillator stabilization */
63
80
}
64
81
82
+ #endif
83
+
65
84
/* Software reset the module to ensure it is re-initialized correctly */
66
85
/* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete.
67
86
* CTRL.SWRST and STATUS.SYNCBUSY will both be cleared when the reset is complete, as described in chapter 13.8.1
@@ -85,7 +104,11 @@ void board_init(void)
85
104
86
105
/* Write Generic Clock Generator 1 configuration */
87
106
GCLK -> GENCTRL .reg = GCLK_GENCTRL_ID ( GENERIC_CLOCK_GENERATOR_XOSC32K ) | // Generic Clock Generator 1
107
+ #if defined(CRYSTALLESS )
108
+ GCLK_GENCTRL_SRC_OSC32K | // Selected source is Internal 32KHz Oscillator
109
+ #else
88
110
GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator
111
+ #endif
89
112
// GCLK_GENCTRL_OE | // Output clock to a pin for tests
90
113
GCLK_GENCTRL_GENEN ;
91
114
@@ -129,6 +152,49 @@ void board_init(void)
129
152
/* Wait for synchronization */
130
153
}
131
154
155
+ #if defined(CRYSTALLESS )
156
+
157
+ #define NVM_SW_CALIB_DFLL48M_COARSE_VAL 58
158
+
159
+ // Turn on DFLL
160
+ uint32_t coarse = ( * ((uint32_t * )(NVMCTRL_OTP4 ) + (NVM_SW_CALIB_DFLL48M_COARSE_VAL / 32 )) >> (NVM_SW_CALIB_DFLL48M_COARSE_VAL % 32 ) )
161
+ & ((1 << 6 ) - 1 );
162
+ if (coarse == 0x3f ) {
163
+ coarse = 0x1f ;
164
+ }
165
+ // TODO(tannewt): Load this value from memory we've written previously. There
166
+ // isn't a value from the Atmel factory.
167
+ uint32_t fine = 0x1ff ;
168
+
169
+ SYSCTRL -> DFLLVAL .bit .COARSE = coarse ;
170
+ SYSCTRL -> DFLLVAL .bit .FINE = fine ;
171
+ /* Write full configuration to DFLL control register */
172
+ SYSCTRL -> DFLLMUL .reg = SYSCTRL_DFLLMUL_CSTEP ( 0x1f / 4 ) | // Coarse step is 31, half of the max value
173
+ SYSCTRL_DFLLMUL_FSTEP ( 10 ) |
174
+ SYSCTRL_DFLLMUL_MUL ( (48000 ) ) ;
175
+
176
+ SYSCTRL -> DFLLCTRL .reg = 0 ;
177
+
178
+ while ( (SYSCTRL -> PCLKSR .reg & SYSCTRL_PCLKSR_DFLLRDY ) == 0 )
179
+ {
180
+ /* Wait for synchronization */
181
+ }
182
+
183
+ SYSCTRL -> DFLLCTRL .reg = SYSCTRL_DFLLCTRL_MODE |
184
+ SYSCTRL_DFLLCTRL_CCDIS |
185
+ SYSCTRL_DFLLCTRL_USBCRM | /* USB correction */
186
+ SYSCTRL_DFLLCTRL_BPLCKC ;
187
+
188
+ while ( (SYSCTRL -> PCLKSR .reg & SYSCTRL_PCLKSR_DFLLRDY ) == 0 )
189
+ {
190
+ /* Wait for synchronization */
191
+ }
192
+
193
+ /* Enable the DFLL */
194
+ SYSCTRL -> DFLLCTRL .reg |= SYSCTRL_DFLLCTRL_ENABLE ;
195
+
196
+ #else // has crystal
197
+
132
198
/* Write full configuration to DFLL control register */
133
199
SYSCTRL -> DFLLCTRL .reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */
134
200
SYSCTRL_DFLLCTRL_WAITLOCK |
@@ -153,6 +219,8 @@ void board_init(void)
153
219
/* Wait for synchronization */
154
220
}
155
221
222
+ #endif
223
+
156
224
/* ----------------------------------------------------------------------------------------------
157
225
* 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz.
158
226
*/
0 commit comments