Page 1 of 1

Function with IRAM_ATTR gets blocked by spi flash operation in different task on different core

Posted: Fri Mar 21, 2025 8:16 am
by t23319222
Hi,

I want to write a function that gets executed even during a flash write operation. I have already tried this:
I have delared two tasks (on different cores):

Code: Select all

void setup() {
   Serial.begin(9600);
   delay(2000);
   // Create task1 on Core 0
   xTaskCreatePinnedToCore(task1, "Task1", 2048, NULL, 1, NULL, 0);
   // Create task2 on Core 1
   xTaskCreatePinnedToCore(task2, "Task2", 4096, NULL, 2, NULL, 1);
}
task1: increments a counter continuously
task2: writes to flash memory for 5 seconds and then waits 5 seconds

During the 5 seconds of writing to flash the counter only gets incremented by about 400, and in the 5 second interval when there is no write happening, the counter gets incremented by 4000:

Pogram output:
write start:
Counter: 2
Counter: 112
Counter: 223
Counter: 331
Counter: 437
write end
Counter difference during flash write: 536
Counter: 604
Counter: 1604
Counter: 2604
Counter: 3604
Counter: 4604
Starting flash write to app1...
write start

And this happens even though I put a iram attribute on the counter function:

Code: Select all

void IRAM_ATTR task1(void *pvParameter) {
   while (1) {
       counter++;  // Increment counter continuously
       vTaskDelay(1 / portTICK_PERIOD_MS);  // Small delay
   }
}
My question is, how can I make a task, that runs continuously, even when a flash operation is ongoing?
My code is:

Code: Select all

#include <Arduino.h>
#include "esp_partition.h"
volatile uint32_t counter = 0;  // Shared counter
void IRAM_ATTR task1(void *pvParameter) {
   while (1) {
       counter++;  // Increment counter continuously
       vTaskDelay(1 / portTICK_PERIOD_MS);  // Small delay
   }
}
void task2(void *pvParameter) {
 // Locate the app1 partition
 const esp_partition_t* partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_1, NULL);
 if (!partition) {
     Serial.println("app1 partition not found!");
     return;
 }
 while (1) {
     Serial.println("Starting flash write to app1...");
     uint32_t startCounter = counter;
     Serial.println("------------ write start ----------------");
     auto start = millis();
     do
     {
          // Data to write
         uint8_t data[256] = {0x55};  // 256 bytes of dummy data (0x55 pattern)
         // Erase sector before writing (necessary for raw flash writes)
         esp_err_t err = esp_partition_erase_range(partition, 0, 4096);
         if (err == ESP_OK) {
             err = esp_partition_write(partition, 0, data, sizeof(data));
         }
     } while (millis() - start < 5000);
     Serial.println("------------ write end ----------------");
     uint32_t endCounter = counter;
     Serial.printf("Counter difference during flash write: %d\n", endCounter - startCounter);
     // Wait before the next write
     vTaskDelay(5000 / portTICK_PERIOD_MS);
 }
}

void setup() {
   Serial.begin(9600);
   delay(2000);
   // Create task1 on Core 0
   xTaskCreatePinnedToCore(task1, "Task1", 2048, NULL, 1, NULL, 0);
   // Create task2 on Core 1
   xTaskCreatePinnedToCore(task2, "Task2", 4096, NULL, 2, NULL, 1);
}
void loop() {
   // Print counter value every second
   Serial.printf("Counter: %d\n", counter);
   delay(1000);
}

Re: Function with IRAM_ATTR gets blocked by spi flash operation in different task on different core

Posted: Fri Mar 21, 2025 10:58 am
by MicroController
All tasks (except for one) are stopped during writes to flash. The only thing which stays alive is interrupt service routines (ISR) that are in IRAM and registered as such; functions have to be put into IRAM so that they can be called from IRAM ISRs even during flash writes.