mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-02 10:00:57 +02:00
feat(esp_ringbuf): Add vRingbufferReset
Function has similar behavior to xQueueReset() where... - Buffer is emptied - Blocked sender is unblocked Aslo added associated unit test cases.
This commit is contained in:
committed by
Guillaume Souchere
parent
13ec7d2d2a
commit
589d5b132d
@@ -386,6 +386,15 @@ void vRingbufferReturnItem(RingbufHandle_t xRingbuffer, void *pvItem);
|
||||
*/
|
||||
void vRingbufferReturnItemFromISR(RingbufHandle_t xRingbuffer, void *pvItem, BaseType_t *pxHigherPriorityTaskWoken);
|
||||
|
||||
/**
|
||||
* @brief Reset a ring buffer back to its original empty state
|
||||
*
|
||||
* @param[in] xRingbuffer Ring buffer to reset
|
||||
*
|
||||
* @note Users must ensure that all buffers are returned before calling this function
|
||||
*/
|
||||
void vRingbufferReset(RingbufHandle_t xRingbuffer);
|
||||
|
||||
/**
|
||||
* @brief Delete a ring buffer
|
||||
*
|
||||
|
@@ -1252,6 +1252,32 @@ void vRingbufferReturnItemFromISR(RingbufHandle_t xRingbuffer, void *pvItem, Bas
|
||||
portEXIT_CRITICAL_ISR(&pxRingbuffer->mux);
|
||||
}
|
||||
|
||||
void vRingbufferReset(RingbufHandle_t xRingbuffer)
|
||||
{
|
||||
Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer;
|
||||
configASSERT(pxRingbuffer);
|
||||
|
||||
portENTER_CRITICAL(&pxRingbuffer->mux);
|
||||
// Check for unreturned buffers
|
||||
configASSERT(pxRingbuffer->pucAcquire == pxRingbuffer->pucWrite);
|
||||
configASSERT(pxRingbuffer->pucRead == pxRingbuffer->pucFree);
|
||||
// Reset state
|
||||
pxRingbuffer->pucAcquire = pxRingbuffer->pucHead;
|
||||
pxRingbuffer->pucWrite = pxRingbuffer->pucHead;
|
||||
pxRingbuffer->pucRead = pxRingbuffer->pucHead;
|
||||
pxRingbuffer->pucFree = pxRingbuffer->pucHead;
|
||||
pxRingbuffer->xItemsWaiting = 0;
|
||||
pxRingbuffer->uxRingbufferFlags &= ~rbBUFFER_FULL_FLAG;
|
||||
|
||||
// If there's a task waiting to transmit, unblock it
|
||||
if (listLIST_IS_EMPTY(&pxRingbuffer->xTasksWaitingToSend) == pdFALSE) {
|
||||
if (xTaskRemoveFromEventList(&pxRingbuffer->xTasksWaitingToSend) == pdTRUE) {
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&pxRingbuffer->mux);
|
||||
}
|
||||
|
||||
void vRingbufferDelete(RingbufHandle_t xRingbuffer)
|
||||
{
|
||||
Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer;
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include "freertos/ringbuf.h"
|
||||
#include "unity.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_task.h"
|
||||
|
||||
#include "test_functions.h"
|
||||
|
||||
@@ -1318,3 +1319,62 @@ TEST_CASE("Test no-split full buffer becomes empty when oldest is returned last"
|
||||
TEST_ASSERT_NOT_NULL(slot);
|
||||
vRingbufferDelete(buffer_handle);
|
||||
}
|
||||
|
||||
/* ----------------------------------- Test ring buffer reset --------------------------------------
|
||||
* Reset Case: Test that vRingbufferReset() empties the ring buffer
|
||||
* Reset unblocks sender: Test that vRingbufferReset() will unblock a previously blocked sender
|
||||
*/
|
||||
|
||||
static uint8_t item[SMALL_ITEM_SIZE] = {0};
|
||||
|
||||
TEST_CASE("Test ring buffer reset", "[esp_ringbuf][linux]")
|
||||
{
|
||||
// Create buffer
|
||||
RingbufHandle_t rb = xRingbufferCreate(SMALL_ITEM_SIZE, RINGBUF_TYPE_BYTEBUF);
|
||||
TEST_ASSERT_MESSAGE(rb != NULL, "Failed to create ring buffer");
|
||||
// Fill buffer
|
||||
TEST_ASSERT_EQUAL(pdTRUE, xRingbufferSend(rb, item, SMALL_ITEM_SIZE, 0));
|
||||
// Confirm buffer is full
|
||||
TEST_ASSERT_EQUAL(0, xRingbufferGetCurFreeSize(rb));
|
||||
// Reset ring buffer
|
||||
vRingbufferReset(rb);
|
||||
// Confirm buffer is empty
|
||||
TEST_ASSERT_EQUAL(SMALL_ITEM_SIZE, xRingbufferGetCurFreeSize(rb));
|
||||
// Cleanup
|
||||
vRingbufferDelete(rb);
|
||||
}
|
||||
|
||||
static volatile bool post_reset_send = false;
|
||||
|
||||
static void post_reset_send_task(void *arg)
|
||||
{
|
||||
RingbufHandle_t rb = (RingbufHandle_t)arg;
|
||||
TEST_ASSERT_EQUAL(pdTRUE, xRingbufferSend(rb, item, SMALL_ITEM_SIZE, portMAX_DELAY));
|
||||
post_reset_send = true;
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("Test ring buffer reset unblocks sender ", "[esp_ringbuf][linux]")
|
||||
{
|
||||
// Create buffer
|
||||
RingbufHandle_t rb = xRingbufferCreate(SMALL_ITEM_SIZE, RINGBUF_TYPE_BYTEBUF);
|
||||
TEST_ASSERT_MESSAGE(rb != NULL, "Failed to create ring buffer");
|
||||
// Fill buffer
|
||||
TEST_ASSERT_EQUAL(pdTRUE, xRingbufferSend(rb, item, SMALL_ITEM_SIZE, 0));
|
||||
// Confirm buffer is full
|
||||
TEST_ASSERT_EQUAL(0, xRingbufferGetCurFreeSize(rb));
|
||||
// Launch task to block on sending to full ring buffer
|
||||
post_reset_send = false;
|
||||
xTaskCreatePinnedToCore(post_reset_send_task, "send tsk", 2048, (void*)rb, ESP_TASK_MAIN_PRIO + 1, NULL, 0);
|
||||
vTaskDelay(10);
|
||||
// Confirm blocked task has not sent
|
||||
TEST_ASSERT_EQUAL(false, post_reset_send);
|
||||
// Reset the ring buffer
|
||||
vRingbufferReset(rb);
|
||||
// Check task has unblocked and sent
|
||||
vTaskDelay(1);
|
||||
TEST_ASSERT_EQUAL(true, post_reset_send);
|
||||
// Cleanup
|
||||
vRingbufferDelete(rb);
|
||||
vTaskDelay(1);
|
||||
}
|
||||
|
Reference in New Issue
Block a user