我想在 ESP32 上实现生产者/消费者任务。为此,有两个任务:第一个任务通过 I2C 读取输入并将其存储在队列中;第二个任务从队列中获取值。虽然,生产者持续提供数据,因此不能被搁置,同时消费者任务相对较慢,包括文件管理。 出于这个原因,我有两个队列,因此在消费者从其中一个队列获取值期间,消费者填充另一个队列。为此,我打算实现一种信号量,为他们应该使用的队列任务提供信息。
在执行过程中,收到以下错误信息:
ELF file SHA256: f835c00085624c05
Rebooting...
ets Jul 29 2019 12:21:46
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1184
load:0x40078000,len:13104
load:0x40080400,len:3036
entry 0x400805e4
assert failed: xQueueGenericSend queue.c:820 (pxQueue)
Backtrace: 0x40083585:0x3ffb4d80 0x400890c9:0x3ffb4da0 0x4008e10d:0x3ffb4dc0 0x400898ce:0x3ffb4ef0 0x400d1444:0x3ffb4f30
这里是相关代码:
#include <Arduino.h>
#include "esp_task_wdt.h"
TaskHandle_t Task1_f;
TaskHandle_t Task2_f;
void Task1code( void * pvParameters );
void Task2code( void * pvParameters );
static volatile QueueHandle_t queue;
enum semaphore_t {INSENDING, INRECEIVING, IDLE};
static volatile semaphore_t queue_semaphore;
void setup() {
xTaskCreatePinnedToCore(
Task1code, /* Task function. */
"Task1 - producer", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1_f, /* Task handle to keep track of created task */
0); /* pin task to core 0 */
xTaskCreatePinnedToCore(
Task2code, /* Task function. */
"Task2 - consumer", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
2, /* priority of the task */
&Task2_f, /* Task handle to keep track of created task */
1); /* pin task to core 1 */
queue = xQueueCreate(256, sizeof(uint8_t));
queue_semaphore = INSENDING;
Serial.begin(115200);
while(!Serial);
}
void Task1code( void * pvParameters ){
uint8_t l_counter = 0;
Serial.printf("%s running on core %d\n", "Task1code", xPortGetCoreID());
for(;;){
if(l_counter<100){
xQueueSend(queue, &l_counter, portMAX_DELAY);
l_counter++;
}else if(queue_semaphore==INSENDING){
queue_semaphore=INRECEIVING;
}else if(queue_semaphore==IDLE){
queue_semaphore=INSENDING;
l_counter=0;
}
esp_task_wdt_reset();
delay(5000);
}
}
void Task2code( void * pvParameters ){
uint8_t l_counter = 0;
Serial.printf("%s running on core %d\n", "Task2code", xPortGetCoreID());
for(;;){
if(queue_semaphore==INRECEIVING){
while(uxQueueSpacesAvailable(queue)!=256){
xQueueReceive(queue, &l_counter, portMAX_DELAY);
//...
}
queue_semaphore=IDLE;
}
esp_task_wdt_reset();
delay(3000);
}
}
void loop() {
vTaskDelete(NULL);
}
注:代码经过简化
我不确定 FreeRTOS 二进制信号量或互斥量是否可以解决问题,因为生产者任务无法暂停。