test_freertos_backported_functions.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /*
  7. * Test features that are backported from version FreeRTOS 9.0.0.
  8. *
  9. * 1) Test backported timer functions
  10. * - xTimerCreateStatic(), vTimerSetTimerId(), xTimerGetPeriod(), xTimerGetExpiryTime()
  11. * 2) Test backported queue/semaphore functions
  12. * - xQueueCreateStatic()
  13. * - xSemaphoreCreateBinaryStatic(), xSemaphoreCreateCountingStatic(), uxSemaphoreGetCount()
  14. * - xSemaphoreCreateMutexStatic(), xSemaphoreCreateRecursiveMutexStatic()
  15. * 3) Test static allocation of tasks
  16. * - xTaskCreateStaticPinnedToCore()
  17. * 4) Test static allocation of event group
  18. * - xEventGroupCreateStatic()
  19. * 5) Test Thread Local Storage Pointers and Deletion Callbacks
  20. * - vTaskSetThreadLocalStoragePointerAndDelCallback()
  21. * - pvTaskGetThreadLocalStoragePointer()
  22. *
  23. * Note: The *pcQueueGetName() function is also backported, but is not tested in
  24. * the following test cases (see Queue Registry test cases instead)
  25. * For more details please refer the the ESP-IDF FreeRTOS changes documentation
  26. */
  27. #include <stdio.h>
  28. #include "freertos/FreeRTOS.h"
  29. #include "freertos/task.h"
  30. #include "freertos/timers.h"
  31. #include "freertos/queue.h"
  32. #include "freertos/semphr.h"
  33. #include "freertos/event_groups.h"
  34. #include "unity.h"
  35. #include "test_utils.h"
  36. /* ---------------------Test 1: Backported Timer functions-----------------------
  37. * Test xTimerCreateStatic(), vTimerSetTimerId(), xTimerGetPeriod(), xTimerGetExpiryTime()
  38. *
  39. * This test creates a one-shot static timer, sets/checks the timer's id and period. Then ensures
  40. * the timer cb is executed in a timely fashion.
  41. */
  42. #define TMR_PERIOD_TICKS 10
  43. #define TIMER_ID 0xFF
  44. #define TICK_DELTA 5
  45. static StaticTimer_t timer_buffer;
  46. static TickType_t tmr_ideal_exp;
  47. static void tmr_cb(TimerHandle_t xtimer)
  48. {
  49. //Check cb is called in timely fashion
  50. TEST_ASSERT_UINT32_WITHIN(TICK_DELTA, tmr_ideal_exp, xTaskGetTickCount());
  51. }
  52. //No need for smp test as Timer Task always runs on core 0
  53. TEST_CASE("Test FreeRTOS backported timer functions", "[freertos]")
  54. {
  55. //Create one shot static timer with period TMR_PERIOD_TICKS
  56. TimerHandle_t tmr_handle = xTimerCreateStatic("static_tmr", TMR_PERIOD_TICKS, pdFALSE, NULL, tmr_cb, &timer_buffer);
  57. TEST_ASSERT_EQUAL(TMR_PERIOD_TICKS, xTimerGetPeriod(tmr_handle)); //Test xTimerGetPeriod()
  58. vTimerSetTimerID(tmr_handle, (void *)TIMER_ID);
  59. TEST_ASSERT_EQUAL(TIMER_ID, (uint32_t)pvTimerGetTimerID(tmr_handle)); //Test vTimerSetTimerID()
  60. TEST_ASSERT_EQUAL(pdTRUE, xTimerStart(tmr_handle, 1)); //Start Timer
  61. tmr_ideal_exp = xTaskGetTickCount() + TMR_PERIOD_TICKS; //Calculate ideal expiration time
  62. vTaskDelay(2); //Need to yield to allow daemon task to process start command, or else expiration time will be NULL
  63. TEST_ASSERT_UINT32_WITHIN(TICK_DELTA, tmr_ideal_exp, xTimerGetExpiryTime(tmr_handle)); //Test xTimerGetExpiryTime()
  64. vTaskDelay(2*TMR_PERIOD_TICKS); //Delay until one shot timer has triggered
  65. TEST_ASSERT_EQUAL(pdPASS, xTimerDelete(tmr_handle, portMAX_DELAY)); //Clean up
  66. }
  67. /* ---------------Test backported queue/semaphore functions-------------------
  68. * xQueueCreateStatic()
  69. * xSemaphoreCreateBinaryStatic(), xSemaphoreCreateCountingStatic()
  70. * xSemaphoreCreateMutexStatic(), xSemaphoreCreateRecursiveMutexStatic()
  71. * uxSemaphoreGetCount() is also tested on the static counting semaphore
  72. *
  73. * This test creates various static queue/semphrs listed above and tests them by
  74. * doing a simple send/give and rec/take.
  75. */
  76. #define ITEM_SIZE 3
  77. #define NO_OF_ITEMS 3
  78. #define DELAY_TICKS 2
  79. static StaticQueue_t queue_buffer; //Queues, Semaphores, and Mutex use the same queue structure
  80. static uint8_t queue_storage_area[(ITEM_SIZE*NO_OF_ITEMS)]; //Queue storage provided in separate buffer to queue struct
  81. TEST_CASE("Test FreeRTOS backported Queue and Semphr functions", "[freertos]")
  82. {
  83. //Test static queue
  84. uint8_t queue_item_to_send[ITEM_SIZE];
  85. uint8_t queue_item_received[ITEM_SIZE];
  86. for(int i = 0; i < ITEM_SIZE; i++){
  87. queue_item_to_send[i] = (0xF << i);
  88. }
  89. QueueHandle_t handle = xQueueCreateStatic(NO_OF_ITEMS, ITEM_SIZE,(uint8_t*) &queue_storage_area, &queue_buffer);
  90. TEST_ASSERT_EQUAL(pdTRUE, xQueueSendToBack(handle, &queue_item_to_send, DELAY_TICKS));
  91. vTaskDelay(1);
  92. TEST_ASSERT_EQUAL(pdTRUE, xQueueReceive(handle, queue_item_received, DELAY_TICKS));
  93. vTaskDelay(1);
  94. for(int i = 0; i < ITEM_SIZE; i++){
  95. TEST_ASSERT_EQUAL(queue_item_to_send[i], queue_item_received[i]); //Check received contents are correct
  96. }
  97. vQueueDelete(handle); //Technically not needed as deleting static queue/semphr doesn't clear static memory
  98. //Test static binary semaphore
  99. handle = xSemaphoreCreateBinaryStatic(&queue_buffer); //Queue and Semphr handles are the same
  100. TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreGive(handle));
  101. vTaskDelay(1);
  102. TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(handle, DELAY_TICKS));
  103. vTaskDelay(1);
  104. vSemaphoreDelete(handle);
  105. //Test static counting semaphore and uxSemaphoreGetCount()
  106. handle = xSemaphoreCreateCountingStatic(NO_OF_ITEMS, 0, &queue_buffer);
  107. for(int i = 0; i < NO_OF_ITEMS; i++){
  108. TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreGive(handle));
  109. }
  110. vTaskDelay(1);
  111. TEST_ASSERT_EQUAL(NO_OF_ITEMS, uxSemaphoreGetCount(handle)); //Test uxSemaphoreGetCount()
  112. for(int i = 0; i < NO_OF_ITEMS; i++){
  113. TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(handle, DELAY_TICKS));
  114. }
  115. vTaskDelay(1);
  116. TEST_ASSERT_EQUAL(0, uxSemaphoreGetCount(handle));
  117. vSemaphoreDelete(handle);
  118. //Test static mutex
  119. handle = xSemaphoreCreateMutexStatic(&queue_buffer);
  120. TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(handle, DELAY_TICKS));
  121. vTaskDelay(1);
  122. TEST_ASSERT_EQUAL_PTR((void *)xTaskGetCurrentTaskHandle(), xSemaphoreGetMutexHolder(handle)); //Current task should now hold mutex
  123. TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreGive(handle));
  124. vTaskDelay(1);
  125. TEST_ASSERT_EQUAL_PTR(NULL, xSemaphoreGetMutexHolder(handle)); //Mutex should have been released
  126. vSemaphoreDelete(handle);
  127. //Test static mutex recursive
  128. handle = xSemaphoreCreateRecursiveMutexStatic(&queue_buffer);
  129. for(int i = 0; i < NO_OF_ITEMS; i++){
  130. TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTakeRecursive(handle, DELAY_TICKS));
  131. }
  132. vTaskDelay(1);
  133. TEST_ASSERT_EQUAL_PTR((void *)xTaskGetCurrentTaskHandle(), xSemaphoreGetMutexHolder(handle)); //Current task should hold mutex
  134. for(int i = 0; i < NO_OF_ITEMS; i++){
  135. TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreGiveRecursive(handle));
  136. }
  137. vTaskDelay(1);
  138. TEST_ASSERT_EQUAL_PTR(NULL, xSemaphoreGetMutexHolder(handle)); //Mutex should have been released
  139. vSemaphoreDelete(handle);
  140. }
  141. /* -----------------Test backported static task allocation -------------------
  142. * Test xTaskCreateStaticPinnedToCore() but creating static task on each core
  143. * and checking the task cb has run successfully.
  144. */
  145. #define STACK_SIZE 2048 //Task stack size
  146. static StackType_t task_stack[STACK_SIZE]; //Static buffer for task stack
  147. static StaticTask_t task_buffer; //Static buffer for TCB
  148. static bool has_run[portNUM_PROCESSORS];
  149. static void task(void *arg)
  150. {
  151. has_run[xPortGetCoreID()] = true; //Signify static task cb has run
  152. vTaskDelete(NULL);
  153. }
  154. TEST_CASE("Test FreeRTOS static task allocation", "[freertos]")
  155. {
  156. for(int core = 0; core < portNUM_PROCESSORS; core++){
  157. has_run[core] = false; //Clear has_run flag
  158. TaskHandle_t handle = xTaskCreateStaticPinnedToCore(task, "static task", STACK_SIZE, NULL,
  159. UNITY_FREERTOS_PRIORITY + 1, (StackType_t *)&task_stack,
  160. (StaticTask_t *)&task_buffer, core);
  161. vTaskDelay(5); //Allow for static task to run, delete, and idle to clean up
  162. TEST_ASSERT_NOT_EQUAL(NULL, handle); //Check static task was successfully allocated
  163. TEST_ASSERT_TRUE(has_run[core]) //Check static task has run
  164. }
  165. }
  166. /* ------------- Test backported static event group allocation -------------------
  167. * Test xEventGroupCreateStatic() but creating static event group then waiting
  168. * for an event.
  169. */
  170. #define WAIT_BITS 0x01 //Wait for first bit
  171. static StaticEventGroup_t event_group;
  172. static EventGroupHandle_t eg_handle;
  173. TEST_CASE("Test FreeRTOS backported eventgroup functions", "[freertos]")
  174. {
  175. eg_handle = xEventGroupCreateStatic((StaticEventGroup_t *)&event_group);
  176. xEventGroupSetBits(eg_handle, WAIT_BITS);
  177. TEST_ASSERT_EQUAL(WAIT_BITS, xEventGroupWaitBits(eg_handle, WAIT_BITS, pdTRUE, pdTRUE, portMAX_DELAY));
  178. //Cleanup static event
  179. vEventGroupDelete(eg_handle);
  180. }