Understanding and Managing Memory on the Arduino Nano RP2040 Connect

Hello everyone,

I’m working with the Arduino Nano RP2040 Connect and have run into some questions regarding memory management. I’d like to understand how to better manage, monitor, and possibly reset memory on this board, particularly while working with both Wi-Fi and BLE functionality. Here are some specific questions I have:

  1. RAM and Flash Memory Details :
  • Could anyone confirm the exact specifications for RAM and flash memory on the Arduino Nano RP2040 Connect? I know it has 264 KB of SRAM and 16 MB of external flash, but I'm curious if there are any nuances in how this memory is split or managed internally by the board.
  1. Resetting or Clearing RAM and Flash Memory :
  • Is there a way to reset or clear memory on this board without having to power-cycle it?
  • Are there recommended practices for clearing SRAM or handling flash memory specifically? For example, if I want to ensure no residual data is affecting my code, are there functions or commands to do this?
  1. Monitoring Available Memory (SRAM):
  • Since traditional methods like freeMemory() or sbrk() don’t seem to provide accurate readings on this board, are there alternative ways to monitor memory usage on the RP2040?
  • If anyone has used specific libraries or RTOS setups for monitoring memory on the RP2040, I'd love to hear your experiences.
  1. Memory Optimization Tips for Wi-Fi and BLE Use:
  • I’m currently running both Wi-Fi and BLE on this board and suspect it’s causing some memory-related issues with I2C communications.
  • If anyone has recommendations on managing memory while running both Wi-Fi and BLE, I’d really appreciate any advice on memory-efficient code practices or known optimizations for this board.

Thank you for any help you can provide! I look forward to learning more about how to effectively manage memory on the Arduino Nano RP2040 Connect.

Your whole premis that you have to somehow reset the memory is wrong, you don't. What do you ever mean by resetting memory? Either the memory contains useful code (flash) or variables (RAM) or it doesn't. If you are having problems with code and those problems seem to be memory related, or indeed whatever they seem to be, then there's something wrong with your code.

Please post the code and describe the problem.

Don't forget the code tags.

1 Like

Thank you for your response, well here s my problem, there s a rasberri PI wiznet w5500 as a master and arduino nano rp2040 connect as slave, the slave role is to mesure either WIFI or BLE depending on specific command received by I2C protocol, here s the slave code :

#include <WiFiNINA.h>
#include <ArduinoBLE.h>
#include <Wire.h>

#define SLAVE_ADDRESS 8
constexpr long TIMEOUT_DURATION = 3000;  // 3 seconds timeout for BLE reading
constexpr int OUTPUT_SIZE = 21;

char output[OUTPUT_SIZE];                // Fixed-size buffer for output
char command = '\0';
bool mesure_done = false;
bool mesure_done_slave = false;
bool results_sent = false;
unsigned long debut_mesures;

extern "C" char* sbrk(int incr);

int freeMemory() {
  char stack_dummy = 0;
  return &stack_dummy - sbrk(0);
}

void setup() {
  Wire.begin(SLAVE_ADDRESS);
  Wire.onReceive(receiveEvent);
  Wire.onRequest(requestEvent);
  Serial.begin(9600);

  // Set up LED pins if needed
  pinMode(LEDR, OUTPUT);
  pinMode(LEDG, OUTPUT);
  pinMode(LEDB, OUTPUT);

  activateBLE();
  Serial.print("Initial Free Memory: ");
  Serial.println(freeMemory());  // Print initial free memory
}

void loop() {
  Serial.print("Free Memory in Loop: ");
  Serial.println(freeMemory());  // Monitor free memory periodically in loop

  if (command == 'W') {
    listNetworks();
    Serial.print("Free Memory after Wi-Fi scan: ");
    Serial.println(freeMemory());  // Check memory after Wi-Fi scan
    command = '\0';
  } else if (command == 'B') {
    readBLE();
    Serial.print("Free Memory after BLE read: ");
    Serial.println(freeMemory());  // Check memory after BLE read
  }

  delay(1000);  // Delay to avoid overwhelming the Serial monitor
}

void receiveEvent(int howMany) {
  if (howMany > 0) {
    command = Wire.read();
    Serial.println("Received command via I2C");
  }
}

void requestEvent() {
  if (!mesure_done_slave) {
    Wire.write('F');
    Serial.println("Measurement not done yet");
  } else {
    if (results_sent) {
      Wire.write(output, OUTPUT_SIZE);
      memset(output, 0, OUTPUT_SIZE);  // Clear buffer
      results_sent = false;
      mesure_done_slave = false;
    } else {
      Wire.write('S');
      Serial.println("Sent 'S' to indicate data ready");
      results_sent = true;
    }
  }
}

void listNetworks() {
  BLE.end();
  delay(100);  // Allow time for BLE to deactivate
  WiFi.end();
  delay(100);

  int herbsrssi = 0;
  int Linkyrssi = 0;
  debut_mesures = millis();
  int numSsid = WiFi.scanNetworks();

  if (numSsid == -1) {
    Serial.println("Couldn't get a WiFi connection");
    return;
  }

  // Scan for specific networks and get RSSI values
  for (int i = 0; i < numSsid; i++) {
    if (strcmp(WiFi.SSID(i), "Linksys02978") == 0) {
      Linkyrssi = WiFi.RSSI(i);
    }
    if (strcmp(WiFi.SSID(i), "HERBS_AP") == 0) {
      herbsrssi = WiFi.RSSI(i);
    }
  }

  // Build output message using snprintf for memory efficiency
  snprintf(output, OUTPUT_SIZE, "%s,%s,%s,%lu",
           (herbsrssi != 0) ? String(herbsrssi).c_str() : "KO",
           (Linkyrssi != 0) ? String(Linkyrssi).c_str() : "KO",
           "/",
           millis() - debut_mesures);

  while (strlen(output) < OUTPUT_SIZE - 1) {
    strcat(output, "*");  // Pad with '*' to fill remaining buffer
  }
  mesure_done_slave = true;
}

void readBLE() {
  activateBLE();
  memset(output, 0, OUTPUT_SIZE);  // Clear output buffer
  strcpy(output, "/,/,");

  BLE.scanForName("Arduino Nano RP2040", true);
  debut_mesures = millis();

  while (!mesure_done && ((millis() - debut_mesures) < TIMEOUT_DURATION)) {
    BLEDevice device = BLE.available();
    if (device) {
      snprintf(output + strlen(output), OUTPUT_SIZE - strlen(output), "/,/,%d,", device.rssi());
      mesure_done = true;
    }
  }

  if (!mesure_done) {
    strcat(output, "/,/,KO");
  }

  snprintf(output + strlen(output), OUTPUT_SIZE - strlen(output), "%lu", millis() - debut_mesures);
  while (strlen(output) < OUTPUT_SIZE - 1) {
    strcat(output, "*");
  }

  mesure_done_slave = true;
  mesure_done = false;
  command = '\0';
}

void activateBLE() {
  BLE.end();
  delay(100);
  WiFi.end();
  delay(100);

  if (!BLE.begin()) {
    Serial.println("Failed to initialize BLE!");
    while (true);
  }
}

After some execution time, the slave crashes and a blinking orange LED start appearing. In the begining, i suspected it maybe be I2C bus problem but after doing a sample ping pong program for i2c exchange over 8 hours no problem happened. The **CODE I PROVIDED ABOVE ** is a revised one after getting ride of string type and all possible dynamic memory allocation it greatly reduce how frequently the problem happened, i suspect that alternating wifi and BLE is causing a large chunk of memory to be occupied maybe? I didn t find a specific library or method that allows to monitor free memory, i tried the one in the code i posted but it was returing a fixe large negative value.

Thank you.
That's beyond my ability to help, I'm sure someone else better able to understand code problems will be along soon.

not all of them ...

I would advise to just keep a %d and have the value and if it's 0 then you know it's an issue


command should be volatile and you should not use Serial within receiveEvent() or requestEvent() as you are within an interrupt context

have you tried a Wire.setClock() at a lower speed ?

1 Like

Since the rp2040 Connect runs MBed software, you might be able to use the MBed memory statistics functions, if they are enabled in the Arduino library build: Mbed statistics - API references and tutorials | Mbed OS 6 Documentation

(And it looks like they are enabled: ArduinoCore-mbed/variants/NANO_RP2040_CONNECT/conf/mbed_app.json at 2c40ba8d0ea6339f8a24577ed849e872532e8fb4 · arduino/ArduinoCore-mbed · GitHub )

Forgive me for the possibly foolish question, but, what is this mbed? Is it something that comes with Arduino?

It is one of the operating systems for the RP2040. The other one is FreeRTOS. They provide functions to support multiprocessing.

1 Like

MBED is a multi-tasking operating system that Arduino uses on most of its more advanced ARM platforms that have networking support. Among other things, it permits implements the TCP/IP stack more "transparently" then when you try to do networking on one of the less powerful platforms.

thank you for your response, yes i tried the set the Clock at lower speed but same problem, i read at another post when arduino nano rp 2040 Connect has a blinking orange LED with pattern 4 times slow then 4 times slow means "SOS" which is equivalent to say the board has crashed.

have you removed the Serial prints from your callback functions and made the variables that are used in both contexts volatile?

1 Like

thank you ! i will try it out .

Thank you for the suggestion. After further investigation, I realized the issue wasn't with the I2C communication as I initially thought. Instead, the problem was linked to switching between BLE and Wi-Fi, which caused a memory leak and eventually led to board crashes. I found a forum post discussing this exact issue and tested it by running the switching code on a separate Arduino Nano RP2040. The board exhibited the same crash behavior after a random execution time, confirming the cause.

OK thx for sharing the explanation

I had kinda similar issue in the past, where using BLE together with u8g2 was causing super random, very hard to catch crashes. Was never able to solve that properly, so ended up using separate board just for u8g2 ...
The board was Nano 33 BLE, though

So I can't help much other then... Any specific reason to use Mbed?
Have you considered giving Pico core a try?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.