test_freertos_task_notify.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. Test of FreeRTOS task notifications. This test creates a sender and receiver
  3. task under different core permutations. For each permutation, the sender task
  4. will test the xTaskNotify(), xTaskNotifyGive(), xTaskNotifyFromISR(), and
  5. vTaskNotifyGiveFromISR(), whereas the receiver task will test
  6. xTaskNotifyWait() and ulTaskNotifyTake().
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include "freertos/FreeRTOS.h"
  11. #include "freertos/task.h"
  12. #include <freertos/semphr.h>
  13. #include "driver/timer.h"
  14. #include "esp_ipc.h"
  15. #include "unity.h"
  16. #include "test_utils.h"
  17. #define NO_OF_NOTIFS 4
  18. #define NO_OF_TASKS 2 //Sender and receiver
  19. #define TIMER_DIVIDER 10000
  20. #define TIMER_COUNT 100
  21. #define MESSAGE 0xFF
  22. static uint32_t send_core_message = 0;
  23. static TaskHandle_t rec_task_handle;
  24. static bool isr_give = false;
  25. static SemaphoreHandle_t trigger_send_semphr;
  26. static SemaphoreHandle_t task_delete_semphr;
  27. //Test tracking vars
  28. static volatile uint32_t notifs_sent = 0;
  29. static volatile uint32_t notifs_rec = 0;
  30. static bool wrong_core = false;
  31. static void sender_task (void* arg){
  32. int curcore = xPortGetCoreID();
  33. //Test xTaskNotify
  34. xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
  35. notifs_sent++;
  36. xTaskNotify(rec_task_handle, (MESSAGE << curcore), eSetValueWithOverwrite);
  37. //Test xTaskNotifyGive
  38. xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
  39. notifs_sent++;
  40. xTaskNotifyGive(rec_task_handle);
  41. //Test xTaskNotifyFromISR
  42. xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
  43. isr_give = false;
  44. timer_start(TIMER_GROUP_0, curcore);
  45. //Test vTaskNotifyGiveFromISR
  46. xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
  47. isr_give = true;
  48. timer_start(TIMER_GROUP_0, curcore);
  49. //Delete Task and Semaphores
  50. xSemaphoreGive(task_delete_semphr);
  51. vTaskDelete(NULL);
  52. }
  53. static void receiver_task (void* arg){
  54. uint32_t notify_value;
  55. //Test xTaskNotifyWait from task
  56. xTaskNotifyWait(0, 0xFFFFFFFF, &notify_value, portMAX_DELAY);
  57. if(notify_value != send_core_message){
  58. wrong_core = true;
  59. }
  60. notifs_rec++;
  61. //Test ulTaskNotifyTake from task
  62. xSemaphoreGive(trigger_send_semphr);
  63. ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
  64. notifs_rec++;
  65. //Test xTaskNotifyWait from ISR
  66. xSemaphoreGive(trigger_send_semphr);
  67. xTaskNotifyWait(0, 0xFFFFFFFF, &notify_value, portMAX_DELAY);
  68. if(notify_value != send_core_message){
  69. wrong_core = true;
  70. }
  71. notifs_rec++;
  72. //Test ulTaskNotifyTake from ISR
  73. xSemaphoreGive(trigger_send_semphr);
  74. ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
  75. notifs_rec++;
  76. //Test complete, stop timer and delete task
  77. xSemaphoreGive(task_delete_semphr);
  78. vTaskDelete(NULL);
  79. }
  80. static void IRAM_ATTR sender_ISR ()
  81. {
  82. int curcore = xPortGetCoreID();
  83. if(curcore == 0){ //Clear timer interrupt
  84. //Clear intr and pause via direct reg access as IRAM ISR cannot access timer APIs
  85. TIMERG0.int_clr_timers.t0 = 1;
  86. TIMERG0.hw_timer[0].config.enable = 0;
  87. }else{
  88. TIMERG0.int_clr_timers.t1 = 1;
  89. TIMERG0.hw_timer[1].config.enable = 0;
  90. }
  91. //Re-enable alarm
  92. TIMERG0.hw_timer[curcore].config.alarm_en = 1;
  93. if(isr_give){ //Test vTaskNotifyGiveFromISR() on same core
  94. notifs_sent++;
  95. vTaskNotifyGiveFromISR(rec_task_handle, NULL);
  96. }
  97. else { //Test xTaskNotifyFromISR()
  98. notifs_sent++;
  99. xTaskNotifyFromISR(rec_task_handle, (MESSAGE << curcore), eSetValueWithOverwrite, NULL);
  100. }
  101. portYIELD_FROM_ISR();
  102. return;
  103. }
  104. static void timerg0_init(void *isr_handle)
  105. {
  106. int timer_group = TIMER_GROUP_0;
  107. int timer_idx = xPortGetCoreID();
  108. timer_config_t config;
  109. config.alarm_en = 1;
  110. config.auto_reload = 1;
  111. config.counter_dir = TIMER_COUNT_UP;
  112. config.divider = TIMER_DIVIDER;
  113. config.intr_type = TIMER_INTR_LEVEL;
  114. config.counter_en = TIMER_PAUSE;
  115. /*Configure timer*/
  116. timer_init(timer_group, timer_idx, &config);
  117. /*Stop timer counter*/
  118. timer_pause(timer_group, timer_idx);
  119. /*Load counter value */
  120. timer_set_counter_value(timer_group, timer_idx, 0x00000000ULL);
  121. /*Set alarm value*/
  122. timer_set_alarm_value(timer_group, timer_idx, TIMER_COUNT);
  123. /*Enable timer interrupt*/
  124. timer_enable_intr(timer_group, timer_idx);
  125. //Auto Reload
  126. timer_set_auto_reload(timer_group, timer_idx, 1);
  127. /*Set ISR handler*/
  128. timer_isr_register(timer_group, timer_idx, sender_ISR, NULL, ESP_INTR_FLAG_IRAM, (intr_handle_t *)isr_handle);
  129. }
  130. static void timerg0_deinit(void* isr_handle)
  131. {
  132. int timer_group = TIMER_GROUP_0;
  133. int timer_idx = xPortGetCoreID();
  134. intr_handle_t handle = *((intr_handle_t *) isr_handle);
  135. //Pause timer then free registered ISR
  136. timer_pause(timer_group, timer_idx);
  137. esp_intr_free(handle);
  138. }
  139. TEST_CASE("Test Task_Notify", "[freertos]")
  140. {
  141. //Initialize and pause timers. Used to trigger ISR
  142. intr_handle_t isr_handle_0 = NULL;
  143. timerg0_init(&isr_handle_0); //Core 0 timer
  144. #ifndef CONFIG_FREERTOS_UNICORE
  145. intr_handle_t isr_handle_1 = NULL;
  146. esp_ipc_call(1, timerg0_init, &isr_handle_1); //Core 1 timer
  147. #endif
  148. trigger_send_semphr = xSemaphoreCreateBinary();
  149. task_delete_semphr = xQueueCreateCountingSemaphore(NO_OF_TASKS, 0);
  150. for(int i = 0; i < portNUM_PROCESSORS; i++){ //Sending Core
  151. for(int j = 0; j < portNUM_PROCESSORS; j++){ //Receiving Core
  152. //Reset Values
  153. notifs_sent = 0;
  154. notifs_rec = 0;
  155. wrong_core = false;
  156. send_core_message = (0xFF << i); //0xFF if core 0, 0xFF0 if core 1
  157. xTaskCreatePinnedToCore(receiver_task, "rec task", 1000, NULL, UNITY_FREERTOS_PRIORITY + 2, &rec_task_handle, j);
  158. xTaskCreatePinnedToCore(sender_task, "send task", 1000, NULL, UNITY_FREERTOS_PRIORITY + 1, NULL, i);
  159. vTaskDelay(5); //Wait for task creation to complete
  160. xSemaphoreGive(trigger_send_semphr); //Trigger sender task
  161. for(int k = 0; k < NO_OF_TASKS; k++){ //Wait for sender and receiver task deletion
  162. xSemaphoreTake(task_delete_semphr, portMAX_DELAY);
  163. }
  164. vTaskDelay(5); //Give time tasks to delete
  165. TEST_ASSERT(notifs_sent == NO_OF_NOTIFS);
  166. TEST_ASSERT(notifs_rec == NO_OF_NOTIFS);
  167. TEST_ASSERT(wrong_core == false);
  168. }
  169. }
  170. //Delete Semaphroes and timer ISRs
  171. vSemaphoreDelete(trigger_send_semphr);
  172. vSemaphoreDelete(task_delete_semphr);
  173. timerg0_deinit(&isr_handle_0);
  174. isr_handle_0 = NULL;
  175. #ifndef CONFIG_FREERTOS_UNICORE
  176. esp_ipc_call(1, timerg0_deinit, &isr_handle_1);
  177. isr_handle_1 = NULL;
  178. #endif
  179. }