esp_timer: timer queue overflow
Posted: Wed Jul 04, 2018 5:07 pm
Using the high resolution timer, all is good for periods above a few microseconds.
If I use a period of 0, after a handful of callbacks, I get esp_timer: timer queue overflow
Obviously it is a bit of a waste to setup a timer with a callback with a time of 0, but it is sometimes convenient to save a lot of redesign with the case of 0, and it seems the queue is not getting cleared up fast enough to allow a callback to setup a further timer with a period of 0.
I can see the error comes from xSemaphoreGiveFromISR(s_timer_semaphore, &need_yield) != pdPASS) in esp_timer.c
Here is my timer setup code:
Here is the callback code:
Given that I am stopping and deleting the timer in the callback, before making it again, it seems there is an asynchronous process to clear up the queue that means a timer cannot be immediately used again? I tried increasing the FreeRTOS timer queue size from 10 to 20 and task priority from 1 to 24 with no change.
I can work around it. I could also perhaps just do it differently without a timer if the timer value is less than 100us (since the valid timer intervals are in units of 100us and the lowest two valid values are 0 or 100us). I am just curious why this happens most of all.
If I use a period of 0, after a handful of callbacks, I get esp_timer: timer queue overflow
Obviously it is a bit of a waste to setup a timer with a callback with a time of 0, but it is sometimes convenient to save a lot of redesign with the case of 0, and it seems the queue is not getting cleared up fast enough to allow a callback to setup a further timer with a period of 0.
I can see the error comes from xSemaphoreGiveFromISR(s_timer_semaphore, &need_yield) != pdPASS) in esp_timer.c
Here is my timer setup code:
Code: Select all
bool my_set_timer(uint32_t timer_number, uint32_t time_us, void (*callback)(void *), void *params)
{
//if (time_us==0) time_us=4;
//stop & delete previous timer
if (my_timer_info[timer_number].my_timer)
{
printf("Timer %d exists - stopping and deleting\n",timer_number);
esp_timer_stop(my_timer_info[timer_number].my_timer);
esp_timer_delete(my_timer_info[timer_number].my_timer);
my_timer_info[timer_number].my_timer=NULL;
}
//timer arguments
esp_timer_create_args_t my_timer_args;
my_timer_args.callback = (esp_timer_cb_t)HRT_callback; //!< esp_timer_cb_t Function to call when timer expires
my_timer_args.arg = (void*)(&my_timer_info[timer_number]); //!< void* Argument to pass to the callback
my_timer_args.dispatch_method = ESP_TIMER_TASK; //!< esp_timer_dispatch_t Call the callback from task or from ISR
char timer_name[10];
sprintf(timer_name, "ISOTP%d", timer_number);
my_timer_args.name = timer_name; //!< const char* Timer name, used in esp_timer_dump function
//create timer handle (esp_timer_create(IN,OUT))
if (esp_timer_create(&my_timer_args, &my_timer_info[timer_number].my_timer)!=ESP_OK)
{
my_timer_info[timer_number].my_timer=NULL;
}
if (my_timer_info[timer_number].my_timer==NULL)
{
printf("Error esp_timer_create!\n");
return false;
}
//info for HRT_callback
my_timer_info[timer_number].callback=callback;
my_timer_info[timer_number].params=params;
//start timer
if (esp_timer_start_once(my_timer_info[timer_number].my_timer, time_us)!=ESP_OK)
{
printf("Error calling esp_timer_start!\n");
return false;
}
else
{
//printf("esp_timer_start success\n");
//printf("timer_number %d, time_us %d\n",timer_number,time_us);
return true;
}
}
Code: Select all
void HRT_callback(struct timer_info* base)
{
//printf("HRT_callback\n");
if (base->my_timer)
{
esp_timer_stop(base->my_timer);
esp_timer_delete(base->my_timer);
base->my_timer = NULL;
}
else
{
printf("Missing timer handle in HRT_callback!\n");
return;
}
if (base->callback && base->params)
{
base->callback(base->params);
}
else
{
printf("Missing callback or params in HRT_callback!\n");
return;
}
}
I can work around it. I could also perhaps just do it differently without a timer if the timer value is less than 100us (since the valid timer intervals are in units of 100us and the lowest two valid values are 0 or 100us). I am just curious why this happens most of all.