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 函数内部的某个地方。
不管怎样,我希望这个帖子对某人有所帮助。
我在探索 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 函数内部的某个地方。 不管怎样,我希望这个帖子对某人有所帮助。