浏览代码

fix(drivers/ipc): correct rt_ringbuffer_peek to not consume data

Shaun 3 天之前
父节点
当前提交
ffcd1cb316

+ 1 - 0
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);

+ 44 - 4
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);
 
 /**

+ 4 - 4
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;