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