Skip to content

Commit 4c589d6

Browse files
committed
Merge branch 'feat/add-ringbuf-reset' into 'master'
feat(esp_ringbuf): Add vRingbufferReset Closes IDFGH-16385 See merge request espressif/esp-idf!41717
2 parents b614744 + c03987c commit 4c589d6

File tree

3 files changed

+101
-0
lines changed

3 files changed

+101
-0
lines changed

components/esp_ringbuf/include/freertos/ringbuf.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,16 @@ void vRingbufferReturnItem(RingbufHandle_t xRingbuffer, void *pvItem);
386386
*/
387387
void vRingbufferReturnItemFromISR(RingbufHandle_t xRingbuffer, void *pvItem, BaseType_t *pxHigherPriorityTaskWoken);
388388

389+
/**
390+
* @brief Reset a ring buffer back to its original empty state
391+
*
392+
* @param[in] xRingbuffer Ring buffer to reset
393+
*
394+
* @return ESP_ERR_INVALID_STATE if one or more items are not sent, completed or returned
395+
* ESP_OK if the operation was successful
396+
*/
397+
esp_err_t vRingbufferReset(RingbufHandle_t xRingbuffer);
398+
389399
/**
390400
* @brief Delete a ring buffer
391401
*

components/esp_ringbuf/ringbuf.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,38 @@ void vRingbufferReturnItemFromISR(RingbufHandle_t xRingbuffer, void *pvItem, Bas
12521252
portEXIT_CRITICAL_ISR(&pxRingbuffer->mux);
12531253
}
12541254

1255+
esp_err_t vRingbufferReset(RingbufHandle_t xRingbuffer)
1256+
{
1257+
Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer;
1258+
configASSERT(pxRingbuffer);
1259+
1260+
portENTER_CRITICAL(&pxRingbuffer->mux);
1261+
// Check for unreturned buffers
1262+
if ((pxRingbuffer->pucAcquire != pxRingbuffer->pucWrite) ||
1263+
(pxRingbuffer->pucRead != pxRingbuffer->pucFree)) {
1264+
portEXIT_CRITICAL(&pxRingbuffer->mux);
1265+
return ESP_ERR_INVALID_STATE;
1266+
}
1267+
1268+
// Reset state
1269+
pxRingbuffer->pucAcquire = pxRingbuffer->pucHead;
1270+
pxRingbuffer->pucWrite = pxRingbuffer->pucHead;
1271+
pxRingbuffer->pucRead = pxRingbuffer->pucHead;
1272+
pxRingbuffer->pucFree = pxRingbuffer->pucHead;
1273+
pxRingbuffer->xItemsWaiting = 0;
1274+
pxRingbuffer->uxRingbufferFlags &= ~rbBUFFER_FULL_FLAG;
1275+
1276+
// If there's a task waiting to transmit, unblock it
1277+
if (listLIST_IS_EMPTY(&pxRingbuffer->xTasksWaitingToSend) == pdFALSE) {
1278+
if (xTaskRemoveFromEventList(&pxRingbuffer->xTasksWaitingToSend) == pdTRUE) {
1279+
portYIELD_WITHIN_API();
1280+
}
1281+
}
1282+
portEXIT_CRITICAL(&pxRingbuffer->mux);
1283+
1284+
return ESP_OK;
1285+
}
1286+
12551287
void vRingbufferDelete(RingbufHandle_t xRingbuffer)
12561288
{
12571289
Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer;

components/esp_ringbuf/test_apps/main/test_ringbuf_common.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "freertos/ringbuf.h"
2121
#include "unity.h"
2222
#include "esp_rom_sys.h"
23+
#include "esp_task.h"
2324

2425
#include "test_functions.h"
2526

@@ -1318,3 +1319,61 @@ TEST_CASE("Test no-split full buffer becomes empty when oldest is returned last"
13181319
TEST_ASSERT_NOT_NULL(slot);
13191320
vRingbufferDelete(buffer_handle);
13201321
}
1322+
1323+
/* ----------------------------------- Test ring buffer reset --------------------------------------
1324+
* Reset Case: Test that vRingbufferReset() empties the ring buffer
1325+
* Reset unblocks sender: Test that vRingbufferReset() will unblock a previously blocked sender
1326+
*/
1327+
1328+
static uint8_t item[SMALL_ITEM_SIZE] = {0};
1329+
1330+
TEST_CASE("Test ring buffer reset", "[esp_ringbuf][linux]")
1331+
{
1332+
// Create buffer
1333+
RingbufHandle_t rb = xRingbufferCreate(SMALL_ITEM_SIZE, RINGBUF_TYPE_BYTEBUF);
1334+
TEST_ASSERT_MESSAGE(rb != NULL, "Failed to create ring buffer");
1335+
// Fill buffer
1336+
TEST_ASSERT_EQUAL(pdTRUE, xRingbufferSend(rb, item, SMALL_ITEM_SIZE, 0));
1337+
// Confirm buffer is full
1338+
TEST_ASSERT_EQUAL(0, xRingbufferGetCurFreeSize(rb));
1339+
// Reset ring buffer
1340+
vRingbufferReset(rb);
1341+
// Confirm buffer is empty
1342+
TEST_ASSERT_EQUAL(SMALL_ITEM_SIZE, xRingbufferGetCurFreeSize(rb));
1343+
// Cleanup
1344+
vRingbufferDelete(rb);
1345+
}
1346+
1347+
static volatile bool post_reset_send = false;
1348+
1349+
static void post_reset_send_task(void *arg)
1350+
{
1351+
RingbufHandle_t rb = (RingbufHandle_t)arg;
1352+
TEST_ASSERT_EQUAL(pdTRUE, xRingbufferSend(rb, item, SMALL_ITEM_SIZE, portMAX_DELAY));
1353+
post_reset_send = true;
1354+
vTaskDelete(NULL);
1355+
}
1356+
1357+
TEST_CASE("Test ring buffer reset unblocks sender ", "[esp_ringbuf][linux]")
1358+
{
1359+
// Create buffer
1360+
RingbufHandle_t rb = xRingbufferCreate(SMALL_ITEM_SIZE, RINGBUF_TYPE_BYTEBUF);
1361+
TEST_ASSERT_MESSAGE(rb != NULL, "Failed to create ring buffer");
1362+
// Fill buffer
1363+
TEST_ASSERT_EQUAL(pdTRUE, xRingbufferSend(rb, item, SMALL_ITEM_SIZE, 0));
1364+
// Confirm buffer is full
1365+
TEST_ASSERT_EQUAL(0, xRingbufferGetCurFreeSize(rb));
1366+
// Launch task to block on sending to full ring buffer
1367+
post_reset_send = false;
1368+
xTaskCreatePinnedToCore(post_reset_send_task, "send tsk", 2048, (void*)rb, ESP_TASK_MAIN_PRIO + 1, NULL, 0);
1369+
vTaskDelay(10);
1370+
// Confirm blocked task has not sent
1371+
TEST_ASSERT_EQUAL(false, post_reset_send);
1372+
// Reset the ring buffer
1373+
vRingbufferReset(rb);
1374+
1375+
TEST_ASSERT_EQUAL(true, post_reset_send);
1376+
// Cleanup
1377+
vRingbufferDelete(rb);
1378+
vTaskDelay(1);
1379+
}

0 commit comments

Comments
 (0)