Skip to content

Commit 37b592a

Browse files
committed
Bootloader: allow crystalless configuration
1 parent a46d49a commit 37b592a

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

bootloaders/zero/board_definitions_arduino_nona_wlan.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959

6060
/* Frequency of the board main oscillator */
6161
#define VARIANT_MAINOSC (32768ul)
62+
#define CRYSTALLESS (1)
6263

6364
/* Calibration values for DFLL48 pll */
6465
#define NVM_SW_CALIB_DFLL48M_COARSE_VAL (58)

bootloaders/zero/board_init.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,23 @@ void board_init(void)
5050
/* Turn on the digital interface clock */
5151
PM->APBAMASK.reg |= PM_APBAMASK_GCLK;
5252

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+
5370
/* ----------------------------------------------------------------------------------------------
5471
* 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator)
5572
*/
@@ -62,6 +79,8 @@ void board_init(void)
6279
/* Wait for oscillator stabilization */
6380
}
6481

82+
#endif
83+
6584
/* Software reset the module to ensure it is re-initialized correctly */
6685
/* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete.
6786
* 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)
85104

86105
/* Write Generic Clock Generator 1 configuration */
87106
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
88110
GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator
111+
#endif
89112
// GCLK_GENCTRL_OE | // Output clock to a pin for tests
90113
GCLK_GENCTRL_GENEN;
91114

@@ -129,6 +152,49 @@ void board_init(void)
129152
/* Wait for synchronization */
130153
}
131154

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+
132198
/* Write full configuration to DFLL control register */
133199
SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */
134200
SYSCTRL_DFLLCTRL_WAITLOCK |
@@ -153,6 +219,8 @@ void board_init(void)
153219
/* Wait for synchronization */
154220
}
155221

222+
#endif
223+
156224
/* ----------------------------------------------------------------------------------------------
157225
* 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz.
158226
*/

0 commit comments

Comments
 (0)