From 7d983fe5a30057ab84cbdf6ce7d60e127f5c12d6 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Sat, 24 Jun 2023 21:30:53 +0800 Subject: [PATCH] esp_ringbuf: Add xRingbufferCreateWithCaps() This commit adds APIS to create a ring buffer with specific memory caps. The following APIs have been added: - xRingbufferGetStaticBuffer() - xRingbufferCreateWithCaps() - vRingbufferDeleteWithCaps() --- .../esp_ringbuf/include/freertos/ringbuf.h | 34 ++++++++++ components/esp_ringbuf/ringbuf.c | 64 +++++++++++++++++++ .../esp_ringbuf/test_apps/main/test_ringbuf.c | 31 ++++++++- 3 files changed, 128 insertions(+), 1 deletion(-) diff --git a/components/esp_ringbuf/include/freertos/ringbuf.h b/components/esp_ringbuf/include/freertos/ringbuf.h index 64d7365e79..942b3262b0 100644 --- a/components/esp_ringbuf/include/freertos/ringbuf.h +++ b/components/esp_ringbuf/include/freertos/ringbuf.h @@ -513,6 +513,40 @@ void vRingbufferGetInfo(RingbufHandle_t xRingbuffer, */ void xRingbufferPrintInfo(RingbufHandle_t xRingbuffer); +/** + * @brief Retrieve the pointers to a statically created ring buffer + * + * @param[in] xRingbuffer Ring buffer + * @param[out] ppucRingbufferStorage Used to return a pointer to the queue's storage area buffer + * @param[out] ppxStaticRingbuffer Used to return a pointer to the queue's data structure buffer + * @return pdTRUE if buffers were retrieved, pdFALSE otherwise. + */ +BaseType_t xRingbufferGetStaticBuffer(RingbufHandle_t xRingbuffer, uint8_t **ppucRingbufferStorage, StaticRingbuffer_t **ppxStaticRingbuffer); + +/** + * @brief Creates a ring buffer with specific memory capabilities + * + * This function is similar to xRingbufferCreate(), except that it allows the + * memory allocated for the ring buffer to have specific capabilities (e.g., + * MALLOC_CAP_INTERNAL). + * + * @note A queue created using this function must only be deleted using + * vRingbufferDeleteWithCaps() + * @param[in] xBufferSize Size of the buffer in bytes + * @param[in] xBufferType Type of ring buffer, see documentation. + * @param[in] uxMemoryCaps Memory capabilities of the queue's memory (see + * esp_heap_caps.h) + * @return Handle to the created ring buffer or NULL on failure. + */ +RingbufHandle_t xRingbufferCreateWithCaps(size_t xBufferSize, RingbufferType_t xBufferType, UBaseType_t uxMemoryCaps); + +/** + * @brief Deletes a ring buffer previously created using xRingbufferCreateWithCaps() + * + * @param xRingbuffer Ring buffer + */ +void vRingbufferDeleteWithCaps(RingbufHandle_t xRingbuffer); + #ifdef __cplusplus } #endif diff --git a/components/esp_ringbuf/ringbuf.c b/components/esp_ringbuf/ringbuf.c index 0f90d07a9b..1457db4d34 100644 --- a/components/esp_ringbuf/ringbuf.c +++ b/components/esp_ringbuf/ringbuf.c @@ -11,6 +11,7 @@ #include "freertos/task.h" #include "freertos/queue.h" #include "freertos/ringbuf.h" +#include "esp_heap_caps.h" // ------------------------------------------------- Macros and Types -------------------------------------------------- @@ -1360,3 +1361,66 @@ void xRingbufferPrintInfo(RingbufHandle_t xRingbuffer) pxRingbuffer->pucWrite - pxRingbuffer->pucHead, pxRingbuffer->pucAcquire - pxRingbuffer->pucHead); } + +BaseType_t xRingbufferGetStaticBuffer(RingbufHandle_t xRingbuffer, uint8_t **ppucRingbufferStorage, StaticRingbuffer_t **ppxStaticRingbuffer) +{ + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + BaseType_t xReturn; + + configASSERT(pxRingbuffer && ppucRingbufferStorage && ppxStaticRingbuffer); + + if (pxRingbuffer->uxRingbufferFlags & rbBUFFER_STATIC_FLAG) { + *ppucRingbufferStorage = pxRingbuffer->pucHead; + *ppxStaticRingbuffer = (StaticRingbuffer_t *)pxRingbuffer; + xReturn = pdTRUE; + } else { + xReturn = pdFALSE; + } + + return xReturn; +} + +RingbufHandle_t xRingbufferCreateWithCaps(size_t xBufferSize, RingbufferType_t xBufferType, UBaseType_t uxMemoryCaps) +{ + RingbufHandle_t xRingbuffer; + StaticRingbuffer_t *pxStaticRingbuffer; + uint8_t *pucRingbufferStorage; + + pxStaticRingbuffer = heap_caps_malloc(sizeof(StaticRingbuffer_t), (uint32_t)uxMemoryCaps); + pucRingbufferStorage = heap_caps_malloc(xBufferSize, (uint32_t)uxMemoryCaps); + + if (pxStaticRingbuffer == NULL || pucRingbufferStorage == NULL) { + goto err; + } + + // Create the ring buffer using static creation API + xRingbuffer = xRingbufferCreateStatic(xBufferSize, xBufferType, pucRingbufferStorage, pxStaticRingbuffer); + if (xRingbuffer == NULL) { + goto err; + } + + return xRingbuffer; + +err: + heap_caps_free(pxStaticRingbuffer); + heap_caps_free(pucRingbufferStorage); + return NULL; +} + +void vRingbufferDeleteWithCaps(RingbufHandle_t xRingbuffer) +{ + BaseType_t xResult; + StaticRingbuffer_t *pxStaticRingbuffer = NULL; + uint8_t *pucRingbufferStorage = NULL; + + // Retrieve the buffers used to create the ring buffer before deleting it + xResult = xRingbufferGetStaticBuffer(xRingbuffer, &pucRingbufferStorage, &pxStaticRingbuffer); + configASSERT(xResult == pdTRUE); + + // Delete the ring buffer + vRingbufferDelete(xRingbuffer); + + // Free the memory buffers + heap_caps_free(pxStaticRingbuffer); + heap_caps_free(pucRingbufferStorage); +} diff --git a/components/esp_ringbuf/test_apps/main/test_ringbuf.c b/components/esp_ringbuf/test_apps/main/test_ringbuf.c index 18e640a499..6fcea7fbd5 100644 --- a/components/esp_ringbuf/test_apps/main/test_ringbuf.c +++ b/components/esp_ringbuf/test_apps/main/test_ringbuf.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,7 @@ #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 "spi_flash_mmap.h" #include "unity.h" @@ -1093,3 +1094,31 @@ TEST_CASE("Test ringbuffer 0 item size", "[esp_ringbuf]") vRingbufferDelete(allow_split_rb); vRingbufferDelete(byte_rb); } + +/* --------------------- 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); +}