SAM L10/L11 SleepWalking
SleepWalking Overview
SleepWalking is the capability of a device to temporarily and asynchronously wake up a peripheral by enabling its clock so it can perform a task without waking up the CPU from Standby mode. This is called SleepWalking because it allows the CPU to sleep until a relevant event occurs. To perform SleepWalking, the Event System (EVSYS) is required to interconnect the peripherals. The EVSYS is used to connect an Event Generator Peripheral to an Event User Peripheral.
When the CPU is in Standby, the Event User Peripheral can request its clock, upon receiving an event generator peripheral trigger, to perform its task autonomously as described in the following figure.
This timing chart explicitly shows that the CPU will wake up only after the peripheral wake-up request (interrupt) is issued.
Initially, we see the peripheral requesting its clock to perform the first task. The conditions to wake up the SleepWalking CPU were not met after this first task. The peripheral requests its clock again, and the conditions are subsequently met to trigger a peripheral interrupt allowing the CPU to wake up.
Thus, SleepWalking is accomplished by the peripheral itself using the EVSYS to interconnect the peripherals in Standby without CPU intervention. The CPU and the full RAM will not wake up until the condition is true.
When implementing SleepWalking user has to reproduce the following configuration:
SleepWalking with Dynamic Power Gating
To reduce power consumption even further, SleepWalking with dynamic Power Domain Gating (also referred to as "Dynamic Sleepwalking") is used to turn the power domain state from retention to active and vice-versa, based on an event or DMA trigger. This capability, which extends the clock gating function normally provided by the "Static" SleepWalking function to enable a power domain, is called Power Gating.
Related Peripherals
SleepWalking involves several parts of the architecture and strongly depends on which peripherals are used in the targeted application. You must be familiar with common system peripherals that are the minimal required set to get the device performing SleepWalking. Here is a list of tasks and peripheral components that are required for SleepWalking:
- Configure Power Gating and Sleep modes: Power Manager (PM)
- Configure the internal Voltage Regulator and Performance Levels: Supply Controller (SUPC)
- Configure the clock System, enable, set On Demand and Run in Standby mode:
- Interconnect Peripherals: Event System
How to Perform SleepWalking
Application Considerations
Before considering a SleepWalking implementation, you must understand the key power constraints for your application. Consider the following questions:
- Is my application power-constrained?
- E.g.: Is it battery-powered?
- In my application, what is the ratio of Sleep time vs. Active time?
- Will my application require the maximum CPU frequency for computation during Active mode?
- What is the source clock that I will use for the CPU?
- What Performance Level must be required in Active and in Sleep?
- What will be the most suitable Sleep mode for my application?
- Is that Sleep mode available with my considered Performance Level?
- Should I consider switching to a lower Performance Level once in Sleep?
- What will be the relevant interrupt(s) waking up my devices
- How many peripherals does my application require?
- Is it possible to interconnect them using the Event System?
- If yes, what is my Event Generator Peripheral?
- What is my Event User Peripheral?
- What is the EVSYS connection required to get them working together as expected?
- Will they work synchronously or asynchronously from each other?
- Considering power efficiency, what is the best clock configuration for my application?
- Should all the parts of my system be clocked by the same clock source?
- Should they be clocked independently allowing the unused parts to be switched off?
- What are the clock sources that are the most power-efficient for each peripheral for my application?
- Can I group some peripherals to a dedicated clock source?
- Considering that my application will spend most of the time in Sleep mode, which fast clock can I use to spend as little time as possible when in Active mode?
Guide to Main Steps
Source Clocks
In this step, you have to implement the clock(s) strategy of your application:
- When the device is in Active mode.
- When the device is in Low-Power mode.
- Enable the source clock(s) of the peripherals. Refer to the Oscillator Controller (OSCCTRL) or 32K Oscillator Controller (OSC32KCTRL) peripheral example.
- Configure the clock sources with On Demand and Run in Standby enabled. These bits are located into the specified source clock Control Register e.g:
- For OSC16M:
- OSCCTRL.OSC16MCTRL.bit.ONDEMAND
- OSCCTRL.OSC16MCTRL.bit.RUNSTDBY
- For DFLLULP:
- OSCCTRL.DFLLULPCTRL.bit.ONDEMAND
- OSCCTRL.DFLLULPCTRL.bit.RUNSTDBY
Generic Clock Generator
Configure the generic clock generator with Run in Standby enabled. This bit is located into the Generic Generator CONTROL x Register e.g.,:
- For GENCTRL0:
- GCLK.GENCTRL0.bit.RUNSTDBY
Peripheral Event Generator
According to the Event System page, you have to identify which peripherals can be interconnected together using the Peripheral Event System in your application. In this step, the Peripheral Event Generator is configured.
Regarding SleepWalking, the main settings to consider in the Peripheral Event Generator configuration are the following:
- Run In Standby capability: If the Event Generator Peripheral is required to Run in StandBy Low-Power mode, the bit RUNSTDBY must be set. This bit is located in the Control register of the Event Generator Peripheral.
- On Demand clock request capability: This is a mandatory parameter that is required to be set, allowing the peripheral to be able to request its own clock. This bit is located in the Control register of the Event Generator Peripheral.
- Event Generation capability must be configured. This feature is usually configured through the Event Control Register (EVCTRL) of each peripheral connected to the Event System.
*** EXAMPLE SLEEPWALKING: TC0 is used to trigger
*** ADC Start conversion using the Event System,
*** at 1 kHz frequency based on XOSC32K.
***/
void init_TC0_1KHz(void)
{
/*** Disable TC0 (Enable Protected, write synchronized) ***/
TC0->COUNT8.CTRLA.bit.ENABLE = 0;
while(TC0->COUNT8.SYNCBUSY.reg & TC_SYNCBUSY_ENABLE);
/*** Configure TC0 in 8-bit counter with GLCK
*** for synchronization and a DIV16 to get 1KHz
*** event generation for the ADC.
***/
TC0->COUNT8.CTRLA.reg |= (TC_CTRLA_MODE(TC_CTRLA_MODE_COUNT8_Val) |
TC_CTRLA_RUNSTDBY|
TC_CTRLA_ONDEMAND|
TC_CTRLA_PRESCALER(TC_CTRLA_PRESCALER_DIV1_Val));
/*** TC0 Wave generator is configured
*** as Match frequency generator (MFRQ)
***/
TC0->COUNT8.WAVE.reg = (TC_WAVE_WAVEGEN_MFRQ);
/*** TC0 is an event generator based on compare value
*** These bits enable the generation of an event for
*** every match or capture on channel 0.
***/
TC0->COUNT8.EVCTRL.reg = (TC_EVCTRL_MCEO0);
/*** 32 is the number to get an event @ 1 kHz frequency
*** used by the ADC with a 32 kHz input frequency.
***/
TC0->COUNT8.CC[0].reg = 32;
/*** (write synchronized) ***/
while(TC0->COUNT8.SYNCBUSY.reg & TC_SYNCBUSY_CC0);
/***
*** TC Enable is not done
*** at this tep as EVSYS reminds to be configured
***/
}
Peripheral Event User
According to the Event System page, you have to identify which peripherals can be interconnected together using the Peripheral Event System in your application. In this step, the Peripheral Event User is configured.
Regarding SleepWalking, the main settings to consider in the Peripheral Event Generator configuration are the following:
- Run In Standby capability: If the Event User Peripheral is required to Run in StandBy Low-Power mode, the bit RUNSTDBY must be set. This bit is located in the Control register of the Event User Peripheral.
- On Demand clock request capability: This is a mandatory parameter that is required to be set, allowing the peripheral to be able to request its clock. This bit is located in the Control register of the Event User Peripheral.
- Event Input trigger must be configured. This feature is usually configured through the Event Control Register (EVCTRL) of each peripheral connected to the Event System.
*** EXAMPLE SLEEPWALKING: TC0 is used to trigger
*** ADC Start conversion using the Event System,
*** at 1 kHz frequency based on XOSC32K.
***/
void ADC_preconfig(void)
{
/*** Configure the ADC with
*** run in Standby and On-Demand
***/
ADC->CTRLA.reg = (ADC_CTRLA_RUNSTDBY|ADC_CTRLA_ONDEMAND);
/*** ADC clock prescaler configuration ***/
ADC->CTRLB.reg = (ADC_CTRLB_PRESCALER_DIV2);
/*** ADC in 12-bit resolution ***/
ADC->CTRLC.reg = (ADC_CTRLC_RESSEL_12BIT);
/*** (write synchronized) ***/
while(ADC->SYNCBUSY.reg & ADC_SYNCBUSY_CTRLC);
/*** internal variable reference voltage ***/
ADC->REFCTRL.reg = (ADC_REFCTRL_REFSEL_INTVCC2);
/*** Event control input with start of Conv ***/
ADC->EVCTRL.reg = (ADC_EVCTRL_STARTEI);
/*** MUXNEG: Internal Ground;
*** MUXPOS: AIN0: Signal on ADC+
*** of the Xplained Pro EXT1 connector
***/
ADC->INPUTCTRL.reg = (ADC_INPUTCTRL_MUXNEG(0x18)|
ADC_INPUTCTRL_MUXPOS_AIN0);
/*** (write synchronized) ***/
while(ADC->SYNCBUSY.reg & ADC_SYNCBUSY_INPUTCTRL);
/*** wait 5 adc Clock during sample ***/
ADC->SAMPCTRL.reg = ADC_SAMPCTRL_SAMPLEN(4);
/*** (write synchronized) ***/
while(ADC->SYNCBUSY.reg & ADC_SYNCBUSY_SAMPCTRL);
/***
*** ADC Interrupt and ADC Enable are not done
*** at this tep as EVSYS reminds to be configured
***/
}
Peripheral Event System
In this step, the interconnection between the Event Generator Peripheral and the Event User Peripheral is realized by configuring the Event System (EVSYS).
*** meaning, the ADC ISR is called each sample for evaluation.
*** NOTE: 1KHz may be 1024 Hz or 1000 Hz depending on which is easier, as we
*** don't want to penalize an MCU for requiring much higher speed clocks
*** to subdivide down to one or the other.
***/
void EVSYS_ADC_TC_1kHz(void)
{
/***
*** Configure EVSYS Channel 0 to interconnect ADC and TC
*** Configure ADC channel 0 Start of conversion
*** as user and TC as a trigger generator.
*** Asynchronous path is required as TC and ADC are not using the same clock generator
*** The EVSYS Channel 0 must also have RUNSTDBY and ONDEMAND bits set.
***/
EVSYS->USER[EVSYS_ID_USER_ADC_START].reg = EVSYS_USER_CHANNEL(EVSYS_USER_CHANNEL_0);
EVSYS->Channel[0].CHANNEL.reg = (EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT|
EVSYS_CHANNEL_RUNSTDBY |
EVSYS_CHANNEL_ONDEMAND |
EVSYS_CHANNEL_PATH_ASYNCHRONOUS|
EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_TC0_MC0));
/*** Now, Enable ADC result ready interrupt ***/
ADC->INTENSET.bit.RESRDY = 0x01;
/*** Enable resready ADC interrupt (ID 22)
*** At core level
***/
NVIC_EnableIRQ(ADC_RESRDY_IRQn);
NVIC_SetPriority(ADC_RESRDY_IRQn,1);
/*** Enable ADC first (Enable Protected, write synchronized) ***/
ADC->CTRLA.bit.ENABLE = 0x1;
while(ADC->SYNCBUSY.reg & ADC_SYNCBUSY_ENABLE);
/*** Enable TC then (Enable Protected, write synchronized) ***/
TC0->COUNT8.CTRLA.bit.ENABLE = 1;
while(TC0->COUNT8.SYNCBUSY.reg & TC_SYNCBUSY_ENABLE);
}
Prepare to Enter Low-Power Mode
In this step, the aim is to prepare the device to be very power efficient once it enters Sleep mode, by using different combined low-power techniques offered by its architecture.
Although these techniques are introduced in this section, they can also be used in different applications where Sleepwalking is not even required.
- Enable the NVM Flash Cache Low-Power mode: By default, the cache is enabled using the "No Miss Penalty" mode which gives the best system performances, but consumes more power. The Low-Power mode reduces the power consumption of the cache system but inserts a wait state each time there is a cache miss. This mode may not be relevant if CPU performance is required, as the application will be stalled and may lead to increased run time (NVMCTRL->CTRLB.bit.READMODE).
- Adapt Performance Level to save power consumption: Disabling the PL selection forces the device to run in PL0, reducing the power consumption, and the wake-up time from Standby Sleep mode (PM->PLCFG.bit.PLDIS).
- Enable Dynamic Power Gating: Make sure to have Dynamic SleepWalking for switchable power domain PDSW enabled (PM->STDBYCFG.bit.DPGPDSW).
- Adapt SRAM size retention (PM->PWCFG.bit.RAMPSWC).
- Select the most Power-efficient Regulator Type for your application: Buck regulator is generally the most efficient in terms of power consumption (SUPC->VREG.bit.SEL).
- Check if the ULP Voltage reference is ready to be used by the main regulator (SUPC->STATUS.bit.ULPVREFRDY).
- Select the ULP Voltage reference before entering into Sleep mode (SUPC->VREG.bit.VREFSEL).
- If your application main voltage is above 2.5 V, apply the Low-Power mode Efficiency for the Low Power Voltage Regulator (LPVREG) (SUPC->VREG.bit.LPEFF).
- Optionally configure the IO ports to be in a tri-state condition.
{
/* Enable the cache LOW POWER read mode */
NVMCTRL->CTRLB.bit.READMODE = 1;
/* Disable Performance Level forcing the device to be in
* PL0 to reduce power consumption.
* User must consider this, if once in active,
* the application requires more performances.
*/
PM->PLCFG.bit.PLDIS = 1;
/* Enable Dynamic Power Gating enabled */
PM->STDBYCFG.bit.DPGPDSW = PM_STDBYCFG_DPGPDSW_1_Val;
/* 4kB SRAM out of 16kB will be retained in STANDBY */
PM->PWCFG.bit.RAMPSWC = PM_PWCFG_RAMPSWC_4KB_Val;
/* Buck Regulator mode : Select Buck = 1 */
SUPC->VREG.bit.SEL = 1;
while(SUPC->STATUS.bit.VREGRDY==0);
/* As VREG Switching mode is let in automatic mode
* PM->.STDBYCFG.reg.VREGSMOD=0,
* user has to check if the MAINREG low power R
* reference is ready.
*/
while(SUPC->STATUS.bit.ULPVREFRDY==0);
/* low power ref for vreg once in Sleep Mode */
SUPC->VREG.bit.VREFSEL = 1;
/* Set Low power Mode Efficiency
* for the Low Power Voltage Regulator (LPVREG)
* !!!! Apply this when power voltage is above 2.5 V !!!!
*/
SUPC->VREG.bit.LPEFF = 0x1;
}
Enter in Low Power
Once ready, the device can enter into Low-Power mode. There are two remaining steps before issuing the Wait For Interrupt (WFI) instruction:
- Select the Sleep mode required using the bitfield PM->SLEEPCFG.bit.SLEEPMODE.
- Check if the previous register write operation has been successfully performed.
{
/*** Sleep Mode is STANDBY ***/
PM->SLEEPCFG.bit.SLEEPMODE = PM_SLEEPCFG_SLEEPMODE_STANDBY_Val;
//Ensure register is written before issuing wfi command
while(PM->SLEEPCFG.bit.SLEEPMODE!=PM_SLEEPCFG_SLEEPMODE_STANDBY_Val);
// WAIT FOR IRQ
__WFI();
}
Exit From Low-Power
The CPU wakes-up only after a peripheral interrupt is issued.
This interrupt usually comes from the Event User Peripheral. In this step, the focus is on what will be implemented in the interrupt handler. SleepWalking doesn't alter classical interrupt handling. The interrupt flags must be cleared in the handler to enable subsequent interrupts.
Reconfigure Device for Active Mode
At this time, the first function to be executed must reconfigure the device to the appropriate operational state allowing it to operate in Active mode.
You have to take particular care to reconfigure the clocks, the performance levels, the Flash Wait States, etc.