test_queuesets.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "freertos/FreeRTOS.h"
  4. #include "freertos/task.h"
  5. #include "freertos/queue.h"
  6. #include "freertos/semphr.h"
  7. #include "unity.h"
  8. /*
  9. * Basic queue set tests. Multiple queues are added to a queue set then each
  10. * queue is filled in a sequential order. The members returned from the queue
  11. * set must adhered to the order in which the queues were filled.
  12. */
  13. #define NO_OF_QUEUES 5
  14. #define QUEUE_LEN 4
  15. #define ITEM_SIZE sizeof(uint32_t)
  16. static QueueHandle_t handles[NO_OF_QUEUES];
  17. static QueueSetHandle_t set_handle;
  18. TEST_CASE("Test Queue sets", "[freertos]")
  19. {
  20. //Create queue set, queues, and add queues to queue set
  21. set_handle = xQueueCreateSet(NO_OF_QUEUES * QUEUE_LEN);
  22. for (int i = 0; i < NO_OF_QUEUES; i++) {
  23. handles[i] = xQueueCreate(QUEUE_LEN, ITEM_SIZE);
  24. TEST_ASSERT_MESSAGE(handles[i] != NULL, "Failed to create queue");
  25. TEST_ASSERT_MESSAGE(xQueueAddToSet(handles[i], set_handle) == pdPASS, "Failed to add to queue set");
  26. }
  27. //Fill queue set via filling each queue
  28. for (int i = 0; i < NO_OF_QUEUES; i++) {
  29. for (int j = 0; j < QUEUE_LEN; j++) {
  30. uint32_t item_num = (i * QUEUE_LEN) + j;
  31. TEST_ASSERT_MESSAGE(xQueueSendToBack(handles[i], &item_num, portMAX_DELAY) == pdTRUE, "Failed to send to queue");
  32. }
  33. }
  34. //Check queue set is notified in correct order
  35. for (int i = 0; i < NO_OF_QUEUES; i++) {
  36. for (int j = 0; j < QUEUE_LEN; j++) {
  37. QueueSetMemberHandle_t member = xQueueSelectFromSet(set_handle, portMAX_DELAY);
  38. TEST_ASSERT_EQUAL_MESSAGE(handles[i], member, "Incorrect queue set member returned");
  39. uint32_t item;
  40. xQueueReceive((QueueHandle_t)member, &item, 0);
  41. TEST_ASSERT_EQUAL_MESSAGE(((i * QUEUE_LEN) + j), item, "Incorrect item value");
  42. }
  43. }
  44. //Remove queues from queue set and delete queues
  45. for (int i = 0; i < NO_OF_QUEUES; i++) {
  46. TEST_ASSERT_MESSAGE(xQueueRemoveFromSet(handles[i], set_handle), "Failed to remove from queue set");
  47. vQueueDelete(handles[i]);
  48. }
  49. vQueueDelete(set_handle);
  50. }
  51. /*
  52. * Queue set thread safety test. Test the SMP thread safety by adding two queues
  53. * to a queue set and have a task on each core send to the queues simultaneously.
  54. * Check returned queue set members are valid.
  55. */
  56. #ifndef CONFIG_FREERTOS_UNICORE
  57. static volatile bool sync_flags[portNUM_PROCESSORS];
  58. static SemaphoreHandle_t sync_sem;
  59. static void send_task(void *arg)
  60. {
  61. QueueHandle_t queue = (QueueHandle_t)arg;
  62. //Wait until task on the other core starts running
  63. xSemaphoreTake(sync_sem, portMAX_DELAY);
  64. sync_flags[xPortGetCoreID()] = true;
  65. while (!sync_flags[!xPortGetCoreID()]) {
  66. ;
  67. }
  68. //Fill queue
  69. for (int i = 0; i < QUEUE_LEN; i++) {
  70. uint32_t item = i;
  71. xQueueSendToBack(queue, &item, portMAX_DELAY);
  72. }
  73. xSemaphoreGive(sync_sem);
  74. vTaskDelete(NULL);
  75. }
  76. TEST_CASE("Test Queue sets thread safety", "[freertos]")
  77. {
  78. //Create queue set, queues, and a send task on each core
  79. sync_sem = xSemaphoreCreateCounting(portNUM_PROCESSORS, 0);
  80. QueueHandle_t queue_handles[portNUM_PROCESSORS];
  81. QueueSetHandle_t queueset_handle = xQueueCreateSet(portNUM_PROCESSORS * QUEUE_LEN);
  82. for (int i = 0; i < portNUM_PROCESSORS; i++) {
  83. sync_flags[i] = false;
  84. queue_handles[i] = xQueueCreate(QUEUE_LEN, ITEM_SIZE);
  85. TEST_ASSERT_MESSAGE(xQueueAddToSet(queue_handles[i], queueset_handle) == pdPASS, "Failed to add to queue set");
  86. xTaskCreatePinnedToCore(send_task, "send", 2048, (void *)queue_handles[i], 10, NULL, i);
  87. }
  88. //Start both send tasks
  89. portDISABLE_INTERRUPTS();
  90. for (int i = 0; i < portNUM_PROCESSORS; i++) {
  91. xSemaphoreGive(sync_sem);
  92. }
  93. portENABLE_INTERRUPTS();
  94. vTaskDelay(2);
  95. //Check returned queue set members are valid
  96. uint32_t expect_0 = 0;
  97. uint32_t expect_1 = 0;
  98. for (int i = 0; i < (portNUM_PROCESSORS * QUEUE_LEN); i++) {
  99. QueueSetMemberHandle_t member = xQueueSelectFromSet(queueset_handle, portMAX_DELAY);
  100. uint32_t item;
  101. if (member == queue_handles[0]) {
  102. xQueueReceive((QueueHandle_t)member, &item, 0);
  103. TEST_ASSERT_EQUAL_MESSAGE(expect_0, item, "Incorrect item value");
  104. expect_0++;
  105. } else if (member == queue_handles[1]) {
  106. xQueueReceive((QueueHandle_t)member, &item, 0);
  107. TEST_ASSERT_EQUAL_MESSAGE(expect_1, item, "Incorrect item value");
  108. expect_1++;
  109. } else {
  110. TEST_ASSERT_MESSAGE(0, "Incorrect queue set member returned");
  111. }
  112. }
  113. for (int i = 0; i < portNUM_PROCESSORS; i++) {
  114. xSemaphoreTake(sync_sem, portMAX_DELAY);
  115. }
  116. for (int i = 0; i < portNUM_PROCESSORS; i++) {
  117. xQueueRemoveFromSet(queueset_handle, handles[i]);
  118. vQueueDelete(queue_handles[i]);
  119. }
  120. vQueueDelete(queueset_handle);
  121. }
  122. #endif