Skip to content

Commit 7b8e0b1

Browse files
committed
Added support for crystal-less configurations
1 parent 68d4a93 commit 7b8e0b1

File tree

1 file changed

+65
-1
lines changed

1 file changed

+65
-1
lines changed

cores/arduino/startup.c

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
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

Comments
 (0)