Unstable resume task

Avicar
Posts: 2
Joined: Tue Jan 09, 2024 5:19 pm

Unstable resume task

Postby Avicar » Thu Jan 11, 2024 7:27 am

Hello,
I need to delay a task for variable times between 1500 to 4500 microseconds. To do so I used the High Resolution Timer (ESP Timer).
To check that implementation I came up with the following piece of code:
  1. #include <stdio.h>
  2. #include "freertos/FreeRTOS.h"
  3. #include "freertos/task.h"
  4. #include "esp_log.h"
  5. #include <esp_err.h>
  6. #include <sys/stat.h>
  7. #include "freertos/timers.h"
  8. #include "esp_timer.h"
  9. #include "sdkconfig.h"
  10.  
  11. esp_timer_handle_t theTimer_handler;
  12. TaskHandle_t task_handler = NULL;
  13.  
  14.  
  15. static void timer_callback(void *param){
  16.    
  17.     vTaskResume(task_handler);
  18.     printf("task state: %d\n",(int)eTaskGetState( task_handler ));
  19.     printf("Timer: %lld μs\n",esp_timer_get_time());
  20. }
  21.  
  22.  
  23. void initTimer(){
  24.     // define timmer
  25.     const esp_timer_create_args_t timer_args = {
  26.         .callback = &timer_callback,
  27.         .name = "Timer"};
  28.  
  29.     // create timmer
  30.     ESP_ERROR_CHECK(esp_timer_create(&timer_args, &theTimer_handler));
  31. }
  32.  
  33.  
  34. static void the_task(void *arg)
  35. {
  36.    
  37.    ESP_ERROR_CHECK(esp_timer_start_once(theTimer_handler, 2800));
  38.     vTaskSuspend(task_handler); // wait for next time
  39.    
  40.     while (1) {
  41.         ESP_ERROR_CHECK(esp_timer_start_once(theTimer_handler, 2800));
  42.         long long int Timer = esp_timer_get_time();
  43.        
  44.         printf("SYS Timer: %lld μs\n",esp_timer_get_time());
  45.         vTaskSuspend(task_handler); // wait for next time
  46.         printf("back\n");
  47.     }
  48. }
  49.  
  50. void app_main(void)
  51. {
  52.  
  53.  
  54.     initTimer();
  55.    
  56.     xTaskCreatePinnedToCore(the_task, "the_task",8196 , NULL, 5, &task_handler,1);
  57.    
  58.     while (1){
  59.          vTaskDelay(1000 / portTICK_PERIOD_MS);
  60.     }
  61.    
  62.  
  63. }
  64. [/code]
The problem is whenever I decrease the timer to less than 3000 microseconds the program will hang after several iterations. I believe it hangs due to the fact that the task is not in suspend state when the timer is off. I can't understand why the task can't enter the suspend state as there is ample time to do that (in order of few milliseconds).
Here is a sample of the last part of the code output:
SYS Timer: 2465120 μs
task state: 1
Timer: 2468504 μs
back
SYS Timer: 2470762 μs
task state: 1
Timer: 2474146 μs
back
SYS Timer: 2476404 μs
task state: 1
Timer: 2479789 μs
back
SYS Timer: 2482047 μs
task state: 1
Timer: 2485431 μs
back
SYS Timer: 2487689 μs
task state: 1
Timer: 2491073 μs
back
SYS Timer: 2493331 μs
task state: 1
back
Timer: 2496727 μs
SYS Timer: 2497243 μs
task state: 0
Timer: 2502354 μs
Any idea about what am I doing wrong?

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

Re: Unstable resume task

Postby MicroController » Thu Jan 11, 2024 11:31 am

Don't use vTaskSuspend/vTaskResume - like, ever.
In your case, the "direct-to-task notification" mechanism is exactly what you want. A more general solution is using semaphores.

Avicar
Posts: 2
Joined: Tue Jan 09, 2024 5:19 pm

Re: Unstable resume task

Postby Avicar » Thu Jan 11, 2024 3:31 pm

Just for whomever interested, I followed @microcontroller great advice and came up with that code:
  1. #include <stdio.h>
  2. #include "freertos/FreeRTOS.h"
  3. #include "freertos/task.h"
  4. #include "esp_log.h"
  5. #include <esp_err.h>
  6. #include <sys/stat.h>
  7. #include "freertos/timers.h"
  8. #include "esp_timer.h"
  9. #include "sdkconfig.h"
  10.  
  11. esp_timer_handle_t theTimer_handler;
  12. TaskHandle_t task_handler = NULL;
  13.  
  14.  
  15. static void timer_callback(void *param){
  16.    
  17.     //vTaskResume(task_handler);
  18.     xTaskNotifyGive(task_handler);
  19.     printf("task state: %d\n",(int)eTaskGetState( task_handler ));
  20.     printf("Timer: %lld μs\n",esp_timer_get_time());
  21. }
  22.  
  23.  
  24. void initTimer(){
  25.     // define timmer
  26.     const esp_timer_create_args_t timer_args = {
  27.         .callback = &timer_callback,
  28.         .name = "Timer"};
  29.  
  30.     // create timmer
  31.     ESP_ERROR_CHECK(esp_timer_create(&timer_args, &theTimer_handler));
  32. }
  33.  
  34.  
  35. static void the_task(void *arg)
  36. {
  37.     while (1) {
  38.         ESP_ERROR_CHECK(esp_timer_start_once(theTimer_handler, 2800));
  39.         long long int Timer = esp_timer_get_time();
  40.  
  41.         ulTaskNotifyTake(pdTRUE,portMAX_DELAY);
  42.         printf("End Timer: %lld μs\n",esp_timer_get_time()-Timer);
  43.         }
  44. }
  45.  
  46. void app_main(void)
  47. {
  48.  
  49.  
  50.     initTimer();
  51.    
  52.     xTaskCreatePinnedToCore(the_task, "the_task",8196 , NULL, 5, &task_handler,1);
  53.    
  54.     while (1){
  55.          vTaskDelay(1000 / portTICK_PERIOD_MS);
  56.     }
  57.    
  58.  
  59. }
Which works great.

Who is online

Users browsing this forum: No registered users and 109 guests