System ON (Idle mode)

Help, please, I’ve been stuck for three days.

I’m working with the Seeed Studio XIAO nRF52840 (Sense) board, using Arduino. The board enters and exits deep sleep (NRF_POWER->SYSTEMOFF = 1;), but this doesn’t work for me. I need System ON (Idle mode).

“The system enters the lowest power consumption mode, where most peripherals, including the CPU and radio, are shut down. The only way to wake the system is via external events like GPIO pin interrupts or timer events.”

But the microcontroller doesn’t want to enter sleep mode.

__WFE();
/* Clear SEV flag if CPU was woken up by event */
__SEV();
__WFE();

Hi there,
So which BSP are you using? Paste the code using the Code Tags </> above
are you using an Interrupt as the wakeup? or timer?
HTH
GL :slight_smile: PJ :v:

Sleeping and waking up by button press

#define int1Pin 2

const int ledPin = 13; // set ledPin to on-board LED

uint8_t interruptCount = 0; // Amount of received interrupts
uint8_t prevInterruptCount = 0; // Interrupt Counter from last loop
uint8_t prevInterruptCountTest = 0; // Interrupt Counter from last loop

void setup() {
  Serial.begin(115200);
 // while ( !Serial ) delay(10);   // for nrf52840 with native usb
 delay(10);

  pinMode(ledPin, OUTPUT); // use the LED as an output
  
  Serial.println("Hello, I am awake!");

  setupDoubleTapInterrupt();

  pinMode(int1Pin, INPUT_PULLDOWN);
  attachInterrupt(digitalPinToInterrupt(int1Pin), int1ISR, RISING);
}

void loop() {
  setLED(false);
  Serial.print("Interrupt Counter: ");
  Serial.println(interruptCount);

  Serial.print("Interrupt Counter  TEST: ");
  Serial.println(interruptCount);

  if (interruptCount > prevInterruptCount) {
    Serial.println("Interrupt received!");
  }
  prevInterruptCount = interruptCount;

  if (interruptCount >= 1) {
    // Trigger System OFF after 5 interrupts
    goToPowerOff();
  }

  delay(500);
}

void goToPowerOff() {

  interruptCount = 0;
  Serial.println("Going to System OFF");
  setLED(true);
  setupDoubleTapInterrupt();
  delay(1000); // delay seems important to apply settings, before going to System OFF
  //Ensure interrupt pin from IMU is set to wake up device
  nrf_gpio_cfg_sense_input(digitalPinToInterrupt(int1Pin), NRF_GPIO_PIN_PULLDOWN, NRF_GPIO_PIN_SENSE_HIGH);
  delay(2000);// Trigger System OFF
  //NRF_POWER->SYSTEMOFF = 1;
  //__WFE();
  //sd_power_system_off(); // Використовувати цей метод, якщо використовується SoftDevice

  __WFE();
    /* Clear SEV flag if CPU was woken up by event */
 __SEV();
  __WFE();

}

void setupDoubleTapInterrupt() {

}

void int1ISR() {
  interruptCount++;
  prevInterruptCountTest++;
}

  void setLED(bool on)
  {
  // data = 1 -> LED = On
  // data = 0 -> LED = Off
  digitalWrite(LED_BUILTIN, on ? HIGH : LOW);
  }
![2024_09_15_15_59_12_StartApp_Arduino_IDE_2.3.2|690x255](upload://jbHUjuiplnTN8BsBTP4dXNXoJa4.png)

Hi there,
Ok, so I can compile it as an Mbed 2.9.0 & 2.9.2 No errors.
Serial output and taping GND pin with jumper from pin2. It stops but doesn’t sleep, same with removing the PIN2 > GND connection. So it is registering the interrupt.

Interrupt Counter: 22
Interrupt Counter TEST: 22
Interrupt received!
Going to System OFF
Interrupt Counter: 0
Interrupt Counter TEST: 0
Interrupt Counter: 0
Interrupt Counter TEST: 0
Interrupt Counter: 0
Interrupt Counter TEST: 0
Interrupt Counter: 0
Interrupt Counter TEST: 0
Interrupt Counter: 4
Interrupt Counter TEST: 4
Interrupt received!
Going to System OFF
Interrupt Counter: 0
Interrupt Counter TEST: 0

I would take a look at the demo I posted a while back and see if your logic is correct. I use the button to sleep and to wake.

HTH
GL :slight_smile: PJ :v:

I simplified the code to the maximum, and it still won’t go to sleep.

#include <Arduino.h>
#include <Wire.h>

const int ledPin = 13; // set ledPin to on-board LED

void setup() {
  Serial.begin(115200);

  while ( !Serial ) delay(10);   // for nrf52840 with native usb
  delay(10);
 
  Serial.println("Hello, I am awake!");
  goToPowerOff();

}

void loop() {

  setLED(false);
  Serial.println("loop");
  delay(1000);

}


void goToPowerOff() {

  Serial.println("Going to System OFF");
  setLED(true);

  Serial.end();
  delay(1000); // delay seems important to apply settings, before going to System OFF
  
  __WFE(); 
  __WFE(); 

}


void int1ISR() {

}

void setLED(bool on)
  {
  // data = 1 -> LED = On
  // data = 0 -> LED = Off
  digitalWrite(LED_BUILTIN, on ? HIGH : LOW);
}

Hi there,
I understand this part maybe it’s not setup correctly or the Event register isn’t clear?
"
We have 2 instructions for entering low-power standby state where most clocks are gated: WFI and WFE.

They differ slightly in their entry and wake-up conditions, with the main difference being that WFE makes use of the event register, the SEV instruction and EVENTI, EVENTO signals.

WFI is targeted at entering either standby, dormant or shutdown mode, where an interrupt is required to wake-up the processor.

A usage for WFE is to put it into a spinlock loop. Where a CPU wants to access a shared resource such as shared memory, we can use a semaphore flag location managed by exclusive load and store access. If multiple CPUs are trying to access the resource, one will get access and will start to use the resource while the other CPUs will be stuck in the spinlock loop. To save power, you can insert the WFE instruction into the loop so the CPUs instead of looping continuously will enter STANDBYWFE. Then the CPU who has been using the resource should execute SEV instruction after it has finished using the resource. This will wake up all other CPUs from STANDBYWFE and another CPU can then access the shared resource."

HTH
GL :slight_smile: PJ :v:

the last part is for the A5 arm chip.

Look at this thread to learn more.

So, does the loop() work?

Could you provide an example of your code?

Hi Vovanxp,
Have you tried Board Support Package "Seeed nRF52 Borads 1.1.8” ?
It is more effective than mbed BSP in reducing sleep current.

No

How do I find this board?

In ArduinoIDE.,Tools → Board → Board Manager
Search for “nRF52” and you will find “Seeed nRF52 Boards by Seeed Studio”.

Thank you, and is there any ready-made example of putting the microcontroller to sleep?

I don’t know if this is directly helpful for your project, but the link below has a sketch. My project needed to sleep for a certain amount of time, so I used the delay() function to enter SystemOnSleep. In this non-mbed BSP, just write delay() and it will go into SystemOnSleep.
Sleep Current of XIAO nRF52840, Deep Sleep vs. Light Sleep
System_ON_Sleep of XIAO BLE - #63 by msfujino

edit
I wrote a sketch for Wakeup with GPIO interrupt. Sleep current is about 25uA.
nRF52_XIAO_LighSleep_InterruptWakeup.zip (1.4 KB)