Possible critical section when using timer interrupt
Posted: Tue Apr 30, 2019 7:24 pm
Hello, I am struggling to understand if there is a possible critical section in my code. This is the code in one of my function:
Then, after other code which is not important in this case (always in the same function):
Then later always in the same function:
The callback triggered by the timer is this:
Everything is happening within the same task but the callback is triggered when the timer expires. So what happens if I enter in the if(led_task_handle != nullptr){ vTaskDelete(led_task_handle)} and the callback is triggered exactly before the vTaskDelete() instruction is called? I suppose I enter in the callback, the other vTaskDelete() is performed then I go back to my main function which calls again the vTaskDelete but at that point it will be vTaskDelete(NULL) so my application will crash.
Are my assumptions correct? How do you think I could fix the code? Because the problem is that everything is happening in the very same task. I suppose I could temporarily disable the callback triggered by the timer...
Code: Select all
TaskHandle_t led_task_handle = nullptr; // handle to the task for led blinking
esp_timer_handle_t led_timer_handle = nullptr; // handle to the timer to stop led blinking
const esp_timer_create_args_t led_timer_args = {
&led_timer_callback, // function to call when timer expires
(void*) &led_task_handle, // argument to pass to the callback, must be void*
ESP_TIMER_TASK, // callback is called from timer task
"led_timer", // timer name, must be a const char*
};
ESP_ERROR_CHECK(esp_timer_create(&led_timer_args, &led_timer_handle)); // create the timer to be used by the led blink function
Code: Select all
if(led_task_handle == nullptr){ // if this is the first time we receive blink we create the task, otherwise we don't do anything because the led task is already running
xTaskCreate(&led_task, "led_task", 512, &led_task_handle, 5, &led_task_handle); // create task to use onboard led
ESP_ERROR_CHECK(esp_timer_start_once(led_timer_handle, BLINK_DURATION*1000000)); // start the timer to trigger blink stop (time duration is in microseconds)
ESP_LOGI(TAG, "LED task started.");
}
Code: Select all
esp_timer_stop(led_timer_handle); // stop the timer from running (no ESP_ERROR_CHECK because we don't know if the timer has ever started)
esp_timer_delete(led_timer_handle); // delete the timer (no ESP_ERROR_CHECK because we don't know if the timer has ever started)
if(led_task_handle != nullptr){ // stop immediately the blink
vTaskDelete(led_task_handle); // delete led blinking task
led_task_handle = nullptr; // set back the task handler to nullptr for safety reasons
turn_off_led(); // this simply sets the onboard LED pin to 0 in order to turn it off
}
Code: Select all
void led_timer_callback(void *param){
TaskHandle_t *led_task_handle = (TaskHandle_t*)param;
if(*led_task_handle != nullptr){
vTaskDelete(*led_task_handle); // delete led blinking task
*led_task_handle = nullptr; // set back the task handler to nullptr for safety reasons
turn_off_led(); // this simply sets the onboard LED pin to 0 in order to turn it off
}
}
Are my assumptions correct? How do you think I could fix the code? Because the problem is that everything is happening in the very same task. I suppose I could temporarily disable the callback triggered by the timer...