ESP32 FreeRtos Queue invokes [Guru Meditation Error: Core 0 panic'ed (LoadProhibited)]

ESP32 FreeRtos Queue invokes [Guru Meditation Error: Core 0 panic'ed (LoadProhibited)]

我在探索 ESP32 Wrover 模块上的 FreeRtos 功能时遇到了一个非常奇怪的问题。目前,我的程序中有两个任务。第一个任务将用于收集一些数据,第二个任务将专门用于将调试消息打印到串行监视器。这些任务使用队列来交换数据。由于我想在系统中创建更多任务,因此数据收集器任务接收队列作为参数结构的一部分。这是我的问题:如果数据收集器任务只向队列发送一条消息,程序就可以完美运行。但是,如果我试图向队列中添加另一条消息(如最后一段代码所示),它会迫使 CPU 遇到“LoadProhibited”异常。根据我在其他主题中的阅读,此问题通常是由于程序中某处访问了 NULL 指针引起的。但正如您在下面的代码中看到的,我试图通过在向队列中添加任何内容之前检查指针来添加一些保护。我还尝试增加任务的分配内存量,并将两个任务固定到核心 1。我仍然得到相同的结果。 这是主要的:

static QueueHandle_t debugMsgQueue      = NULL;
static QueueHandle_t sensorDataBufQueue = NULL;

TaskHandle_t debugTaskHandle        = NULL;
TaskHandle_t sensorTaskHandle       = NULL;

uint32_t sensorTaskWatchdog;

ESP32Time rtc;

void StreamDebugger(void* pvParameters) {
char debugMsg[_debugDataLength];

while (1) {
    if (debugMsgQueue != NULL) {
        if (xQueueReceive(debugMsgQueue, (void*)debugMsg, portMAX_DELAY) == pdPASS) {
            Serial.print(debugMsg);
        }
    }
}
}

void setup(){

Serial.begin(115200);
EEPROM.begin(_eepromSize);

/*CREATING GLOBAL DATA BUFFERS*/
debugMsgQueue       = xQueueCreate(5, sizeof(char[_debugDataLength]));
sensorDataBufQueue  = xQueueCreate(2, sizeof(char*));

if (debugMsgQueue == NULL || sensorDataBufQueue == NULL) {
    Serial.print("\r\nCouldn't create dataBuffers. Aborting operation.");
}

BaseType_t xReturned;

/*DEBUG MESSAGE HANDLER TASK*/
xReturned = xTaskCreate(StreamDebugger, "DEBUG", 2048, NULL, 1, &debugTaskHandle);
if (xReturned != pdPASS) {
    Serial.print("\r\nCouldn't create DEBUGTASK. Aborting operation.");
}

/*MEASURMENT HANDLER TASK*/
const ReadSensorsParameters sensorTaskDescriptor{ &debugMsgQueue,&sensorDataBufQueue,&sensorTaskWatchdog,rtc};

xReturned = xTaskCreate(ReadSensors, "GETDATA", 4096, (void*)&sensorTaskDescriptor, 1, &sensorTaskHandle);
if (xReturned != pdPASS) {
    Serial.print("\r\nCouldn't create GETDATATASK. Aborting operation.");
}
}

void loop(){

}

这是传感器数据收集器任务使用的结构:

typedef struct READSENTASKPARAMETERS {
QueueHandle_t* debugQueue;
QueueHandle_t* dataQueue;
uint32_t* watchdog;
ESP32Time &systemClock;
}ReadSensorsParameters;

这是数据收集器任务,有效的任务:

void ReadSensors(void* pvParameters) {
ReadSensorsParameters* handlers = (ReadSensorsParameters*) pvParameters;

char debugMsg[_debugDataLength];
char dataMsg[_msgDataMaxLength];

strcpy(debugMsg, "READSENSORTASK");
if (debugMsg != NULL && *handlers->debugQueue != NULL) {
    xQueueSend(*handlers->debugQueue, (void*)debugMsg, portMAX_DELAY);
}
vTaskDelete(NULL);
}

这是修改后的任务,由于某种原因根本不起作用:

void ReadSensors(void* pvParameters) {
ReadSensorsParameters* handlers = (ReadSensorsParameters*) pvParameters;

char debugMsg[_debugDataLength];
char dataMsg[_msgDataMaxLength];

strcpy(debugMsg, "READSENSORTASK");
if (debugMsg != NULL && *handlers->debugQueue != NULL) {
    xQueueSend(*handlers->debugQueue, (void*)debugMsg, portMAX_DELAY);
}
if (debugMsg != NULL && *handlers->debugQueue != NULL) {
    xQueueSend(*handlers->debugQueue, (void*)debugMsg, portMAX_DELAY);
}
vTaskDelete(NULL);
}

这是我收到的错误消息: rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) 配置:0,SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO,时钟 div:1 load:0x3fff0018,长度:4 load:0x3fff001c,长度:1044 load:0x40078000,len:8896 load:0x40080400,len:5816 条目 0x400806ac READSENSORTASKGuru 冥想错误:核心 0 恐慌(LoadProhibited)。异常未处理。 核心 0 寄存器转储: PC:0x400d0e5c PS:0x00060d30 A0:0x800889dc A1:0x3ffb2f80
A2:0x00000000 A3:0x3f400fad A4:0x3ffc07b8 A5:0x3ffb8058
A6:0x00000000 A7:0x00000000 A8:0x800d0e5a A9:0x3ffb2f70
A10:0x3ffb2f8a A11:0x3f400fbc A12:0x000000ff A13:0x0000ff00
A14:0x00ff0000 A15:0xff000000 SAR:0x00000010 借口:0x0000001c
EXCVADDR:0x00000000 LBEG:0x4000142d LEND:0x4000143a LCOUNT:0xfffffff3

回溯:0x400d0e5c:0x3ffb2f800x400889d9:0x3ffb2fe0

有人知道吗?

已解决!结果(经过几个不眠之夜)

static const MyTaskParameters sensorTaskDescriptor{
    &debugMsgQueue,
    &sensorDataBufQueue,
    &sensorTaskWatchdog,
    rtc,
    &sensorTaskWatchdogSemaphore,
    &rtcSemaphore
};

必须声明为静态变量。我认为发生的事情是,当创建 READSENSORTASK 时,它立即启动 运行 并且能够将数据放入输出缓冲区。在第一次上下文切换后,SETUP 任务被自动删除,因此这个 sensorTaskDescriptor 变量也被删除,这就是下一个消息放置调用 LoadProhibited 消息的原因。对我来说仍然很奇怪的是,我试图检查所有指向指针的指针是否为 NULL。我猜错误的调用是在 xQueueSend 函数内部的某个地方。 不管怎样,我希望这个帖子对某人有所帮助。