Hi all,
I've been trying to get my Arduino Nano 33 BLE into a low power sleep mode, which should wake on a specific interrupt/"event" (such as a push button) and then simply continue. However, this does not seem to work as expected, yet.
Note: I am specifically referring to the "system ON" sleep mode as described in the NRF52840 reference/docs from the Nordic website, NOT a simple delay as i need to actually save power, nor the "system OFF" mode (NRF_POWER->SYSTEMOFF = 1
) as I do not want a reset.
What I have tried so far:
There does not seem to be a nice Arduino solution for this problem with this board anyway. But, looking at the ArduinoLowPower library source and NRF52840 SDK, I believe that the proper way to reach this kind of sleep state should be using sd_app_evt_wait();
like so:
#include "nrf_gpio.h"
#include "nrf_nvic.h"
#include "nrf_soc.h"
#include "pinDefinitions.h"
#define PIN_PUSH_BUTTON 2
void setup()
{
//Configure RGB LED
pinMode(22, OUTPUT);
pinMode(23, OUTPUT);
pinMode(24, OUTPUT);
digitalWrite(22, HIGH);
digitalWrite(23, HIGH);
digitalWrite(24, LOW);
nrf_gpio_cfg_sense_input(g_APinDescription[PIN_PUSH_BUTTON].name, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
}
void loop()
{
digitalWrite(24, HIGH);
sd_app_evt_wait();
digitalWrite(24, LOW);
}
This compiles fine, however, as I can tell from the LED, sd_app_evt_wait();
always immediately wakes up again.
If I go to "system OFF" mode instead, via
void loop()
{
digitalWrite(24, HIGH);
NRF_POWER->SYSTEMOFF = 1;
digitalWrite(24, LOW);
}
the LED stays off until the reset when I press the push button.
Does someone know, whether sd_app_evt_wait();
is just not fully supported by the mbed core for some reason or whether there is some other default interrupt that I did not consider?
I did some further research and the problem is likely related to some unhandled "event"/interrupt, as "system OFF" only wakes from a very limited set of interrupts, in contrast to "system ON".
Also, if I put noInterrupts();
just before sd_app_evt_wait();
, it does not wake up again (i.e. the function call itself works in principle).
Additionally, I tried to clear all IRQs that I could find in the headers before going to sleep (+ some FPU-related fix):
sd_nvic_ClearPendingIRQ(Reset_IRQn);
sd_nvic_ClearPendingIRQ(NonMaskableInt_IRQn);
sd_nvic_ClearPendingIRQ(HardFault_IRQn);
sd_nvic_ClearPendingIRQ(MemoryManagement_IRQn);
sd_nvic_ClearPendingIRQ(BusFault_IRQn);
sd_nvic_ClearPendingIRQ(UsageFault_IRQn);
sd_nvic_ClearPendingIRQ(SVCall_IRQn);
sd_nvic_ClearPendingIRQ(DebugMonitor_IRQn);
sd_nvic_ClearPendingIRQ(PendSV_IRQn);
sd_nvic_ClearPendingIRQ(SysTick_IRQn);
sd_nvic_ClearPendingIRQ(POWER_CLOCK_IRQn);
sd_nvic_ClearPendingIRQ(RADIO_IRQn);
sd_nvic_ClearPendingIRQ(UARTE0_UART0_IRQn);
sd_nvic_ClearPendingIRQ(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn);
sd_nvic_ClearPendingIRQ(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn);
sd_nvic_ClearPendingIRQ(NFCT_IRQn);
sd_nvic_ClearPendingIRQ(GPIOTE_IRQn);
sd_nvic_ClearPendingIRQ(SAADC_IRQn);
sd_nvic_ClearPendingIRQ(TIMER0_IRQn);
sd_nvic_ClearPendingIRQ(TIMER1_IRQn);
sd_nvic_ClearPendingIRQ(TIMER2_IRQn);
sd_nvic_ClearPendingIRQ(RTC0_IRQn);
sd_nvic_ClearPendingIRQ(TEMP_IRQn);
sd_nvic_ClearPendingIRQ(RNG_IRQn);
sd_nvic_ClearPendingIRQ(ECB_IRQn);
sd_nvic_ClearPendingIRQ(CCM_AAR_IRQn);
sd_nvic_ClearPendingIRQ(WDT_IRQn);
sd_nvic_ClearPendingIRQ(RTC1_IRQn);
sd_nvic_ClearPendingIRQ(QDEC_IRQn);
sd_nvic_ClearPendingIRQ(COMP_LPCOMP_IRQn);
sd_nvic_ClearPendingIRQ(SWI0_EGU0_IRQn);
sd_nvic_ClearPendingIRQ(SWI1_EGU1_IRQn);
sd_nvic_ClearPendingIRQ(SWI2_EGU2_IRQn);
sd_nvic_ClearPendingIRQ(SWI3_EGU3_IRQn);
sd_nvic_ClearPendingIRQ(SWI4_EGU4_IRQn);
sd_nvic_ClearPendingIRQ(SWI5_EGU5_IRQn);
sd_nvic_ClearPendingIRQ(TIMER3_IRQn);
sd_nvic_ClearPendingIRQ(TIMER4_IRQn);
sd_nvic_ClearPendingIRQ(PWM0_IRQn);
sd_nvic_ClearPendingIRQ(PDM_IRQn);
sd_nvic_ClearPendingIRQ(MWU_IRQn);
sd_nvic_ClearPendingIRQ(PWM1_IRQn);
sd_nvic_ClearPendingIRQ(PWM2_IRQn);
sd_nvic_ClearPendingIRQ(SPIM2_SPIS2_SPI2_IRQn);
sd_nvic_ClearPendingIRQ(RTC2_IRQn);
sd_nvic_ClearPendingIRQ(I2S_IRQn);
sd_nvic_ClearPendingIRQ(FPU_IRQn);
sd_nvic_ClearPendingIRQ(USBD_IRQn);
sd_nvic_ClearPendingIRQ(UARTE1_IRQn);
sd_nvic_ClearPendingIRQ(QSPI_IRQn);
sd_nvic_ClearPendingIRQ(CRYPTOCELL_IRQn);
sd_nvic_ClearPendingIRQ(PWM3_IRQn);
sd_nvic_ClearPendingIRQ(SPIM3_IRQn);
__set_FPSCR(__get_FPSCR() & ~(0x0000009F));
(void) __get_FPSCR();
sd_nvic_ClearPendingIRQ(FPU_IRQn);
But this made no difference as well.
Any advice?
Thanks!