Function with IRAM_ATTR gets blocked by spi flash operation in different task on different core
Posted: Fri Mar 21, 2025 8:16 am
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):
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:
My question is, how can I make a task, that runs continuously, even when a flash operation is ongoing?
My code is:
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);
}
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 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);
}