Skip to content

Commit d4a60a6

Browse files
committed
Cleaned up init code and made it even lower power
init code now only initialises Gclk1 ( EXosc32k ) and Gclk0 ( Dfll48 ), system runs ar 48 MHz normally and switches to internal 4MHz clk and low performanc ( good power saving ) mode on sleep, gets restored on wakeup Wake from IDLE is <1s Wake from STANDBY is 1s Quescent current on the PCB is still high ( around 1.2 mA ) run 14 mA idle 1,5 mA standby 1,21 mA backup 1,21 mA
1 parent bafcad0 commit d4a60a6

File tree

7 files changed

+125
-148
lines changed

7 files changed

+125
-148
lines changed

cores/arduino/Arduino.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ void loop( void ) ;
125125
#endif
126126

127127
// Allows publishing the Beta core under samd-beta / arduino organization
128-
#ifndef ARDUINO_ARCH_SAMD
129-
#define ARDUINO_ARCH_SAMD
128+
#ifndef ARDUINO_ARCH_SAMR
129+
#define ARDUINO_ARCH_SAMR
130130
#endif
131131

132132
// USB Device

cores/arduino/USB/USBCore.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,9 @@ void USBDeviceClass::init()
296296

297297
usbd.calibrate();
298298
usbd.setUSBDeviceMode();
299-
usbd.runInStandby();
299+
//usbd.runInStandby();
300+
usbd.noRunInStandby(); // don't run in standby mode
301+
300302
//usbd.setLowSpeed();
301303
usbd.setFullSpeed();
302304

cores/arduino/WInterrupts.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ static void __initialize()
4848
*/
4949
EIC->CTRLA.bit.CKSEL = 1; // use ULP32k as source
5050
// Enable EIC
51-
EIC->CTRLA.bit.ENABLE = 1;
51+
EIC->CTRLA.bit.ENABLE = 1;
5252
while (EIC->SYNCBUSY.bit.ENABLE == 1) { /*wait for sync*/ }
5353
}
5454

cores/arduino/startup.c

Lines changed: 47 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,13 @@ void SystemInit( void )
8686
temp.bit.RUNSTDBY = 0;
8787
// commit changes
8888
OSC32KCTRL->XOSC32K.reg = temp.reg;
89-
9089
// enable xosc32k clock
9190
OSC32KCTRL->XOSC32K.reg |= OSC32KCTRL_XOSC32K_ENABLE;
9291
// wait for clock to become ready
9392
while ( (OSC32KCTRL->STATUS.reg & OSC32KCTRL_STATUS_XOSC32KRDY) == 0 );
94-
93+
94+
9595
// init DFLL
96-
// wait for dfll register to be ready before we write to it
97-
while ( ( OSCCTRL->STATUS.reg & OSCCTRL_STATUS_DFLLRDY) == 0 );
98-
9996
/* Using DFLL48M COARSE CAL value from NVM Software Calibration Area Mapping
10097
in DFLL.COARSE helps to output a frequency close to 48 MHz.*/
10198
#define NVM_DFLL_COARSE_POS 26 /* DFLL48M Coarse calibration value bit position.*/
@@ -110,48 +107,7 @@ void SystemInit( void )
110107
coarse = 0x1f;
111108
}
112109

113-
114-
// system_clock_source_dfll_set_config_errata_9905;
115-
/* Disable ONDEMAND mode while writing configurations */
116-
117-
118-
119-
OSCCTRL->DFLLCTRL.bit.ONDEMAND = 0;
120-
OSCCTRL->DFLLCTRL.bit.ENABLE = 1;
121-
// wait for dfll register to be ready before we write to it
122-
while ( ( OSCCTRL->STATUS.reg & OSCCTRL_STATUS_DFLLRDY) == 0 );
123-
124-
OSCCTRL_DFLLMUL_Type dfllMul = OSCCTRL->DFLLMUL;
125-
dfllMul.bit.CSTEP = (0x1f / 4); //MAX_COARSE_STEP_SIZE
126-
dfllMul.bit.FSTEP = (0xff / 4); //MAX_FINE_STEP_SIZE
127-
dfllMul.bit.MUL = (48000000 / 32768); // MULTIPLY_FACTOR
128-
// OSCCTRL->DFLLMUL.reg = dfllMul.reg;
129-
130-
// wait for dfll register to be ready before we write to it
131-
// while ((OSCCTRL->STATUS.reg & OSCCTRL_STATUS_DFLLRDY) == 0);
132-
133-
OSCCTRL_DFLLCTRL_Type dfllCtrl = OSCCTRL->DFLLCTRL;
134-
dfllCtrl.bit.MODE = 1; // closed loop mode
135-
dfllCtrl.bit.LLAW = 0; /** Keep DFLL lock when the device wakes from sleep */
136-
dfllCtrl.bit.STABLE = 0;/** Keep tracking after the DFLL has gotten a fine lock */
137-
dfllCtrl.bit.QLDIS = 0;/** Enable the QuickLock feature for looser lock requirements on the DFLL */
138-
dfllCtrl.bit.CCDIS = 0;/** Enable a chill cycle, where the DFLL output frequency is not measured */
139-
dfllCtrl.bit.ONDEMAND = 0; /** disable on demand mode*/
140-
dfllCtrl.bit.RUNSTDBY = 0; /** Do not run in standby */
141-
// OSCCTRL->DFLLCTRL.reg = dfllCtrl.reg;
142-
143-
// wait for dfll register to be ready before we write to it
144-
// while ( ( OSCCTRL->STATUS.reg & OSCCTRL_STATUS_DFLLRDY) == 0 );
145-
146-
OSCCTRL_DFLLVAL_Type dfllval = OSCCTRL->DFLLVAL;
147-
dfllval.bit.COARSE = coarse; /** Coarse calibration value (closed loop mode) */
148-
dfllval.bit.FINE = 0xff / 4; /* Midpoint fine calibration value (closed loop mode) */
149-
// OSCCTRL->DFLLVAL= dfllval;
150-
151-
// clock not enabled yet
152-
//
153-
154-
// init GCLK (0,1,2,3)
110+
// init GCLK (0,1)
155111
/* Turn on the digital interface clock */
156112
MCLK->APBAMASK.reg |= MCLK_APBAMASK_GCLK;
157113
/* Software reset the module to ensure it is re-initialized correctly */
@@ -164,67 +120,27 @@ void SystemInit( void )
164120

165121
GCLK_GENCTRL_Type gclkConfig;
166122
/* Configure GCLK generator 1 ( hw timer )
167-
* run in standby : 1
168-
* source : GCLK_SOURCE_XOSC32K
123+
* run in standby : 0
124+
* source : GCLK_GENCTRL_SRC_XOSC32K - more stable then ULP32k
169125
* prescaler ( division factor ) : 1
170126
* output enable : 0
171127
*/
172128
gclkConfig.reg = 0;
173129
gclkConfig.reg = GCLK->GENCTRL[1].reg;
174130
gclkConfig.bit.DIV = 1;
175-
gclkConfig.bit.SRC = GCLK_GENCTRL_SRC_XOSC32K_Val;
131+
gclkConfig.bit.SRC = GCLK_GENCTRL_SRC_XOSC32K_Val; // apparently more stable than ULP32k ( for the DFLL48 )
176132
gclkConfig.bit.OE = 0;
177133
gclkConfig.bit.RUNSTDBY = 0;
178-
179134
GCLK->GENCTRL[1].reg = gclkConfig.reg;
180135
/* Enable generator */
181136
gclk_gen_sync(1);
182137
GCLK->GENCTRL[1].reg |= GCLK_GENCTRL_GENEN;
183138

184-
/* Configure GCLK generator 2 ( adc )
185-
* run in standby : 0
186-
* source : GCLK_SOURCE_OSC16M
187-
* prescaler ( division factor ) : 5 ( use improved dutycycle mode )
188-
* output enable : 0
189-
*/
190-
gclkConfig.reg = 0;
191-
gclkConfig.reg = GCLK->GENCTRL[2].reg;
192-
gclkConfig.bit.DIV = 5;
193-
gclkConfig.bit.IDC = 1;
194-
gclkConfig.bit.SRC = GCLK_GENCTRL_SRC_OSC16M_Val;
195-
gclkConfig.bit.OE = 0;
196-
gclkConfig.bit.RUNSTDBY = 0;
197-
198-
GCLK->GENCTRL[2].reg = gclkConfig.reg;
199-
/* Enable generator */
200-
gclk_gen_sync(2);
201-
GCLK->GENCTRL[2].reg |= GCLK_GENCTRL_GENEN;
202-
203-
/* Configure GCLK generator 3
204-
* run in standby : 0
205-
* source : GCLK_SOURCE_DFLL48M
206-
* prescaler : 1
207-
* output enable : 0
208-
*/
209-
gclkConfig.reg = 0;
210-
gclkConfig.reg = GCLK->GENCTRL[3].reg;
211-
gclkConfig.bit.DIV = 1;
212-
gclkConfig.bit.SRC = GCLK_GENCTRL_SRC_DFLL48M_Val;
213-
gclkConfig.bit.OE = 0;
214-
gclkConfig.bit.RUNSTDBY = 0;
215-
216-
GCLK->GENCTRL[3].reg = gclkConfig.reg;
217-
/* Enable generator */
218-
gclk_gen_sync(3);
219-
GCLK->GENCTRL[3].reg |= GCLK_GENCTRL_GENEN;
220-
221-
222-
223139
/* Enable DFLL reference clock in closed loop mode */
224140
/* Disable the peripheral channel */
225141
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_DFLL48].reg &= ~GCLK_PCHCTRL_CHEN;
226142
/* Configure the peripheral channel */
227-
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_DFLL48].reg = GCLK_PCHCTRL_GEN(1); // Generator 1 is the source ( xosc32k )
143+
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_DFLL48].reg = GCLK_PCHCTRL_GEN(1); // Generator 1 is the source ( 32k )
228144
/* Enable the peripheral channel */
229145
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_DFLL48].reg |= GCLK_PCHCTRL_CHEN;
230146

@@ -235,15 +151,39 @@ void SystemInit( void )
235151
/* DFLL Enable (Open and Closed Loop) */
236152
// system_clock_source_dfll_set_config_errata_9905;
237153
/* Disable ONDEMAND mode while writing configurations */
154+
while ( ( OSCCTRL->STATUS.reg & OSCCTRL_STATUS_DFLLRDY) == 0 );
155+
OSCCTRL->DFLLCTRL.bit.ONDEMAND = 0;
156+
OSCCTRL->DFLLCTRL.bit.ENABLE = 0;
157+
// wait for dfll register to be ready before we write to it
158+
while ( ( OSCCTRL->STATUS.reg & OSCCTRL_STATUS_DFLLRDY) == 0 );
159+
160+
OSCCTRL_DFLLMUL_Type dfllMul = OSCCTRL->DFLLMUL;
161+
dfllMul.bit.CSTEP = (0x1f / 4); //MAX_COARSE_STEP_SIZE
162+
dfllMul.bit.FSTEP = (0xff / 4); //MAX_FINE_STEP_SIZE
163+
dfllMul.bit.MUL = (VARIANT_MCK / 32768); // MULTIPLY_FACTOR
164+
165+
OSCCTRL_DFLLCTRL_Type dfllCtrl = OSCCTRL->DFLLCTRL;
166+
dfllCtrl.bit.MODE = 1; // closed loop mode
167+
dfllCtrl.bit.LLAW = 0; /** low power, we re-aquire lock after wake */ // low power, we re-aquire lock after wake
168+
dfllCtrl.bit.STABLE = 0;/** Keep tracking after the DFLL has gotten a fine lock */
169+
dfllCtrl.bit.QLDIS = 0;/** Enable the QuickLock feature for looser lock requirements on the DFLL */
170+
dfllCtrl.bit.CCDIS = 0;/** Enable a chill cycle, where the DFLL output frequency is not measured */
171+
dfllCtrl.bit.ONDEMAND = 0; /** disable on demand mode*/
172+
dfllCtrl.bit.RUNSTDBY = 0; /** Do not run in standby */
173+
dfllCtrl.bit.ENABLE = 1; // set enable bit
174+
175+
OSCCTRL_DFLLVAL_Type dfllval = OSCCTRL->DFLLVAL;
176+
dfllval.bit.COARSE = coarse; /** Coarse calibration value (closed loop mode) */
177+
dfllval.bit.FINE = 0xff / 4; /* Midpoint fine calibration value (closed loop mode) */
178+
// clock not enabled yet
179+
//
238180

239181
// wait for dfll register to be ready before we write to it
240182
while ( ( OSCCTRL->STATUS.reg & OSCCTRL_STATUS_DFLLRDY) == 0 );
241183

242184
OSCCTRL->DFLLCTRL.bit.ONDEMAND = 0;
243185
OSCCTRL->DFLLCTRL.bit.ENABLE = 1;
244-
dfllCtrl.bit.ENABLE = 1; // set enable bit
245-
//
246-
186+
247187
OSCCTRL->DFLLMUL.reg = 0;
248188
OSCCTRL->DFLLVAL.reg = 0;
249189
// wait for dfll register to be ready before we write to it
@@ -268,7 +208,6 @@ void SystemInit( void )
268208
/* Wait for DFLL sync */
269209
}
270210

271-
OSCCTRL->DFLLCTRL.bit.ONDEMAND = 1;
272211
/* Enable generator 0 as it depends on other generators*/
273212
/* Configure GCLK generator 0 (Main Clock)
274213
* run in standby : false
@@ -285,6 +224,19 @@ gclkConfig.bit.RUNSTDBY = 0;
285224
GCLK->GENCTRL[0].reg = gclkConfig.reg;
286225
gclk_gen_sync(0);
287226
GCLK->GENCTRL[0].reg |= GCLK_GENCTRL_GENEN;
227+
228+
//OSC32KCTRL->XOSC32K.bit.ONDEMAND = 1; // enable xosc32k to be ondemand
229+
//
230+
//prepare OSC16M to always run in 4MHz mode
231+
// going to use it when we go to sleep
232+
233+
OSCCTRL->OSC16MCTRL.bit.ENABLE= 0 ;
234+
OSCCTRL->OSC16MCTRL.bit.FSEL= OSCCTRL_OSC16MCTRL_FSEL_4_Val ;
235+
OSCCTRL->OSC16MCTRL.bit.RUNSTDBY = 1;
236+
OSCCTRL->OSC16MCTRL.bit.ONDEMAND = 0;
237+
238+
OSCCTRL->OSC16MCTRL.reg |= OSCCTRL_OSC16MCTRL_ENABLE;
239+
288240
/* CPU and BUS clocks */
289241
MCLK->BUPDIV.reg = MCLK_BUPDIV_BUPDIV_DIV1;/** Divide Main clock by one */
290242
MCLK->LPDIV.reg = MCLK_LPDIV_LPDIV_DIV1; /** Divide low power clock by 1*/

cores/arduino/wiring.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
*/
1818

1919
#include "Arduino.h"
20+
2021
#define VERY_LOW_POWER
22+
2123
#ifdef __cplusplus
2224
extern "C" {
2325
#endif
@@ -82,8 +84,6 @@ void init( void )
8284

8385
// Defining VERY_LOW_POWER breaks Arduino APIs since all pins are considered INPUT at startup
8486
// However, it really lowers the power consumption by a factor of 20 in low power mode (0.03mA vs 0.6mA)
85-
// retain all IO configurations upon wakeup
86-
// PM->CTRLA.reg = PM_CTRLA_IORET;
8787
#ifndef VERY_LOW_POWER
8888
// Setup all pins (digital and analog) in INPUT mode (default is nothing)
8989
for (uint32_t ul = 0 ; ul < NUM_DIGITAL_PINS ; ul++ )

libraries/SPI/SPI.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
#define SPI_MODE2 0x03
3838
#define SPI_MODE3 0x01
3939

40-
#if defined(ARDUINO_ARCH_SAMD)
40+
#if defined(ARDUINO_ARCH_SAMR)
4141
// The datasheet specifies a typical SPI SCK period (tSCK) of 42 ns,
4242
// see "Table 36-48. SPI Timing Characteristics and Requirements",
4343
// which translates into a maximum SPI clock of 23.8 MHz.

0 commit comments

Comments
 (0)