mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-02 10:00:57 +02:00
Merge branch 'feat/add-ringbuf-reset' into 'master'
feat(esp_ringbuf): Add vRingbufferReset Closes IDFGH-16385 See merge request espressif/esp-idf!41717
This commit is contained in:
@@ -386,6 +386,16 @@ 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
|
||||
*
|
||||
* @return ESP_ERR_INVALID_STATE if one or more items are not sent, completed or returned
|
||||
* ESP_OK if the operation was successful
|
||||
*/
|
||||
esp_err_t vRingbufferReset(RingbufHandle_t xRingbuffer);
|
||||
|
||||
/**
|
||||
* @brief Delete a ring buffer
|
||||
*
|
||||
|
@@ -1252,6 +1252,38 @@ void vRingbufferReturnItemFromISR(RingbufHandle_t xRingbuffer, void *pvItem, Bas
|
||||
portEXIT_CRITICAL_ISR(&pxRingbuffer->mux);
|
||||
}
|
||||
|
||||
esp_err_t vRingbufferReset(RingbufHandle_t xRingbuffer)
|
||||
{
|
||||
Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer;
|
||||
configASSERT(pxRingbuffer);
|
||||
|
||||
portENTER_CRITICAL(&pxRingbuffer->mux);
|
||||
// Check for unreturned buffers
|
||||
if ((pxRingbuffer->pucAcquire != pxRingbuffer->pucWrite) ||
|
||||
(pxRingbuffer->pucRead != pxRingbuffer->pucFree)) {
|
||||
portEXIT_CRITICAL(&pxRingbuffer->mux);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
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,61 @@ 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);
|
||||
|
||||
TEST_ASSERT_EQUAL(true, post_reset_send);
|
||||
// Cleanup
|
||||
vRingbufferDelete(rb);
|
||||
vTaskDelay(1);
|
||||
}
|
||||
|
Reference in New Issue
Block a user