Encountering Core panic'ed when trying to use FreeRTOS queue in esp32

32 views Asked by At

I have an esp32 and i wish to use it to drive a HC-SR04 sonar module. I use interrupts to get information from sensors,then I use a queue to pass the data to a freertos task to output it. At first, it work and output the correct data, but after few second, it report an error and reboot.

Here is the error:

Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.

Core 1 register dump: 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 EXCCAUSE: 0x0000001c
EXCVADDR: 0x800d31d0 LBEG : 0x400899a4 LEND : 0x400899ba LCOUNT : 0xffffffff

Backtrace: 0x40084c8d:0x3ffbf53c |<-CORRUPTED

Then I found that if I delete the code that were used to push the data to the queue, it will work normally. So I guass that is the problem,but I don't Know how to fix it.

Here is main:

radar radar0(25,35);

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

Here is how radar class define:

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);
}

Thank for your help!
ps: Please forgive my poor English.I'm not a native speaker.

1

There are 1 answers

0
Hhehepei On

After hours of research, I found something in a post. It seems that in esp32 we can't use float in the interupt,because it will use the FPU , which is not allow to use inside an interrupt handler.
After remove float in my interrupt handler,the code finally work.