尝试在 esp32 中使用 FreeRTOS 队列时遇到核心恐慌

问题描述 投票:0回答:1

我有一个 esp32,我想用它来驱动 HC-SR04 声纳模块。我使用中断从传感器获取信息,然后使用队列将数据传递给 freertos 任务以输出它。一开始,它工作并输出正确的数据,但几秒钟后,它报告错误并重新启动。

这是错误:

古鲁冥想错误:核心 1 恐慌(加载禁止)。异常未处理。

核心 1 寄存器转储: PC:0x40084c90 PS:0x00050631 A0:0x800d31c4 A1:0x3ffbf53c
A2:0x00000040 A3:0x00018040 A4:0x000637ff A5:0x3ffbf50c A6:0x00000008 A7:0x00000000 A8:0x00000001 A9:0x4008bf6e
A10:0x00060b23 A11:0x3ffc4a14 A12:0x3ff44000 A13:0xffffff00 A14:0x00000000 A15:0x00000020 SAR:0x0000001d 借口:0x0000001c
EXCVADDR:0x800d31d0 LBEG:0x400899a4 借出:0x400899ba LCOUNT:0xffffffff

回溯:0x40084c8d:0x3ffbf53c |<-CORRUPTED

然后我发现,如果我删除用于将数据推送到队列的代码,它就可以正常工作。所以我猜这就是问题所在,但我不知道如何解决它。

主要内容如下:

radar radar0(25,35);

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200); 
  Serial.setDebugOutput(true);
  radar0.start();
} 

以下是雷达类别的定义:

class radar
{
private:
    uint8_t txPin,rxPin;
    Ticker loopTrigger; //ticker that use to trigger loop
    Ticker singalEnder; //ticker that use to generate a 1ms pulse
    QueueHandle_t dstQueue; //queue that use to pass dst to coroutine
    float previousDst;
    bool enable;
    unsigned long echoStartTime; //The time the echo start received
    void loop(); 
    void echoStartHandler(); //callback when the echo start
    void echoEndHandler(); //callback when the echo end
    void queueListener();
public:
    radar(uint8_t txPin,uint8_t rxPin);
    void start();
};
radar::radar(uint8_t txPin,uint8_t rxPin){
    this->txPin=txPin;
    this->rxPin=rxPin;
    this->enable=true;
    this->dstQueue = xQueueCreate(4,sizeof(float));
}

void radar::start(){
    //set pin mode
    pinMode(this->txPin,OUTPUT);
    pinMode(this->rxPin,INPUT);
    //low down the txPin
    digitalWrite(this->txPin,LOW);
    //Create a coroutine for listening to the dstQueue
    auto fn = [](void *arg){static_cast<radar*>(arg)->queueListener();};
    xTaskCreate(fn,"dstListener",1024,this,0,NULL);
    //enable the radar
    this->enable=true;
    this->loop();
}

void radar::queueListener(){
    float dst;
    while (this->enable)
    {
        if (xQueueReceive(this->dstQueue,&dst,0)==pdFALSE){
            //sleep 10ms if the queue is empty
            vTaskDelay(10/portTICK_PERIOD_MS);
            continue;
        }
        if (abs(dst-this->previousDst)>5){
            Serial.println(dst);
            this->previousDst=dst;
        }
    }
    vTaskDelete(NULL);
}

void radar::echoStartHandler(){
    this->echoStartTime = micros();
    //Set rxPin pull-down interrupt
    attachInterruptArg(rxPin,[](void* r){static_cast<radar*>(r)->echoEndHandler();},this,FALLING);
}

void radar::echoEndHandler(){
    detachInterrupt(this->rxPin);
    unsigned long echoEndTime = micros();
    float pluseTime;
    if (echoEndTime > this->echoStartTime){ //If the variable does not overflow
        pluseTime = echoEndTime - this->echoStartTime;
    }else{
        pluseTime = echoEndTime + (LONG_MAX - this->echoStartTime);
    }
    float dst = pluseTime * 0.0173;
    //push the dst to queue 
    BaseType_t xHigherPriorityTaskWoken;
    xQueueSendFromISR(this->dstQueue,&dst,&xHigherPriorityTaskWoken);
    if (xHigherPriorityTaskWoken==pdTRUE){
        portYIELD_FROM_ISR();
    }
}

void radar::loop(){
    if (!this->enable){
        return;
    }
    //Set loop() to be triggered after 100ms
    this->loopTrigger.once_ms<radar*>(100,[](radar* r){r->loop();},this);
    //Generate a 1ms pulse at txPin
    digitalWrite(this->txPin,HIGH);
    this->singalEnder.once_ms<uint8_t>(1,[](uint8_t pin){digitalWrite(pin,LOW);},this->txPin);
    //Set rxPin pull-up callback
    attachInterruptArg(rxPin,[](void* r){static_cast<radar*>(r)->echoStartHandler();},this,RISING);
}

感谢您的帮助!
ps: 请原谅我糟糕的英语。我不是母语人士。

c++ esp32 freertos
1个回答
0
投票

经过几个小时的研究,我在帖子中发现了一些东西。看来在esp32中我们不能在中断中使用float,因为它将使用FPU,而FPU不允许在中断处理程序中使用。
在我的中断处理程序中删除浮动后,代码终于可以工作了。

© www.soinside.com 2019 - 2024. All rights reserved.