Using vfs_fat filesystem, makes ADC fail in continous mode with timeout

FrankJensen
Posts: 63
Joined: Sun Mar 10, 2024 9:34 pm

Using vfs_fat filesystem, makes ADC fail in continous mode with timeout

Postby FrankJensen » Tue Jan 28, 2025 10:08 am

Hi forum.

I have something, that behaves unexpected. I am running ADC in continous mode in one task, and use the file system totally independent in another task, but somehow just opening a file, even without writing anything, the ADC goes into timeout, when I call fclose.

If I make the ADC buffer really big, I can make this fault occur more random, sometimes days inbetween, but setting the buffer to what is enough, the fault occur everytime I access the filesystem - once an hour.

I have boiled the code down to a minimum, and the fault persists. I am using my own hardware with ESP32-S3-N16R8V, and I have repliceated the error on a original Espressif esp32-s3-devkitc-1.

I use Platformio, CPP and latest ESPIDF 5.3.1. The fault was also in 5.3.0.

I stop and start ADC in order to get the ADC back on track, but would like to get to the root of this. I suspect, that the DMA for the ADC might stop on fclose. If the DMA does not stop, I would expect an overflow, and this do not happen. A timeout indicates to me, that the dataflow has stopped.

Is there anything wrong with my code, or is it an actual bug. Input apreciated 8-)

The log looks like this:

Code: Select all

I (18775) ADC: Data OK
I (18775) ADC: Data OK
I (18775) ADC: Data OK
I (18785) ADC: Data OK
I (18785) ADC: Data OK
I (18785) ADC: Data OK
I (18795) ADC: Data OK
I (18795) ADC: Data OK
I (18795) ADC: Data OK
D (18805) wl_flash: read - src_addr= 0x00003000, size= 0x00001000
File opened
D (18805) wl_flash: erase_range - start_address= 0x00003000, size= 0x00001000
D (18805) wl_flash: erase_sector - sector= 0x00000003
I (18805) ADC: Data OK
I (18805) ADC: Data OK
I (18805) ADC: Data OK
D (18855) wl_flash: write - dest_addr= 0x00003000, size= 0x00001000
E (23805) ADC: Error ESP_ERR_TIMEOUT
E (23805) ADC: TIMEOUT!
E (28805) ADC: Error ESP_ERR_TIMEOUT
Code to replicate here:

Code: Select all

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "esp_log.h"
#include <cmath>
#include "esp_adc/adc_continuous.h"
#include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h"

#include "esp_vfs_fat.h"

#define ADS_STACK          6000      //  3500
#define ADC_BUFFER_SIZE    20480      // 10240
#define ADC_FRAME_SIZE      512      //  2560

#define ADC_TASK_STOP_BIT       (1 << 0)
#define ADC_TASK_OVERFLOW_BIT   (1 << 1)
#define ADC_TASK_TIMEOUT_BIT    (1 << 2)
#define ADC_TASK_READY_BIT      (1 << 3)

static const char *TAGFS = "FATFS";
static const char *TAG = "ADC";

bool fatfs_Struct(void* data, size_t size);
static void _task_adc(void* parameter);

char test_file[10];

wl_handle_t s_wl_handle;
EventGroupHandle_t adc_event_group = NULL;
adc_cali_handle_t adc_cali_handle;
adc_continuous_handle_t adc_handle{nullptr};

const char *path = "/fatfs";
uint8_t* result = NULL;
uint32_t ret_num = 0;

extern "C" void app_main(void)
{
    vTaskDelay(pdMS_TO_TICKS(3000));

    esp_log_level_set("vfs_fat", ESP_LOG_VERBOSE);
    esp_log_level_set("ff_diskio_spiflash", ESP_LOG_VERBOSE);
    esp_log_level_set("wl_flash", ESP_LOG_VERBOSE);

    // Mount configuration
    esp_vfs_fat_mount_config_t mount_config = {
        .format_if_mount_failed = true,
        .max_files = 5,
        .allocation_unit_size = CONFIG_WL_SECTOR_SIZE
    };

    // Mount the partition named "storage" as FAT with wear leveling
    esp_err_t ret = esp_vfs_fat_spiflash_mount_rw_wl(path, "storage", &mount_config, &s_wl_handle);

    if (ret != ESP_OK) {
        ESP_LOGE(TAGFS, "Failed to mount FATFS (%s)", esp_err_to_name(ret));
        if (ret == ESP_FAIL) {
            ESP_LOGE(TAGFS, "General failure, possibly due to incorrect partition size or label.");
        } else if (ret == ESP_ERR_NO_MEM) {
            ESP_LOGE(TAGFS, "Out of memory.");
        } else if (ret == ESP_ERR_NOT_FOUND) {
            ESP_LOGE(TAGFS, "Partition not found.");
        } else if (ret == ESP_ERR_INVALID_STATE) {
            ESP_LOGE(TAGFS, "Invalid state, possibly due to incorrect wear leveling configuration.");
        }
        while (1) {
            vTaskDelay(pdMS_TO_TICKS(10));
        }
    } else {
        ESP_LOGI(TAGFS, "FAT filesystem mounted");
    }

    ESP_LOGI(TAG, "Start task");

    result = (uint8_t*)heap_caps_malloc(ADC_BUFFER_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_DMA); // MALLOC_CAP_SPIRAM);
    std::fill(result, result + ADC_BUFFER_SIZE, 0);

    adc_event_group = xEventGroupCreate();

    xTaskCreatePinnedToCore(
        _task_adc,                  /* Task function. */
        "ads",                      /* String with name of task. */
        ADS_STACK,                  /* Stack size in words. */
        NULL,                       /* Parameter passed as input of the task */
        8,                          /* Priority of the task. */
        NULL,                       /* Task handle. */
        0);


    for(;;) {

        vTaskDelay(pdMS_TO_TICKS(15000));

        FILE* outFile = fopen("/fatfs/test.bin", "wb");
        if (outFile == NULL) {
            ESP_LOGE("FATFS", "Failed to open file for writing: %s", "/fatfs/test.bin");
            perror("Error"); // This will print a more detailed error
            while (1) {
                vTaskDelay(pdMS_TO_TICKS(10));
            }
        }

        printf("File opened\n");

        uint32_t  written = fwrite((uint8_t*)test_file, sizeof(test_file), 1, outFile);
        fclose(outFile);

        printf("/fatfs/test.bin have been written, size: %u %lu\n", sizeof(test_file), written);
    }
}

// ================ Ring buffer overflow callback: ==================================================
static bool IRAM_ATTR adc_pool_overflow_cb(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data)
{
    xEventGroupSetBitsFromISR(adc_event_group, ADC_TASK_OVERFLOW_BIT, NULL);

    return false; // Ssouldn't get to here.
}

void _task_adc(void* parameter)
{
//   adc_cali_handle_t adc_cali_handle;
    adc_cali_curve_fitting_config_t cali_config = { };
    cali_config.unit_id = ADC_UNIT_1;
    cali_config.atten = ADC_ATTEN_DB_12;
    cali_config.bitwidth = ADC_BITWIDTH_DEFAULT;
    ESP_ERROR_CHECK(adc_cali_create_scheme_curve_fitting(&cali_config, &adc_cali_handle));

// Configure AD for multiplex
    static adc_channel_t channel[4] = { ADC_CHANNEL_0, ADC_CHANNEL_1, ADC_CHANNEL_2, ADC_CHANNEL_8 };

    adc_continuous_handle_cfg_t adc_config = {};
    adc_config.max_store_buf_size = ADC_BUFFER_SIZE;
    adc_config.conv_frame_size = ADC_FRAME_SIZE;
    adc_continuous_new_handle(&adc_config, &adc_handle);

ESP_LOGE(TAG, "Size: %u", sizeof(channel)/sizeof(adc_channel_t));

    adc_digi_pattern_config_t adc_pattern[SOC_ADC_PATT_LEN_MAX] = { 0 };
    for (int i = 0; i < sizeof(channel)/sizeof(adc_channel_t); i++) {
        adc_pattern[i].atten = ADC_ATTEN_DB_12;                 // analog scale
        adc_pattern[i].channel = channel[i];                    // Kanal
        adc_pattern[i].unit = ADC_UNIT_1;                       // ADC1
        adc_pattern[i].bit_width = SOC_ADC_DIGI_MAX_BITWIDTH;   // Bit 12

ESP_LOGE(TAG, "Size: %u, num %i", sizeof(channel)/sizeof(adc_channel_t), i);

        ESP_LOGI(TAG, "adc_pattern[%d].atten is :%"PRIx8, i, adc_pattern[i].atten);
        ESP_LOGI(TAG, "adc_pattern[%d].channel is :%"PRIx8, i, adc_pattern[i].channel);
        ESP_LOGI(TAG, "adc_pattern[%d].unit is :%"PRIx8, i, adc_pattern[i].unit);
    }

    adc_continuous_config_t dig_cfg = {};
    dig_cfg.sample_freq_hz = 40000;            // ADC_TEST_FREQ_HZ,  40000
    dig_cfg.conv_mode = ADC_CONV_SINGLE_UNIT_1;     // Kun ADC1
    dig_cfg.format = ADC_DIGI_OUTPUT_FORMAT_TYPE2;  // Format 2, hvad det så end er......
    dig_cfg.adc_pattern = adc_pattern;
    dig_cfg.pattern_num = sizeof(channel)/sizeof(adc_channel_t);
    adc_continuous_config(adc_handle, &dig_cfg);

    adc_continuous_evt_cbs_t adc_callbacks =
    {
        .on_pool_ovf = adc_pool_overflow_cb,
    };
    ESP_ERROR_CHECK(adc_continuous_register_event_callbacks(adc_handle, &adc_callbacks, NULL) );

    ESP_LOGI(TAG, "About to start ADC");
    adc_continuous_start(adc_handle);

    for(;;) {

        EventBits_t bits = xEventGroupGetBits(adc_event_group);
        if (bits & ADC_TASK_OVERFLOW_BIT) {
            ESP_LOGE(TAG, "ADC buffer overflow detected!");
            xEventGroupClearBits(adc_event_group, ADC_TASK_OVERFLOW_BIT);
        }
        if (bits & ADC_TASK_TIMEOUT_BIT) { // TIMEOUT
            ESP_LOGE(TAG, "TIMEOUT!");
        }

        while (1) {

            esp_err_t ret_adc = adc_continuous_read(adc_handle, result, ADC_FRAME_SIZE, &ret_num, 5000);

            if (ret_adc == ESP_OK) {
                ESP_LOGI(TAG, "Data OK");
            } else if (ret_adc == ESP_ERR_TIMEOUT) {

                ESP_LOGE(TAG, "Error ESP_ERR_TIMEOUT");
                xEventGroupSetBits(adc_event_group, ADC_TASK_TIMEOUT_BIT);

/* This code will resume ADC if enabled
                vTaskDelay(1);
                adc_continuous_stop(adc_handle);
                vTaskDelay(1);
                adc_continuous_start(adc_handle);
                vTaskDelay(1);
*/
                break; // stop med at hente data fra ADC
            }
        }
    }
}

FrankJensen
Posts: 63
Joined: Sun Mar 10, 2024 9:34 pm

Re: Using vfs_fat filesystem, makes ADC fail in continous mode with timeout

Postby FrankJensen » Sun Feb 09, 2025 9:58 pm

Anyone? Is it just me? If someone can spot an error in the code, I would apreciate it, since it should be easy to replicate it, with the given code.

I have made a workaround, where I block filetransfers with a semaphore, when I use the ADC. But I would like to avoid this.

philippK
Posts: 4
Joined: Tue May 16, 2023 9:23 am

Re: Using vfs_fat filesystem, makes ADC fail in continous mode with timeout

Postby philippK » Mon Feb 10, 2025 8:13 am

I think I have got the same issue.
I also use an esp32s3, but with SPIFFS. So I guess it has something to do with the vfs in general.
Upon calling fwrite or fclose the adc continuous stops working. When calling adc_continuous_read after this I always receive ESP_ERR_TIMEOUT.

Additionally I can't even restart the adc when this happens, because as soon as I call adc_continuous_stop the processor crashes with this message

Code: Select all

assert failed: xTaskPriorityDisinherit tasks.c:5138 (pxTCB == pxCurrentTCBs[ xPortGetCoreID() ])
Let's hope someone from espressif sees this, because this seems like a rather large issue.

FrankJensen
Posts: 63
Joined: Sun Mar 10, 2024 9:34 pm

Re: Using vfs_fat filesystem, makes ADC fail in continous mode with timeout

Postby FrankJensen » Tue Feb 11, 2025 9:15 am

A little happy to hear, that its not only me... :D Your crash indicates a Mutex issue. Are you using mutex'es? Maybe they are not released correctly, in case that the ADC stops.

But anyway, ADC should not stop.

philippK
Posts: 4
Joined: Tue May 16, 2023 9:23 am

Re: Using vfs_fat filesystem, makes ADC fail in continous mode with timeout

Postby philippK » Fri Feb 14, 2025 5:54 am

I found out that, the task which starts adc continuous mode also has to stop it. If you try to stop from another task, it will crash like mentioned before.
Now I can restart the adc when it stops working, but this really is a suboptimal solution.

FrankJensen
Posts: 63
Joined: Sun Mar 10, 2024 9:34 pm

Re: Using vfs_fat filesystem, makes ADC fail in continous mode with timeout

Postby FrankJensen » Tue Feb 18, 2025 12:57 pm

Is it possible for someone to run the code supplied, and confirm if this is a bug, or if it can not be replicated?

ESP_adokitkat
Posts: 57
Joined: Thu Jun 22, 2023 12:50 pm

Re: Using vfs_fat filesystem, makes ADC fail in continous mode with timeout

Postby ESP_adokitkat » Tue Mar 04, 2025 4:11 pm

Hello. Indeed I can replicate your issue, it seems like a bug. I will try to look into it. Could you please create an issue on Github please? https://github.com/espressif/esp-idf/issues

This is how my log looks like:

Code: Select all

I (3516) vfs_fat_spiflash: Formatting FATFS partition, allocation unit size=4096
I (3736) vfs_fat_spiflash: Mounting again
I (3736) FATFS: FAT filesystem mounted
I (3736) ADC: Start task
E (3746) ADC: Size: 4
E (3746) ADC: Size: 4, num 0
I (3746) ADC: adc_pattern[0].atten is :3
I (3746) ADC: adc_pattern[0].channel is :0
I (3746) ADC: adc_pattern[0].unit is :0
E (3756) ADC: Size: 4, num 1
I (3756) ADC: adc_pattern[1].atten is :3
I (3756) ADC: adc_pattern[1].channel is :1
I (3766) ADC: adc_pattern[1].unit is :0
E (3766) ADC: Size: 4, num 2
I (3766) ADC: adc_pattern[2].atten is :3
I (3776) ADC: adc_pattern[2].channel is :2
I (3776) ADC: adc_pattern[2].unit is :0
E (3776) ADC: Size: 4, num 3
I (3786) ADC: adc_pattern[3].atten is :3
I (3786) ADC: adc_pattern[3].channel is :8
I (3786) ADC: adc_pattern[3].unit is :0
I (3796) ADC: About to start ADC
I (3796) ADC: Data OK
I (3806) ADC: Data OK
I (3806) ADC: Data OK
...
I (18766) ADC: Data OK
I (18766) ADC: Data OK
I (18776) ADC: Data OK
I (18776) ADC: Data OK
I (18776) ADC: Data OK
I (18776) ADC: Data OK
I (18786) ADC: Data OK
I (18786) ADC: Data OK
I (18786) ADC: Data OK
File opened
I (18796) ADC: Data OK
I (18796) ADC: Data OK
I (18796) ADC: Data OK
/fatfs/test.bin have been written, size: 10 1
E (23796) ADC: Error ESP_ERR_TIMEOUT
E (23796) ADC: TIMEOUT!
E (28796) ADC: Error ESP_ERR_TIMEOUT
E (28796) ADC: TIMEOUT!
E (33796) ADC: Error ESP_ERR_TIMEOUT
E (33796) ADC: TIMEOUT!
File opened
/fatfs/test.bin have been written, size: 10 1
E (38796) ADC: Error ESP_ERR_TIMEOUT
E (38796) ADC: TIMEOUT!
E (43796) ADC: Error ESP_ERR_TIMEOUT
E (43796) ADC: TIMEOUT!
E (48796) ADC: Error ESP_ERR_TIMEOUT
E (48796) ADC: TIMEOUT!
File opened
/fatfs/test.bin have been written, size: 10 1
E (53796) ADC: Error ESP_ERR_TIMEOUT
E (53796) ADC: TIMEOUT!
E (58796) ADC: Error ESP_ERR_TIMEOUT
E (58796) ADC: TIMEOUT!
E (63796) ADC: Error ESP_ERR_TIMEOUT
E (63796) ADC: TIMEOUT!
File opened
/fatfs/test.bin have been written, size: 10 1
E (68796) ADC: Error ESP_ERR_TIMEOUT
E (68796) ADC: TIMEOUT!
E (73796) ADC: Error ESP_ERR_TIMEOUT
E (73796) ADC: TIMEOUT!

Who is online

Users browsing this forum: No registered users and 48 guests