You need to enable JavaScript to run this app. ESP32基于FreeRTOS开发报xQueueGenericReceive断言失败错误如何解决
优惠活动
大模型
产品
解决方案
定价
更多

ESP32基于FreeRTOS开发报xQueueGenericReceive断言失败错误如何解决

问题描述

我正在开发一个ESP32项目,基于ESP32 Arduino和FreeRTOS实现,核心功能是按照指定频率采样模拟量并存入数组,再通过BLE将数据发送到用户侧应用。目前遇到如下报错无法推进:

/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:1443
(xQueueGenericReceive)- assert failed! abort() was called at PC
0x4008e1d5 on core 1

Backtrace: 0x40091b38:0x3ffe0b20 0x40091d69:0x3ffe0b40
0x4008e1d5:0x3ffe0b60 0x400d1a2d:0x3ffe0ba0 0x4008e525:0x3ffe0be0

Rebooting... ets Jun 8 2016 00:22:57

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:1 load:0x3fff0018,len:4 load:0x3fff001c,len:1044
load:0x40078000,len:8896 load:0x40080400,len:5816 entry 0x400806ac

已排查发现错误和中断中使用的信号量相关,但无法定位具体原因和解决方案,相关代码如下:

#include <ArduinoJson.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

#if CONFIG_FREERTOS_UNICORE
static const BaseType_t app_cpu = 0;
#else
static const BaseType_t app_cpu = 1;
#endif


//ADC Related Global Variables
static const uint16_t timer_divider = 80;
static const uint64_t timer_max_count = 1000;

static const int adc_pin = A0;

static const int BUF_SIZE = 1000;

static int buf[BUF_SIZE];
int Buff_Len = 0;
static int Read = 0;
static int Write = 0;
static int count = 0;
static float avg = 0;
int i = 0;
int BLE_flag = 0;
String cmd;

static hw_timer_t *timer = NULL;
static uint16_t val;
static int count1 = 0;

static SemaphoreHandle_t bin_sem = NULL;
static SemaphoreHandle_t bin_sem2 = NULL;
static portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
//ADC Related Global Variables

//BLE Global Variable
char Reading[4];
BLEServer *pServer = NULL;
BLECharacteristic *pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;

//Declaration BLE necessary Classes
#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"   // UART service UUID
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

class MyServerCallbacks:public BLEServerCallbacks
{
  void onConnect (BLEServer * pServer)
  {
    deviceConnected = true;
  };

  void onDisconnect (BLEServer * pServer)
  {
    deviceConnected = false;
  }
};

//BLE Global Variables

//Task Section 
void IRAM_ATTR onTimer ()
{
  //sampling
  xSemaphoreGiveFromISR (bin_sem2, &task_woken);
  if (task_woken)
    {
      portYIELD_FROM_ISR ();
    }
}

void move_to_Queue (void *parameters)
{
  while (1)
    {
      xSemaphoreTake (bin_sem2, portMAX_DELAY);
      if (Buff_Len == BUF_SIZE || count1 > 2000)
    {
      Serial.println ("Buffer is full");
      xSemaphoreGive (bin_sem);
    }
      else
    {
      // storing the instantaneous sample value to buffer
    }
    }
}

void BLE_Task (void *parameters)
{
  while (1) {
      xSemaphoreTake (bin_sem, portMAX_DELAY);
      Serial.println ("BLE");
      // sending the data
      delay (10);       // bluetooth stack will go into congestion, if too many packets are sent
    }
}

Serial.println ();
}
}

void setup ()
{
  // put your setup code here, to run once:
  Serial.begin (115200);
  vTaskDelay (1000 / portTICK_PERIOD_MS);

  //BLE Declarations
  BLEDevice::init ("UART Service");
  pServer = BLEDevice::createServer ();
  pServer->setCallbacks (new MyServerCallbacks ());
  BLEService *pService = pServer->createService (SERVICE_UUID);
  pTxCharacteristic = pService->createCharacteristic (CHARACTERISTIC_UUID_TX,
                              BLECharacteristic::
                              PROPERTY_NOTIFY);

  pTxCharacteristic->addDescriptor (new BLE2902 ());
  pService->start ();
  pServer->getAdvertising ()->start ();
  Serial.println ("Waiting a client connection to notify...");
  //BLE Declaration


  //ADC Semaphore and Timer Declarations
  bin_sem = xSemaphoreCreateBinary ();
  bin_sem2 = xSemaphoreCreateBinary ();

  if (bin_sem == NULL || bin_sem2 == NULL)
    {
      Serial.println ("Could not create semaphore");
      ESP.restart ();
    }
  xTaskCreatePinnedToCore (move_to_Queue,
               "move_to_Queue", 1024, NULL, 2, NULL, app_cpu);
  xTaskCreatePinnedToCore (BLE_Task,
               "BLE_Task", 2048, NULL, 2, NULL, app_cpu);

  timer = timerBegin (0, timer_divider, true);
  // Provide ISR to timer (timer, function, edge)
  timerAttachInterrupt (timer, &onTimer, true);
  // At what count should ISR trigger (timer, count, autoreload)
  timerAlarmWrite (timer, timer_max_count, true);
  // Allow ISR to trigger
  timerAlarmEnable (timer);
  vTaskDelete (NULL);
}

void loop ()
{
  // put your main code here, to run repeatedly:
}
解决方案
  1. 修复中断函数内的变量未定义问题
    你在onTimer中断函数中直接使用了task_woken变量,但没有提前声明,这是触发FreeRTOS断言错误的核心原因。按照FreeRTOS的API规范,使用xSemaphoreGiveFromISR时,pxHigherPriorityTaskWoken参数对应的变量必须在ISR内部声明为BaseType_t类型,初始值设置为pdFALSE,修改后代码如下:
void IRAM_ATTR onTimer ()
{
  BaseType_t task_woken = pdFALSE;
  // 此处添加ADC采样逻辑
  xSemaphoreGiveFromISR (bin_sem2, &task_woken);
  portYIELD_FROM_ISR(task_woken);
}
  1. 删除多余的无效代码
    BLE_Task函数结束后多了两处多余的闭合括号和Serial.println();语句,直接删除这部分无效代码,避免逻辑混乱。

  2. 临界资源加锁保护
    Buff_Len、count1属于在中断和任务中都会访问的共享变量,必须加自旋锁保护避免数据竞争,修改move_to_Queue函数如下:

void move_to_Queue (void *parameters)
{
  while (1)
  {
    xSemaphoreTake (bin_sem2, portMAX_DELAY);
    bool buf_full = false;
    portENTER_CRITICAL(&spinlock);
    buf_full = (Buff_Len == BUF_SIZE || count1 > 2000);
    if (!buf_full) {
      // 此处写入采样值到buf,更新Buff_Len、count1等变量
    }
    portEXIT_CRITICAL(&spinlock);
    if (buf_full) {
      Serial.println ("Buffer is full");
      xSemaphoreGive (bin_sem);
    }
  }
}
  1. 可选优化:高频中断场景下二进制信号量容易丢事件,建议替换为长度不小于16的队列来传输采样值,可靠性更高。

内容的提问来源于stack exchange,提问作者Eswar Reddy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 06:39:02