From ffcd1cb3160b18ba789c6ae620b5e1c5d76052bc Mon Sep 17 00:00:00 2001 From: Shaun Date: Mon, 23 Feb 2026 00:59:33 +0800 Subject: fix(drivers/ipc): correct rt_ringbuffer_peek to not consume data --- components/drivers/include/ipc/ringbuffer.h | 1 + components/drivers/ipc/ringbuffer.c | 48 ++++++++++++++++++++++++++--- components/drivers/serial/dev_serial_v2.c | 8 ++--- 3 files changed, 49 insertions(+), 8 deletions(-) (limited to 'components/drivers') diff --git a/components/drivers/include/ipc/ringbuffer.h b/components/drivers/include/ipc/ringbuffer.h index 5a585542a7..71fc66e0ec 100644 --- a/components/drivers/include/ipc/ringbuffer.h +++ b/components/drivers/include/ipc/ringbuffer.h @@ -71,6 +71,7 @@ rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb, const rt_uint8_t *pt rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch); rt_size_t rt_ringbuffer_putchar_force(struct rt_ringbuffer *rb, const rt_uint8_t ch); rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb, rt_uint8_t *ptr, rt_uint32_t length); +rt_size_t rt_ringbuffer_get_direct(struct rt_ringbuffer *rb, rt_uint8_t **ptr); rt_size_t rt_ringbuffer_peek(struct rt_ringbuffer *rb, rt_uint8_t **ptr); rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch); rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb); diff --git a/components/drivers/ipc/ringbuffer.c b/components/drivers/ipc/ringbuffer.c index 138eff055e..b5c2c358f2 100644 --- a/components/drivers/ipc/ringbuffer.c +++ b/components/drivers/ipc/ringbuffer.c @@ -219,16 +219,18 @@ rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb, RTM_EXPORT(rt_ringbuffer_get); /** - * @brief Get the first readable byte of the ring buffer. + * @brief Get data from the ring buffer in zero-copy mode. * * @param rb A pointer to the ringbuffer. * @param ptr When this function return, *ptr is a pointer to the first readable byte of the ring buffer. * - * @note It is recommended to read only one byte, otherwise it may cause buffer overflow. + * @note This function returns a direct pointer to the internal buffer and consumes the data + * (advances read_index). It returns the contiguous readable data length. If data wraps + * around the buffer end, call this function again to get the remaining segment. * - * @return Return the size of the ring buffer. + * @return Return the contiguous readable data size we consumed from the ring buffer. */ -rt_size_t rt_ringbuffer_peek(struct rt_ringbuffer *rb, rt_uint8_t **ptr) +rt_size_t rt_ringbuffer_get_direct(struct rt_ringbuffer *rb, rt_uint8_t **ptr) { rt_size_t size; @@ -259,6 +261,44 @@ rt_size_t rt_ringbuffer_peek(struct rt_ringbuffer *rb, rt_uint8_t **ptr) return size; } +RTM_EXPORT(rt_ringbuffer_get_direct); + +/** + * @brief Get the first readable byte of the ring buffer. + * + * @param rb A pointer to the ringbuffer. + * @param ptr When this function return, *ptr is a pointer to the first readable byte of the ring buffer. + * + * @note It is recommended to read only one byte, otherwise it may cause buffer overflow. + * + * @return Return the size of the ring buffer. + */ +rt_size_t rt_ringbuffer_peek(struct rt_ringbuffer *rb, rt_uint8_t **ptr) +{ + rt_size_t size; + + RT_ASSERT(rb != RT_NULL); + + *ptr = RT_NULL; + + /* whether has enough data */ + size = rt_ringbuffer_data_len(rb); + + /* no data */ + if (size == 0) + return 0; + + *ptr = &rb->buffer_ptr[rb->read_index]; + + if ((rt_size_t)(rb->buffer_size - rb->read_index) > size) + { + return size; + } + + size = rb->buffer_size - rb->read_index; + + return size; +} RTM_EXPORT(rt_ringbuffer_peek); /** diff --git a/components/drivers/serial/dev_serial_v2.c b/components/drivers/serial/dev_serial_v2.c index 13007cbe5e..0a7c343b79 100644 --- a/components/drivers/serial/dev_serial_v2.c +++ b/components/drivers/serial/dev_serial_v2.c @@ -2000,13 +2000,13 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event) { rt_serial_update_write_index(&rx_fifo->dma_ping_rb, rx_length); - size = rt_ringbuffer_peek(&rx_fifo->dma_ping_rb, &ptr); + size = rt_ringbuffer_get_direct(&rx_fifo->dma_ping_rb, &ptr); put_len = rt_ringbuffer_put(&rx_fifo->rb, ptr, size); if (put_len != size) break; - size = rt_ringbuffer_peek(&rx_fifo->dma_ping_rb, &ptr); + size = rt_ringbuffer_get_direct(&rx_fifo->dma_ping_rb, &ptr); if (size == 0) break; @@ -2022,11 +2022,11 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event) { rt_serial_update_write_index(&rx_fifo->dma_ping_rb, rx_length); - size = rt_ringbuffer_peek(&rx_fifo->dma_ping_rb, &ptr); + size = rt_ringbuffer_get_direct(&rx_fifo->dma_ping_rb, &ptr); rt_ringbuffer_put_force(&rx_fifo->rb, ptr, size); - size = rt_ringbuffer_peek(&rx_fifo->dma_ping_rb, &ptr); + size = rt_ringbuffer_get_direct(&rx_fifo->dma_ping_rb, &ptr); if (size == 0) break; -- cgit v1.3.1