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 @@ -218,6 +218,51 @@ rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb, } RTM_EXPORT(rt_ringbuffer_get); +/** + * @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 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 contiguous readable data size we consumed from the ring buffer. + */ +rt_size_t rt_ringbuffer_get_direct(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) + { + rb->read_index += size; + return size; + } + + size = rb->buffer_size - rb->read_index; + + /* we are going into the other side of the mirror */ + rb->read_mirror = ~rb->read_mirror; + rb->read_index = 0; + + return size; +} +RTM_EXPORT(rt_ringbuffer_get_direct); + /** * @brief Get the first readable byte of the ring buffer. * @@ -247,16 +292,11 @@ rt_size_t rt_ringbuffer_peek(struct rt_ringbuffer *rb, rt_uint8_t **ptr) if ((rt_size_t)(rb->buffer_size - rb->read_index) > size) { - rb->read_index += size; return size; } size = rb->buffer_size - rb->read_index; - /* we are going into the other side of the mirror */ - rb->read_mirror = ~rb->read_mirror; - rb->read_index = 0; - 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;