Skip to content

Commit 7ae624f

Browse files
committed
Merge branch 'atsamd21e' of github.com:adafruit/ArduinoCore-samd into atsamd21e
2 parents 3af25a4 + ae78e27 commit 7ae624f

File tree

1 file changed

+70
-121
lines changed

1 file changed

+70
-121
lines changed

cores/arduino/startup.c

Lines changed: 70 additions & 121 deletions
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,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

Comments
 (0)