Érico Pinto
Érico Pinto

Reputation: 1

Double exception/Guru Meditation Error: running book example for producer consumer problem with esp32cam got corrupted memory

My first question here. Please be patient.

I am running VS-Code with PlatformIO Windows10 VM, trying to run the first project from the book: Developing IOT projects with ESP32, Vedat Ozan Oner... https://github.com/PacktPublishing/Developing-IoT-Projects-with-ESP32-2nd-edition/blob/main/ch2/espidf_freertos_ex/src/main.cpp

platformio.ini:


[env:esp32cam]
platform = espressif32
board = esp32cam
framework = espidf
monitor_speed=115200
monitor_rts= 0
monitor_dtr= 0
monitor_filters=colorize

I made a lot of changes to understand what was the problem, including changing the priorities, sizes, places of declaration for producer and consumer, and board. But I always got the same error. Only when I deleted the consumer tasks I could run the producer task without problems.

I saw something similar here but I was not sure if it was the case, because I psram wasnt activated

Here is the log:

mI (307) app: application started
I (307) S�: 
consumer-1      R       5       1       3744    10
main            X       1       0       2036    4
IDLE1           R       0       1       1036    6
IDLE0           R       0       0       1232    5
producer        B       5       2147483647      3536    8
esp_timer       S       22      0       3576    3
ipc1            S       24      1       480     2
Tmr Svc         B       1       0       1476    7
consumer-0      B       5       0       3512    9
ipc0            S       24      0       488     1
m
Guru Meditation Error: Core  0 panic'ed (Double exception). 

Core  0 register dump:
PC      : 0x4008d36e  PS      : 0x00040136  A0      : 0x8008634c  A1      : 0x3ffb4e00
A2      : 0x00000003  A3      : 0x3f400fe4  A4      : 0x2d72656d  A5      : 0x20202030
A6      : 0x42092020  A7      : 0x30093509  A8      : 0x800d0e70  A9      : 0x3ffb4db0  
A10     : 0x00000003  A11     : 0x42092020  A12     : 0x3f4001b4  A13     : 0x00000133
A14     : 0x42092020  A15     : 0x3ffb4e10  SAR     : 0x00000004  EXCCAUSE: 0x00000002
EXCVADDR: 0x00000123  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xffffffb1  


Backtrace: 0x4008d36b:0x3ffb4e00 0x40086349:0x3ffb4f30 0x40086349:0x0d390932 |<-CORRUPTED

Just an example of many trials

#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/queue.h>
#include <esp_log.h>

#define TERMINATE_CONSUMER -1

namespace AppResources {
    QueueHandle_t m_number_queue;
    const constexpr int MAX_COUNT{10};
    const constexpr char *TAG{"app"};

void producer(void *p){
        int cnt{0};
        vTaskDelay(pdMS_TO_TICKS(500));
        while (++cnt <= MAX_COUNT){
            if(xQueueSendToBack(m_number_queue, &cnt, portMAX_DELAY) ==pdPASS){
                ESP_LOGI(TAG, "p:%d - Producer inserted successfully", cnt);
                // Notify the consumer task (if using notifications)
                // vTaskNotifyGive(consumer_handle);
            }else{
                ESP_LOGE(TAG, "Send to Queue failed at Count %d", cnt);
            }
        }
        int terminate_signal = TERMINATE_CONSUMER;
        xQueueSendToBack(m_number_queue, &terminate_signal, portMAX_DELAY);
        ESP_LOGI(TAG, "Producer finished, deleting task");
        vTaskDelete(nullptr);
    }; // end of producer

    void consumer(void *p){
        int num;

    //  ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

        while (true){
            if (xQueueReceive(m_number_queue, &num, portMAX_DELAY)== pdPASS){
                
                if (num == TERMINATE_CONSUMER) {
                    ESP_LOGI(TAG, "Consumer received termination signal.");
                    break; // Exit the loop and terminate the task
                }
                ESP_LOGI(TAG, "c%d:%d - Item receiced from the Queue", (int)(uintptr_t)p, num);
                vTaskDelay(pdMS_TO_TICKS(50));
                
            }else{
                ESP_LOGE(TAG, "Failed to receive item from the Queue");
            }
        }
        ESP_LOGI(TAG, "Consumer finished, deleting task");
        vTaskDelete(nullptr);
    }; // end of consumer
} // end of namespace

extern "C" void app_main() {
    //Uncomment this to Log the number of cores
    /*
    int core_count = portNUM_PROCESSORS;
    ESP_LOGI("CoreInfo", "Number of cores: %d", core_count);
    */
    ESP_LOGI(AppResources::TAG, "Application started.");

    AppResources::m_number_queue = xQueueCreate(5, sizeof(int));
    if (AppResources::m_number_queue == nullptr) {
        ESP_LOGE(AppResources::TAG, "Queue creation failed!");
        return;
    }else{
        ESP_LOGI(AppResources::TAG,"Queue Successful created at address %p", AppResources::m_number_queue);
        
        // Error handling for task creation
        if (xTaskCreate(AppResources::producer, "producer", 4096, nullptr, 5, nullptr) != pdPASS) {
            ESP_LOGE(AppResources::TAG, "Failed to create producer task!");
        }
        if (xTaskCreatePinnedToCore(AppResources::consumer, "consumer-0", 4096, (void *)0, 5, nullptr, 0) != pdPASS) {
            ESP_LOGE(AppResources::TAG, "Failed to create consumer task on core 0!");
        }
        if (xTaskCreatePinnedToCore(AppResources::consumer, "consumer-1", 4096, (void *)1, 5, nullptr, 1) != pdPASS) {
            ESP_LOGE(AppResources::TAG, "Failed to create consumer task on core 1!");
        }
    }

    char buffer[256]{0};
    vTaskList(buffer);
    ESP_LOGI(AppResources::TAG, "\n%s", buffer);
} // end of app main

Expecting a log of the queue

Upvotes: 0

Views: 46

Answers (1)

romkey
romkey

Reputation: 7109

At the end of app_main() you call vTaskList() with a buffer that's too small to hold its output.

char buffer[256]{0};
vTaskList(buffer);

Unfortunately vTaskList() has no parameter to specify the size of the buffer, but its documentation makes it clear that you should expect about 40 bytes per task to be sufficient. Your output shows at least 9 tasks, which would be 360 bytes. Your buffer is only 256 bytes long, so vTaskList() will overflow the buffer and may overwrite other things on the stack.

Increase the size of buffer to be large enough to hold the output - try 512:

char buffer[512]{0};
vTaskList(buffer);

You can also test this simply by commenting out the call to vTaskList().

A safer way to do this is to call vTaskListTasks() which does the same thing as vTaskList() but takes the size of the buffer as an argument:

#define TASK_BUFFER_SIZE 512

char buffer[TASK_BUFFER_SIZE]{0};
vTaskListTasks(buffer, TASK_BUFFER_SIZE);

Unlike vTaskList(), vTaskListTasks() knows the size of the output buffer and will not overrun it.

Upvotes: 2

Related Questions