test_freertos_task_notify.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /*
  7. Test of FreeRTOS task notifications. This test creates a sender and receiver
  8. task under different core permutations. For each permutation, the sender task
  9. will test the xTaskNotify(), xTaskNotifyGive(), xTaskNotifyFromISR(), and
  10. vTaskNotifyGiveFromISR(), whereas the receiver task will test
  11. xTaskNotifyWait() and ulTaskNotifyTake().
  12. */
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include "freertos/FreeRTOS.h"
  16. #include "freertos/task.h"
  17. #include "freertos/semphr.h"
  18. #include "driver/gptimer.h"
  19. #include "unity.h"
  20. #include "test_utils.h"
  21. #define NO_OF_NOTIFS 4
  22. #define NO_OF_TASKS 2 //Sender and receiver
  23. #define MESSAGE 0xFF
  24. static uint32_t send_core_message = 0;
  25. static TaskHandle_t recv_task_handle;
  26. static bool isr_give = false;
  27. static bool test_start = false;
  28. static gptimer_handle_t gptimers[portNUM_PROCESSORS];
  29. static SemaphoreHandle_t trigger_send_semphr;
  30. static SemaphoreHandle_t task_delete_semphr;
  31. //Test tracking vars
  32. static volatile uint32_t notifs_sent = 0;
  33. static volatile uint32_t notifs_rec = 0;
  34. static bool wrong_core = false;
  35. static bool on_alarm_sender_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
  36. {
  37. gptimer_stop(timer);
  38. if (!test_start) {
  39. return false;
  40. }
  41. int curcore = xPortGetCoreID();
  42. if (isr_give) { //Test vTaskNotifyGiveFromISR() on same core
  43. notifs_sent++;
  44. vTaskNotifyGiveFromISR(recv_task_handle, NULL);
  45. } else { //Test xTaskNotifyFromISR()
  46. notifs_sent++;
  47. xTaskNotifyFromISR(recv_task_handle, (MESSAGE << curcore), eSetValueWithOverwrite, NULL);
  48. }
  49. // always trigger a task switch when exit ISR context
  50. return true;
  51. }
  52. static void test_gptimer_start(void *arg)
  53. {
  54. gptimer_handle_t gptimer = (gptimer_handle_t)arg;
  55. gptimer_alarm_config_t alarm_config = {
  56. .reload_count = 0,
  57. .alarm_count = 1000,
  58. };
  59. TEST_ESP_OK(gptimer_set_raw_count(gptimer, 0));
  60. TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
  61. TEST_ESP_OK(gptimer_start(gptimer));
  62. }
  63. static void sender_task(void *arg)
  64. {
  65. gptimer_handle_t gptimer = (gptimer_handle_t)arg;
  66. int curcore = xPortGetCoreID();
  67. //Test xTaskNotify
  68. xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
  69. notifs_sent++;
  70. xTaskNotify(recv_task_handle, (MESSAGE << curcore), eSetValueWithOverwrite);
  71. //Test xTaskNotifyGive
  72. xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
  73. notifs_sent++;
  74. xTaskNotifyGive(recv_task_handle);
  75. //Test xTaskNotifyFromISR
  76. xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
  77. isr_give = false;
  78. test_gptimer_start(gptimer);
  79. //Test vTaskNotifyGiveFromISR
  80. xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
  81. isr_give = true;
  82. test_gptimer_start(gptimer);
  83. //Delete Task and Semaphores
  84. xSemaphoreGive(task_delete_semphr);
  85. vTaskDelete(NULL);
  86. }
  87. static void receiver_task(void *arg)
  88. {
  89. uint32_t notify_value;
  90. //Test xTaskNotifyWait from task
  91. xTaskNotifyWait(0, 0xFFFFFFFF, &notify_value, portMAX_DELAY);
  92. if (notify_value != send_core_message) {
  93. wrong_core = true;
  94. }
  95. notifs_rec++;
  96. //Test ulTaskNotifyTake from task
  97. xSemaphoreGive(trigger_send_semphr);
  98. ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
  99. notifs_rec++;
  100. //Test xTaskNotifyWait from ISR
  101. xSemaphoreGive(trigger_send_semphr);
  102. xTaskNotifyWait(0, 0xFFFFFFFF, &notify_value, portMAX_DELAY);
  103. if (notify_value != send_core_message) {
  104. wrong_core = true;
  105. }
  106. notifs_rec++;
  107. //Test ulTaskNotifyTake from ISR
  108. xSemaphoreGive(trigger_send_semphr);
  109. ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
  110. notifs_rec++;
  111. //Test complete, stop timer and delete task
  112. xSemaphoreGive(task_delete_semphr);
  113. vTaskDelete(NULL);
  114. }
  115. static void install_gptimer_on_core(void *arg)
  116. {
  117. int core_id = (int)arg;
  118. gptimer_config_t timer_config = {
  119. .clk_src = GPTIMER_CLK_SRC_DEFAULT,
  120. .direction = GPTIMER_COUNT_UP,
  121. .resolution_hz = 1000000, // 1MHz, 1 tick = 1us
  122. };
  123. TEST_ESP_OK(gptimer_new_timer(&timer_config, &gptimers[core_id]));
  124. gptimer_event_callbacks_t cbs = {
  125. .on_alarm = on_alarm_sender_cb,
  126. };
  127. TEST_ESP_OK(gptimer_register_event_callbacks(gptimers[core_id], &cbs, NULL));
  128. TEST_ESP_OK(gptimer_enable(gptimers[core_id]));
  129. test_gptimer_start(gptimers[core_id]);
  130. xSemaphoreGive(task_delete_semphr);
  131. vTaskDelete(NULL);
  132. }
  133. TEST_CASE("Test Task_Notify", "[freertos]")
  134. {
  135. test_start = false;
  136. trigger_send_semphr = xSemaphoreCreateBinary();
  137. task_delete_semphr = xQueueCreateCountingSemaphore(10, 0);
  138. for (int i = 0; i < portNUM_PROCESSORS; i++) {
  139. xTaskCreatePinnedToCore(install_gptimer_on_core, "install_gptimer", 4096, (void *const)i, UNITY_FREERTOS_PRIORITY + 1, NULL, i);
  140. TEST_ASSERT(xSemaphoreTake(task_delete_semphr, pdMS_TO_TICKS(1000)));
  141. }
  142. // wait the gptimer installation done on specific core
  143. vTaskDelay(10);
  144. // test start
  145. test_start = true;
  146. for (int i = 0; i < portNUM_PROCESSORS; i++) { //Sending Core
  147. for (int j = 0; j < portNUM_PROCESSORS; j++) { //Receiving Core
  148. //Reset Values
  149. notifs_sent = 0;
  150. notifs_rec = 0;
  151. wrong_core = false;
  152. send_core_message = (0xFF << i); //0xFF if core 0, 0xFF0 if core 1
  153. // receiver task has higher priority than sender task
  154. xTaskCreatePinnedToCore(receiver_task, "recv task", 1000, NULL, UNITY_FREERTOS_PRIORITY + 2, &recv_task_handle, j);
  155. xTaskCreatePinnedToCore(sender_task, "send task", 1000, gptimers[i], UNITY_FREERTOS_PRIORITY + 1, NULL, i);
  156. vTaskDelay(5); //Wait for task creation to complete
  157. xSemaphoreGive(trigger_send_semphr); //Trigger sender task
  158. for (int k = 0; k < NO_OF_TASKS; k++) { //Wait for sender and receiver task deletion
  159. TEST_ASSERT(xSemaphoreTake(task_delete_semphr, pdMS_TO_TICKS(2000)));
  160. }
  161. vTaskDelay(5); //Give time tasks to delete
  162. TEST_ASSERT_EQUAL(NO_OF_NOTIFS, notifs_sent);
  163. TEST_ASSERT_EQUAL(NO_OF_NOTIFS, notifs_rec);
  164. TEST_ASSERT_EQUAL(false, wrong_core);
  165. }
  166. }
  167. //Delete Semaphroes and timer ISRs
  168. vSemaphoreDelete(trigger_send_semphr);
  169. vSemaphoreDelete(task_delete_semphr);
  170. for (int i = 0; i < portNUM_PROCESSORS; i++) {
  171. TEST_ESP_OK(gptimer_stop(gptimers[i]));
  172. TEST_ESP_OK(gptimer_disable(gptimers[i]));
  173. TEST_ESP_OK(gptimer_del_timer(gptimers[i]));
  174. }
  175. }