mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
196 lines
6.7 KiB
C
196 lines
6.7 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/*
|
|
* This file contains esp_ringbuf unit tests which run only on the chip target or QEMU,
|
|
* but NOT on the Linux target since they are too hardware-specific.
|
|
*/
|
|
|
|
#include "sdkconfig.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "freertos/semphr.h"
|
|
#include "freertos/ringbuf.h"
|
|
#include "driver/gptimer.h"
|
|
#include "esp_private/spi_flash_os.h"
|
|
#include "esp_memory_utils.h"
|
|
#include "esp_heap_caps.h"
|
|
#include "unity.h"
|
|
#include "esp_rom_sys.h"
|
|
|
|
#include "test_functions.h"
|
|
|
|
/* -------------------------- Test ring buffer ISR -----------------------------
|
|
* The following test case tests ring buffer ISR API. A timer is used to trigger
|
|
* the ISR. The test case will do the following
|
|
* 1) ISR will be triggered periodically by timer
|
|
* 2) The ISR will iterate through all ring buffer types where each iteration
|
|
* will send then receive an item to a ring buffer.
|
|
*/
|
|
|
|
#define ISR_ITERATIONS ((BUFFER_SIZE / SMALL_ITEM_SIZE) * 2)
|
|
|
|
static int buf_type;
|
|
static int iterations;
|
|
|
|
static bool on_timer_alarm(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
|
|
{
|
|
bool need_yield = false;
|
|
|
|
//Test sending to buffer from ISR from ISR
|
|
if (buf_type < NO_OF_RB_TYPES) {
|
|
send_item_and_check(buffer_handles[buf_type], (void *)small_item, SMALL_ITEM_SIZE, 0, true);
|
|
}
|
|
|
|
//Receive item from ISR
|
|
if (buf_type == RINGBUF_TYPE_NOSPLIT) {
|
|
//Test receive from ISR for no-split buffer
|
|
receive_check_and_return_item_no_split(buffer_handles[buf_type], (void *)small_item, SMALL_ITEM_SIZE, 0, true);
|
|
buf_type++;
|
|
} else if (buf_type == RINGBUF_TYPE_ALLOWSPLIT) {
|
|
//Test send from ISR to allow-split buffer
|
|
receive_check_and_return_item_allow_split(buffer_handles[buf_type], (void *)small_item, SMALL_ITEM_SIZE, 0, true);
|
|
buf_type++;
|
|
} else if (buf_type == RINGBUF_TYPE_BYTEBUF) {
|
|
//Test receive from ISR for byte buffer
|
|
receive_check_and_return_item_byte_buffer(buffer_handles[buf_type], (void *)small_item, SMALL_ITEM_SIZE, 0, true);
|
|
buf_type++;
|
|
} else if (buf_type == NO_OF_RB_TYPES) {
|
|
//Check if all iterations complete
|
|
if (iterations < ISR_ITERATIONS) {
|
|
iterations++;
|
|
buf_type = 0; //Reset and iterate through each buffer type again
|
|
goto out;
|
|
} else {
|
|
//Signal complete
|
|
BaseType_t task_woken = pdFALSE;
|
|
xSemaphoreGiveFromISR(done_sem, &task_woken);
|
|
if (task_woken == pdTRUE) {
|
|
buf_type++;
|
|
need_yield = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
out:
|
|
return need_yield;
|
|
}
|
|
|
|
// IDF-6471 - test hangs up on QEMU
|
|
TEST_CASE("Test ring buffer ISR", "[esp_ringbuf][qemu-ignore]")
|
|
{
|
|
gptimer_handle_t gptimer;
|
|
for (int i = 0; i < NO_OF_RB_TYPES; i++) {
|
|
buffer_handles[i] = xRingbufferCreate(BUFFER_SIZE, i);
|
|
}
|
|
done_sem = xSemaphoreCreateBinary();
|
|
buf_type = 0;
|
|
iterations = 0;
|
|
|
|
//Setup timer for ISR
|
|
gptimer_config_t config = {
|
|
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
|
|
.direction = GPTIMER_COUNT_UP,
|
|
.resolution_hz = 1000000,
|
|
};
|
|
TEST_ESP_OK(gptimer_new_timer(&config, &gptimer));
|
|
gptimer_alarm_config_t alarm_config = {
|
|
.reload_count = 0,
|
|
.alarm_count = 2000,
|
|
.flags.auto_reload_on_alarm = true,
|
|
};
|
|
gptimer_event_callbacks_t cbs = {
|
|
.on_alarm = on_timer_alarm,
|
|
};
|
|
TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, NULL));
|
|
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
|
|
TEST_ESP_OK(gptimer_enable(gptimer));
|
|
TEST_ESP_OK(gptimer_start(gptimer));
|
|
//Wait for ISR to complete multiple iterations
|
|
xSemaphoreTake(done_sem, portMAX_DELAY);
|
|
|
|
//Cleanup
|
|
TEST_ESP_OK(gptimer_stop(gptimer));
|
|
TEST_ESP_OK(gptimer_disable(gptimer));
|
|
TEST_ESP_OK(gptimer_del_timer(gptimer));
|
|
vSemaphoreDelete(done_sem);
|
|
for (int i = 0; i < NO_OF_RB_TYPES; i++) {
|
|
vRingbufferDelete(buffer_handles[i]);
|
|
}
|
|
}
|
|
|
|
/* ---------------------------- Test ring buffer SMP ---------------------------
|
|
* The following test case tests each type of ring buffer in an SMP fashion. A
|
|
* sending task and a receiving task is created. The sending task will split
|
|
* a continuous piece of data into items of random length and send it to a ring
|
|
* buffer. The receiving task will receive and check those items.
|
|
* Every permutation of core pinning of the sending and receiving task will be
|
|
* tested.
|
|
*/
|
|
|
|
#if !CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH && !CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH
|
|
/* -------------------------- Test ring buffer IRAM ------------------------- */
|
|
|
|
static IRAM_ATTR __attribute__((noinline)) bool iram_ringbuf_test(void)
|
|
{
|
|
bool result = true;
|
|
uint8_t item[4];
|
|
size_t item_size;
|
|
RingbufHandle_t handle = xRingbufferCreate(CONT_DATA_TEST_BUFF_LEN, RINGBUF_TYPE_NOSPLIT);
|
|
result = result && (handle != NULL);
|
|
spi_flash_guard_get()->start(); // Disables flash cache
|
|
|
|
xRingbufferGetMaxItemSize(handle);
|
|
xRingbufferSendFromISR(handle, (void *)item, sizeof(item), NULL);
|
|
xRingbufferReceiveFromISR(handle, &item_size);
|
|
|
|
spi_flash_guard_get()->end(); // Re-enables flash cache
|
|
vRingbufferDelete(handle);
|
|
|
|
return result;
|
|
}
|
|
|
|
TEST_CASE("Test ringbuffer functions work with flash cache disabled", "[esp_ringbuf]")
|
|
{
|
|
TEST_ASSERT(iram_ringbuf_test());
|
|
}
|
|
#endif /* !CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH && !CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH */
|
|
|
|
/* ------------------------ Test ring buffer 0 Item Size -----------------------
|
|
* The following test case tests that sending/acquiring an item/bytes of 0 size
|
|
* is permissible.
|
|
*/
|
|
|
|
/* --------------------- Test ring buffer create with caps ---------------------
|
|
* The following test case tests ring buffer creation with caps. Specifically
|
|
* the following APIs:
|
|
*
|
|
* - xRingbufferCreateWithCaps()
|
|
* - vRingbufferDeleteWithCaps()
|
|
* - xRingbufferGetStaticBuffer()
|
|
*/
|
|
|
|
TEST_CASE("Test ringbuffer with caps", "[esp_ringbuf]")
|
|
{
|
|
RingbufHandle_t rb_handle;
|
|
uint8_t *rb_storage;
|
|
StaticRingbuffer_t *rb_obj;
|
|
|
|
// Create ring buffer with caps
|
|
rb_handle = xRingbufferCreateWithCaps(BUFFER_SIZE, RINGBUF_TYPE_NOSPLIT, (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT));
|
|
TEST_ASSERT_NOT_EQUAL(NULL, rb_handle);
|
|
|
|
// Get the ring buffer's memory
|
|
TEST_ASSERT_EQUAL(pdTRUE, xRingbufferGetStaticBuffer(rb_handle, &rb_storage, &rb_obj));
|
|
TEST_ASSERT(esp_ptr_in_dram(rb_storage));
|
|
TEST_ASSERT(esp_ptr_in_dram(rb_obj));
|
|
|
|
// Free the ring buffer
|
|
vRingbufferDeleteWithCaps(rb_handle);
|
|
}
|