I am using an nRF52840 with SX1262 as a remote sensor. It achieves approximately 20 μA in normal use. I added a boot counter using the Adafruit LittleFS and InternalFileSystem libraries and can read and write files to the flash without problem. However, if I write to or delete a file, I can no longer put the nRF52840 to sleep: its current consumption rises to 660 μA and the red LED turns on. I assume something to do with flash is generating interrupts following a write.
Any ideas on how to debug this and shutdown the interrupts?
SO , looks like you’re close, Red LED state: The red LED turning on is a massive clue. Check your board definition or pin mappings (LED_BUILTIN or the red user LED on the XIAO nRF52840). Is the filesystem library or boot counter inadvertently toggling or holding a GPIO pin high, or is a peripheral error state triggering an error handler that drives the LED and blocks sleep?
Recommended Next Steps for Debugging:
Isolate the write: Write a minimal test sketch that boots, mounts LittleFS, performs one write, closes the file, and immediately enters a deep sleep state without running any BLE or sensor code. Check if the current still spikes to 660 µA. If it does, it confirms the LittleFS/InternalFS driver on the nRF52840 is leaving a clock or peripheral enabled.
Here is some code that demonstrates the problem. On a bare board with no external peripherals or SX1262 connected, I measure 7.5 μA when sleeping, but jumps to 650 μA following writing a byte to flash.
#include <Arduino.h>
#include <Adafruit_SPIFlash.h>
#include <RadioLib.h>
#include <InternalFileSystem.h>
#include <Adafruit_LittleFS.h>
const unsigned long kSerialSpeed = 115200;
/// other pin connections
const u_int32_t kPinBatEnable = 14; // Send LOW to enable voltage divider for battery monitor
const u_int32_t kPinBatADC = PIN_VBAT; // ADC pin connected to XIAO on-board battery voltage divider
const char kPathTest[] = "/testfile"; // LittleFS path to store sensor id
using namespace Adafruit_LittleFS_Namespace;
Adafruit_FlashTransport_QSPI flashTransport;
// task handle for direct to task notifications
// - faster than a semamphore
static TaskHandle_t xTaskToNotify = NULL;
bool ReadWriteFlash() {
if (!InternalFS.begin()) {
// unable to initialise InternalFS
return false;
}
uint8_t test_data[]{9};
Adafruit_LittleFS_Namespace::File file(InternalFS);
// open file for reading
file.open(kPathTest, FILE_O_READ);
// if file exists, read 1st byte and close
if (file) { // file exists
file.read((uint8_t*) &test_data, 1);
file.close();
}
/*
// write byte to file
file.open(kPathTest, FILE_O_WRITE);
if (file) {
file.seek(0);
file.write((uint8_t*) &test_data, 1);
file.close();
}
*/
InternalFS.end();
return true;
}
/**
* Power down the flash memory.
* (Saves approximately 10 µA.)
*/
void PowerDownFlash(void) {
flashTransport.begin();
flashTransport.runCommand(0xB9);
delayMicroseconds(5);
flashTransport.end();
}
/**
* Activate battery voltage measurement by connecting one end of the voltage divider to ground.
* NB although this increases total current consumption by several µA, this is necessary to
* avoid over-voltage of the ADC by the connected battery.
*/
void EnableVoltageDivider(void) {
pinMode(kPinBatEnable, OUTPUT);
digitalWrite(kPinBatEnable, LOW);
}
void setup() {
// necessary to prevent over-voltage of ADC pin
// - increases quiescent current by Vbat / 1.5E6
// - for 4.5 V supply : 3 microamps
EnableVoltageDivider();
// test read/write to flash storage
ReadWriteFlash();
// Use DC-DC converter to save power - best improvement is on high duty cycle
NRF_POWER->DCDCEN = 1;
// saves a few microamps
PowerDownFlash();
xTaskToNotify = xTaskGetCurrentTaskHandle();
while(true) {
// istop here and go to sleep until woken by interrupt
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
}
}
void loop() {
// never gets here
}