call xTimerStop() too often cause "assert failed: prvProcessReceivedCommands timers.c:858 (xResult)" error and restart

policeman0077
Posts: 11
Joined: Mon Jul 16, 2018 8:52 pm

call xTimerStop() too often cause "assert failed: prvProcessReceivedCommands timers.c:858 (xResult)" error and restart

Postby policeman0077 » Tue Jan 30, 2024 5:44 pm

We have several robots have wonky limit switches which always pull high. So I put some code that when the robot move away from the end stop(limit switch from triggered state to release), I start a timer and wait for the release of the switch(interrupt). If robot detects the release(interrupt), it stop the timer. I tested the code and it works fine.

But one day, I found another robot has a limit switch toggling the high/low frequently and it restart itself. With some digging I found if xTimerStop() is being called too often too fast would "assert failed: prvProcessReceivedCommands timers.c:858 (xResult)" error.

Code: Select all

assert failed: prvProcessReceivedCommands timers.c:858 (xResult)


Backtrace: 0x40081b4e:0x3ffbb5f0 0x40088cd9:0x3ffbb610 0x4008f52d:0x3ffbb630 0x4008be9a:0x3ffbb750
0x40081b4e: panic_abort at C:/Users/Sam/esp/esp-idf/components/esp_system/panic.c:408

0x40088cd9: esp_system_abort at C:/Users/Sam/esp/esp-idf/components/esp_system/esp_system.c:137

0x4008f52d: __assert_func at C:/Users/Sam/esp/esp-idf/components/newlib/assert.c:85

0x4008be9a: prvProcessReceivedCommands at C:/Users/Sam/esp/esp-idf/components/freertos/timers.c:858
 (inlined by) prvTimerTask at C:/Users/Sam/esp/esp-idf/components/freertos/timers.c:600

My code look likes this:

main code start the robot from the end stop

Code: Select all

void robot_start()
{
	xTimerStart( xTimerSenChk, 0 );//Set a timer and wait for sensor interrupt from other direction 
        starMotor(CLEANING_DUTY);
}
interrupt handler send an event through the event queue

Code: Select all

static void IRAM_ATTR gpio_isr_handler(void* arg)
{
    uint32_t gpio_num = (uint32_t) arg;
    sensorTriggerTime=xTaskGetTickCountFromISR();
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
task for receiving event queue and clear timer.

Code: Select all

static void gpio_task_example(void* arg)
{                  
    uint32_t io_num;
    for(;;) {
        if(xQueueReceive(gpio_evt_queue, &io_num,  1000/ portTICK_PERIOD_MS)) { //portMAX_DELAY

            ESP_LOGD(TAG,"GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num));            
            leftSensorStatus = gpio_get_level(GPIO_LEFT_SENSOR);
            rightSensorStatus = gpio_get_level(GPIO_RIGHT_SENSOR);

            ESP_LOGD(TAG,"leftSensorStatus: %d rightSensorStatus: %d", leftSensorStatus, rightSensorStatus);

            if(gpio_callback && ((sensorTriggerTime-LastSensorTriggerTime)*1000/configTICK_RATE_HZ>20)){
		
		    //code determine if it is the correct sensor released
		    //if it is the correct sensor we call xTimerStop() to stop the timer
		    //else timer callback we let us know the sensor is not released
		    if( correct sensor is released)
		    {
		    	xTimerStop();
		    }
		    
                }
            }
            else
            {
                ESP_LOGI(TAG, "sensor trigger interval <20ms, debouce.");
            }
         
            LastSensorTriggerTime=sensorTriggerTime;
        }
    }
}
I thought it might not proper to call xTimerStop() if the timer is already stopped so I modified the code a bit and check the xTimer is dormant or not before by using xTimerIsTimerActive(). The code looks like this:

Code: Select all

 if( correct sensor is released)
 {
	if(xTimerIsTimerActive() != pdFALSE)//stop timer only when timer is active
	{
		xTimerStop();
	}
		    	
}

The problem seems gone after I did the modification. I also look the official document of xTimerStop() https://www.freertos.org/FreeRTOS-timer ... rStop.html It does not mention I could not call it if the timer is already stopped.

So what is the correct practice for it. Thank you in advance for any advice.

enviroment:
esp-idf 4.4.5
FreeRTOS Kernel V10.4.3

MicroController
Posts: 1605
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: call xTimerStop() too often cause "assert failed: prvProcessReceivedCommands timers.c:858 (xResult)" error and resta

Postby MicroController » Tue Jan 30, 2024 11:26 pm

I also look the official document of xTimerStop(). It does not mention I could not call it if the timer is already stopped.
It does mention though that you actually don't control the timer directly; in fact, under the hood you send 'commands' to the timer task via a queue. If you do that too quickly the queue may not be processed fast enough and become full, which in your case causes the assertion failure.

You can look into using the IDF's High Resolution Timer which you can control more directly. You should also consider electrically debouncing the signal before it even enters the ESP where it may trigger a burst of interrupts before the switch settles.

policeman0077
Posts: 11
Joined: Mon Jul 16, 2018 8:52 pm

Re: call xTimerStop() too often cause "assert failed: prvProcessReceivedCommands timers.c:858 (xResult)" error and resta

Postby policeman0077 » Thu Feb 01, 2024 2:34 am

Thank you MicroController for your reply. I will have a look the xTimer queue and command.
The circuit has a rc filter and a schmitter trigger for debouncing and the firmware checks if two consecutive interrupts is within 20ms.

Who is online

Users browsing this forum: No registered users and 70 guests