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,7 +52,21 @@ void SystemInit( void )
5152 /* Turn on the digital interface clock */
5253 PM -> APBAMASK .reg |= PM_APBAMASK_GCLK ;
5354
54- #if !defined(CRYSTALLESS )
55+ #if defined(CRYSTALLESS )
56+
57+ /* ----------------------------------------------------------------------------------------------
58+ * 1) Enable OSC32K clock (Internal 32.768Hz oscillator)
59+ */
60+
61+ uint32_t calib = (* ((uint32_t * ) SYSCTRL_FUSES_OSC32K_ADDR ) & SYSCTRL_FUSES_OSC32K_Msk ) >> SYSCTRL_FUSES_OSC32K_Pos ;
62+
63+ SYSCTRL -> OSC32K .reg = SYSCTRL_OSC32K_CALIB (calib ) | SYSCTRL_OSC32K_STARTUP ( 0x6u ) | // cf table 15.10 of product datasheet in chapter 15.8.6
64+ SYSCTRL_OSC32K_EN32K | SYSCTRL_OSC32K_ENABLE ;
65+
66+ while ( (SYSCTRL -> PCLKSR .reg & SYSCTRL_PCLKSR_OSC32KRDY ) == 0 ); // Wait for oscillator stabilization
67+
68+ #else // has crystal
69+
5570 /* ----------------------------------------------------------------------------------------------
5671 * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator)
5772 */
@@ -64,6 +79,8 @@ void SystemInit( void )
6479 /* Wait for oscillator stabilization */
6580 }
6681
82+ #endif
83+
6784 /* Software reset the module to ensure it is re-initialized correctly */
6885 /* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete.
6986 * CTRL.SWRST and STATUS.SYNCBUSY will both be cleared when the reset is complete, as described in chapter 13.8.1
@@ -76,19 +93,23 @@ void SystemInit( void )
7693 }
7794
7895 /* ----------------------------------------------------------------------------------------------
79- * 2) Put XOSC32K as source of Generic Clock Generator 1
96+ * 2) Put XOSC32K or OSC32K as source of Generic Clock Generator 1
8097 */
81- GCLK -> GENDIV .reg = GCLK_GENDIV_ID ( GENERIC_CLOCK_GENERATOR_XOSC32K ) ; // Generic Clock Generator 1
98+ GCLK -> GENDIV .reg = GCLK_GENDIV_ID ( GENERIC_CLOCK_GENERATOR_OSC32K ) ; // Generic Clock Generator 1
8299
83100 while ( GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY )
84101 {
85102 /* Wait for synchronization */
86103 }
87104
88105 /* Write Generic Clock Generator 1 configuration */
89- GCLK -> GENCTRL .reg = GCLK_GENCTRL_ID ( GENERIC_CLOCK_GENERATOR_XOSC32K ) | // Generic Clock Generator 1
106+ GCLK -> GENCTRL .reg = GCLK_GENCTRL_ID ( GENERIC_CLOCK_GENERATOR_OSC32K ) | // Generic Clock Generator 1
107+ #if defined(CRYSTALLESS )
108+ GCLK_GENCTRL_SRC_OSC32K | // Selected source is Internal 32KHz Oscillator
109+ #else
90110 GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator
91- // GCLK_GENCTRL_OE | // Output clock to a pin for tests
111+ #endif
112+ GCLK_GENCTRL_OE | // Output clock to a pin for tests
92113 GCLK_GENCTRL_GENEN ;
93114
94115 while ( GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY )
@@ -112,8 +133,6 @@ void SystemInit( void )
112133 * 4) Enable DFLL48M clock
113134 */
114135
115- /* DFLL Configuration in Closed Loop mode, cf product datasheet chapter 15.6.7.1 - Closed-Loop Operation */
116-
117136 /* Remove the OnDemand mode, Bug http://avr32.icgroup.norway.atmel.com/bugzilla/show_bug.cgi?id=9905 */
118137 SYSCTRL -> DFLLCTRL .bit .ONDEMAND = 0 ;
119138
@@ -131,6 +150,46 @@ void SystemInit( void )
131150 /* Wait for synchronization */
132151 }
133152
153+ #if defined(CRYSTALLESS )
154+ #define NVM_SW_CALIB_DFLL48M_COARSE_VAL 58
155+ #define NVM_SW_CALIB_DFLL48M_FINE_VAL 64
156+
157+ // Turn on DFLL
158+ SYSCTRL_DFLLVAL_Type dfllval_conf = {0 };
159+ uint32_t coarse = ( * ((uint32_t * )(NVMCTRL_OTP4 )
160+ + (NVM_SW_CALIB_DFLL48M_COARSE_VAL / 32 ))
161+ >> (NVM_SW_CALIB_DFLL48M_COARSE_VAL % 32 ))
162+ & ((1 << 6 ) - 1 );
163+ if (coarse == 0x3f ) {
164+ coarse = 0x1f ;
165+ }
166+ uint32_t fine = ( * ((uint32_t * )(NVMCTRL_OTP4 )
167+ + (NVM_SW_CALIB_DFLL48M_FINE_VAL / 32 ))
168+ >> (NVM_SW_CALIB_DFLL48M_FINE_VAL % 32 ))
169+ & ((1 << 10 ) - 1 );
170+ if (fine == 0x3ff ) {
171+ fine = 0x1ff ;
172+ }
173+ dfllval_conf .bit .COARSE = coarse ;
174+ dfllval_conf .bit .FINE = fine ;
175+
176+ SYSCTRL -> DFLLVAL .reg = dfllval_conf .reg ;
177+ /* Write full configuration to DFLL control register */
178+ SYSCTRL -> DFLLCTRL .reg = SYSCTRL_DFLLCTRL_USBCRM | /* USB correction */
179+ SYSCTRL_DFLLCTRL_CCDIS |
180+ SYSCTRL_DFLLCTRL_WAITLOCK |
181+ SYSCTRL_DFLLCTRL_QLDIS ; /* Disable Quick lock */
182+
183+ while ( (SYSCTRL -> PCLKSR .reg & SYSCTRL_PCLKSR_DFLLRDY ) == 0 )
184+ {
185+ /* Wait for synchronization */
186+ }
187+
188+ /* Enable the DFLL */
189+ SYSCTRL -> DFLLCTRL .reg |= SYSCTRL_DFLLCTRL_ENABLE ;
190+
191+ #else // has crystal
192+
134193 /* Write full configuration to DFLL control register */
135194 SYSCTRL -> DFLLCTRL .reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */
136195 SYSCTRL_DFLLCTRL_WAITLOCK |
@@ -149,6 +208,8 @@ void SystemInit( void )
149208 {
150209 /* Wait for locks flags */
151210 }
211+
212+ #endif
152213
153214 while ( (SYSCTRL -> PCLKSR .reg & SYSCTRL_PCLKSR_DFLLRDY ) == 0 )
154215 {
@@ -168,7 +229,7 @@ void SystemInit( void )
168229 /* Write Generic Clock Generator 0 configuration */
169230 GCLK -> GENCTRL .reg = GCLK_GENCTRL_ID ( GENERIC_CLOCK_GENERATOR_MAIN ) | // Generic Clock Generator 0
170231 GCLK_GENCTRL_SRC_DFLL48M | // Selected source is DFLL 48MHz
171- // GCLK_GENCTRL_OE | // Output clock to a pin for tests
232+ GCLK_GENCTRL_OE | // Output clock to a pin for tests
172233 GCLK_GENCTRL_IDC | // Set 50/50 duty cycle
173234 GCLK_GENCTRL_GENEN ;
174235
@@ -191,121 +252,9 @@ void SystemInit( void )
191252 /* Write Generic Clock Generator 3 configuration */
192253 GCLK -> GENCTRL .reg = GCLK_GENCTRL_ID ( GENERIC_CLOCK_GENERATOR_OSC8M ) | // Generic Clock Generator 3
193254 GCLK_GENCTRL_SRC_OSC8M | // Selected source is RC OSC 8MHz (already enabled at reset)
194- // GCLK_GENCTRL_OE | // Output clock to a pin for tests
255+ GCLK_GENCTRL_OE | // Output clock to a pin for tests
195256 GCLK_GENCTRL_GENEN ;
196257
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-
309258 while ( GCLK -> STATUS .reg & GCLK_STATUS_SYNCBUSY )
310259 {
311260 /* Wait for synchronization */
0 commit comments