2022-04-20 07:31:49 -04:00
|
|
|
/*
|
|
|
|
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2018-07-11 08:50:43 -04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "freertos/FreeRTOS.h"
|
|
|
|
#include "freertos/task.h"
|
|
|
|
#include "freertos/queue.h"
|
|
|
|
#include "freertos/semphr.h"
|
2022-05-19 04:21:31 -04:00
|
|
|
#include "freertos/idf_additions.h"
|
2018-07-11 08:50:43 -04:00
|
|
|
#include "unity.h"
|
2022-05-19 04:21:31 -04:00
|
|
|
#include "test_utils.h"
|
|
|
|
|
|
|
|
#define QUEUE_LEN 4
|
|
|
|
|
|
|
|
static void allocate_resources(int num_queues, int queue_len, QueueHandle_t *queue_list_ret, QueueSetHandle_t *queue_set_ret)
|
|
|
|
{
|
|
|
|
// Create queue set
|
|
|
|
*queue_set_ret = xQueueCreateSet(num_queues * queue_len);
|
|
|
|
TEST_ASSERT_NOT_EQUAL(NULL, *queue_set_ret);
|
|
|
|
// Create queues and add them to the queue set
|
|
|
|
for (int i = 0; i < num_queues; i++) {
|
|
|
|
queue_list_ret[i] = xQueueCreate(queue_len, sizeof(BaseType_t));
|
|
|
|
TEST_ASSERT_NOT_EQUAL(NULL, queue_list_ret[i]);
|
|
|
|
TEST_ASSERT_EQUAL(pdPASS, xQueueAddToSet(queue_list_ret[i], *queue_set_ret));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_resources(int num_queues, QueueHandle_t *queue_list, QueueSetHandle_t queue_set)
|
|
|
|
{
|
|
|
|
// Remove queues form queue set and delete the queues
|
|
|
|
for (int i = 0; i < num_queues; i++) {
|
|
|
|
TEST_ASSERT_EQUAL(pdPASS, xQueueRemoveFromSet(queue_list[i], queue_set));
|
|
|
|
vQueueDelete(queue_list[i]);
|
|
|
|
}
|
|
|
|
vQueueDelete(queue_set);
|
|
|
|
}
|
2018-07-11 08:50:43 -04:00
|
|
|
|
|
|
|
/*
|
2022-05-19 04:21:31 -04:00
|
|
|
Test queue sets basic
|
|
|
|
|
|
|
|
Purpose:
|
|
|
|
- Test that queue set works as expected
|
|
|
|
|
|
|
|
Procedure:
|
|
|
|
- Create NUM_QUEUES queues and add them to the same queue set
|
|
|
|
- Fill each queue sequentially with QUEUE_LEN items
|
2018-07-11 08:50:43 -04:00
|
|
|
|
2022-05-19 04:21:31 -04:00
|
|
|
Expected:
|
|
|
|
- Each call to xQueueSend() should generate a member in the queue set
|
|
|
|
- The order of the members should match the order in which xQueueSend() was called
|
|
|
|
- The item sent by the xQueueSend() is correct when read
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define NUM_QUEUES 5
|
2018-07-11 08:50:43 -04:00
|
|
|
|
|
|
|
TEST_CASE("Test Queue sets", "[freertos]")
|
|
|
|
{
|
2022-05-19 04:21:31 -04:00
|
|
|
// Create queues and queue set
|
|
|
|
QueueHandle_t queues[NUM_QUEUES];
|
|
|
|
QueueSetHandle_t queue_set;
|
|
|
|
allocate_resources(NUM_QUEUES, QUEUE_LEN, queues, &queue_set);
|
2018-07-11 08:50:43 -04:00
|
|
|
|
2022-05-19 04:21:31 -04:00
|
|
|
// Fill each queue sequentially with QUEUE_LEN items
|
|
|
|
for (int i = 0; i < NUM_QUEUES; i++) {
|
2018-07-11 08:50:43 -04:00
|
|
|
for (int j = 0; j < QUEUE_LEN; j++) {
|
2022-05-19 04:21:31 -04:00
|
|
|
BaseType_t item = j;
|
|
|
|
TEST_ASSERT_EQUAL(pdTRUE, xQueueSend(queues[i], &item, 0));
|
2018-07-11 08:50:43 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-19 04:21:31 -04:00
|
|
|
for (int i = 0; i < NUM_QUEUES; i++) {
|
2018-07-11 08:50:43 -04:00
|
|
|
for (int j = 0; j < QUEUE_LEN; j++) {
|
2022-05-19 04:21:31 -04:00
|
|
|
// Check the queue set member
|
|
|
|
QueueSetMemberHandle_t member = xQueueSelectFromSet(queue_set, 0);
|
|
|
|
TEST_ASSERT_EQUAL(queues[i], member);
|
|
|
|
// Check the queue's items
|
|
|
|
BaseType_t item;
|
|
|
|
TEST_ASSERT_EQUAL(pdTRUE, xQueueReceive(member, &item, 0));
|
|
|
|
TEST_ASSERT_EQUAL(j, item);
|
2018-07-11 08:50:43 -04:00
|
|
|
}
|
|
|
|
}
|
2022-05-19 04:21:31 -04:00
|
|
|
// Check that there are no more members
|
|
|
|
TEST_ASSERT_EQUAL(NULL, xQueueSelectFromSet(queue_set, 0));
|
2018-07-11 08:50:43 -04:00
|
|
|
|
2022-05-19 04:21:31 -04:00
|
|
|
// Cleanup queues and queue set
|
|
|
|
free_resources(NUM_QUEUES, queues, queue_set);
|
2018-07-11 08:50:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef CONFIG_FREERTOS_UNICORE
|
2022-05-19 04:21:31 -04:00
|
|
|
/*
|
|
|
|
Test queue set SMP thread safety
|
|
|
|
|
|
|
|
Purpose:
|
|
|
|
- Test that queue set works when being used from different cores simultaneously
|
|
|
|
|
|
|
|
Procedure:
|
|
|
|
- Create a queue for each core and add them to the same queue set
|
|
|
|
- Create a task on each core to send QUEUE_LEN items to their assigned queue
|
|
|
|
- Synchronize the tasks so that the start sending at the same time
|
2018-07-11 08:50:43 -04:00
|
|
|
|
2022-05-19 04:21:31 -04:00
|
|
|
Expected:
|
|
|
|
- Each call to xQueueSend() should generate a member in the queue set
|
|
|
|
- The item sent by the xQueueSend() is correct when read
|
|
|
|
*/
|
|
|
|
|
|
|
|
static volatile bool start_other_cores;
|
|
|
|
static SemaphoreHandle_t done_sem = NULL;
|
|
|
|
|
|
|
|
static void send_func(void *arg)
|
2018-07-11 08:50:43 -04:00
|
|
|
{
|
|
|
|
QueueHandle_t queue = (QueueHandle_t)arg;
|
2022-05-19 04:21:31 -04:00
|
|
|
BaseType_t core_id = xPortGetCoreID();
|
|
|
|
if (core_id == 0) {
|
|
|
|
// We are core 0. Trigger the other cores to start
|
|
|
|
start_other_cores = true;
|
|
|
|
} else {
|
|
|
|
// Wait to be started by main core
|
|
|
|
while (!start_other_cores) {
|
|
|
|
;
|
|
|
|
}
|
2018-07-11 08:50:43 -04:00
|
|
|
}
|
|
|
|
|
2022-05-19 04:21:31 -04:00
|
|
|
// Fill the queue assigned to the current core
|
2018-07-11 08:50:43 -04:00
|
|
|
for (int i = 0; i < QUEUE_LEN; i++) {
|
2022-05-19 04:21:31 -04:00
|
|
|
TEST_ASSERT_EQUAL(pdTRUE, xQueueSend(queue, &core_id, 0));
|
2018-07-11 08:50:43 -04:00
|
|
|
}
|
|
|
|
|
2022-05-19 04:21:31 -04:00
|
|
|
if (core_id != 0) {
|
|
|
|
// Indicate completion to core 0 and self delete
|
|
|
|
xSemaphoreGive(done_sem);
|
|
|
|
vTaskDelete(NULL);
|
|
|
|
}
|
2018-07-11 08:50:43 -04:00
|
|
|
}
|
|
|
|
|
2022-05-19 04:21:31 -04:00
|
|
|
TEST_CASE("Test queue sets multi-core", "[freertos]")
|
2018-07-11 08:50:43 -04:00
|
|
|
{
|
2022-05-19 04:21:31 -04:00
|
|
|
// Create done semaphore
|
|
|
|
done_sem = xSemaphoreCreateCounting(portNUM_PROCESSORS - 1, 0);
|
|
|
|
TEST_ASSERT_NOT_EQUAL(NULL, done_sem);
|
|
|
|
|
|
|
|
// Create queues and queue set
|
|
|
|
QueueHandle_t queues[portNUM_PROCESSORS];
|
|
|
|
QueueSetHandle_t queue_set;
|
|
|
|
allocate_resources(portNUM_PROCESSORS, QUEUE_LEN, queues, &queue_set);
|
|
|
|
|
|
|
|
// Create tasks of the same priority for all cores except for core 0
|
|
|
|
for (int i = 1; i < portNUM_PROCESSORS; i++) {
|
|
|
|
TEST_ASSERT_EQUAL(pdTRUE, xTaskCreatePinnedToCore(send_func, "send", 2048, (void *)queues[i], UNITY_FREERTOS_PRIORITY, NULL, i));
|
2018-07-11 08:50:43 -04:00
|
|
|
}
|
|
|
|
|
2022-05-19 04:21:31 -04:00
|
|
|
// Core 0 calls send_func as well triggering the simultaneous sends from all cores
|
|
|
|
send_func((void *)queues[0]);
|
|
|
|
|
|
|
|
// Wait for all other cores to be done
|
|
|
|
for (int i = 1; i < portNUM_PROCESSORS; i++) {
|
|
|
|
xSemaphoreTake(done_sem, portMAX_DELAY);
|
2018-07-11 08:50:43 -04:00
|
|
|
}
|
|
|
|
|
2022-05-19 04:21:31 -04:00
|
|
|
// Read queues from the queue set, then read an item from the queue
|
|
|
|
uint32_t queues_check_count[portNUM_PROCESSORS] = {0};
|
|
|
|
QueueSetMemberHandle_t member = xQueueSelectFromSet(queue_set, 0);
|
|
|
|
while (member != NULL) {
|
|
|
|
// Read the core ID from the queue, check that core ID is sane
|
|
|
|
BaseType_t core_id;
|
|
|
|
TEST_ASSERT_EQUAL(pdTRUE, xQueueReceive(member, &core_id, 0));
|
|
|
|
TEST_ASSERT_LESS_THAN(portNUM_PROCESSORS, core_id);
|
|
|
|
queues_check_count[core_id]++;
|
|
|
|
|
|
|
|
// Get next member
|
|
|
|
member = xQueueSelectFromSet(queue_set, 0);
|
2018-07-11 08:50:43 -04:00
|
|
|
}
|
2022-05-19 04:21:31 -04:00
|
|
|
// Check that all items from all queues have been read
|
2018-07-11 08:50:43 -04:00
|
|
|
for (int i = 0; i < portNUM_PROCESSORS; i++) {
|
2022-05-19 04:21:31 -04:00
|
|
|
TEST_ASSERT_EQUAL(QUEUE_LEN, queues_check_count[i]);
|
2018-07-11 08:50:43 -04:00
|
|
|
}
|
2022-05-19 04:21:31 -04:00
|
|
|
|
|
|
|
// Cleanup queues and queue set
|
|
|
|
free_resources(portNUM_PROCESSORS, queues, queue_set);
|
|
|
|
// Cleanup done sem
|
|
|
|
vSemaphoreDelete(done_sem);
|
|
|
|
done_sem = NULL;
|
2018-07-11 08:50:43 -04:00
|
|
|
}
|
2022-05-19 04:21:31 -04:00
|
|
|
#endif // CONFIG_FREERTOS_UNICORE
|