Possible critical section when using timer interrupt

matteof93
Posts: 3
Joined: Sun Nov 04, 2018 1:24 pm

Possible critical section when using timer interrupt

Postby matteof93 » 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:

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
Then, after other code which is not important in this case (always in the same 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.");
}
Then later always in the same function:

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
}
The callback triggered by the timer is this:

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
	}
}
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...

Who is online

Users browsing this forum: Google [Bot] and 133 guests