[ringbuffer] ringbuffer size boost to 32bit (#6915)

* ringbuffer size boost to 32bit
* 添加ringbuffer测试demo
related: #682
----
Co-authored-by: Zxy <1308465141@qq.com>
Co-authored-by: Man, Jianting (Meco) <920369182@qq.com>
This commit is contained in:
螺丝松掉的人 2023-02-09 11:55:52 +08:00 committed by GitHub
parent f58d3c5200
commit 20459ec4d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 130 additions and 27 deletions

View File

@ -37,18 +37,15 @@ struct rt_ringbuffer
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 ||| 0 | 1 | 2 | 3 | 4 | 5 | 6 | Empty * | 0 | 1 | 2 | 3 | 4 | 5 | 6 ||| 0 | 1 | 2 | 3 | 4 | 5 | 6 | Empty
* +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+ * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
* read_idx-^ ^-write_idx * read_idx-^ ^-write_idx
* */
* The tradeoff is we could only use 32KiB of buffer for 16 bit of index.
* But it should be enough for most of the cases. rt_uint32_t read_mirror : 1;
* rt_uint32_t read_index : 31;
* Ref: http://en.wikipedia.org/wiki/Circular_buffer#Mirroring */ rt_uint32_t write_mirror : 1;
rt_uint16_t read_mirror : 1; rt_uint32_t write_index : 31;
rt_uint16_t read_index : 15;
rt_uint16_t write_mirror : 1;
rt_uint16_t write_index : 15;
/* as we use msb of index as mirror bit, the size should be signed and /* as we use msb of index as mirror bit, the size should be signed and
* could only be positive. */ * could only be positive. */
rt_int16_t buffer_size; rt_int32_t buffer_size;
}; };
enum rt_ringbuffer_state enum rt_ringbuffer_state
@ -65,19 +62,19 @@ enum rt_ringbuffer_state
* Please note that the ring buffer implementation of RT-Thread * Please note that the ring buffer implementation of RT-Thread
* has no thread wait or resume feature. * has no thread wait or resume feature.
*/ */
void rt_ringbuffer_init(struct rt_ringbuffer *rb, rt_uint8_t *pool, rt_int16_t size); void rt_ringbuffer_init(struct rt_ringbuffer *rb, rt_uint8_t *pool, rt_int32_t size);
void rt_ringbuffer_reset(struct rt_ringbuffer *rb); void rt_ringbuffer_reset(struct rt_ringbuffer *rb);
rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb, const rt_uint8_t *ptr, rt_uint16_t length); rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb, const rt_uint8_t *ptr, rt_uint32_t length);
rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb, const rt_uint8_t *ptr, rt_uint16_t length); rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb, const rt_uint8_t *ptr, rt_uint32_t length);
rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch); 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_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_uint16_t length); rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb, rt_uint8_t *ptr, rt_uint32_t length);
rt_size_t rt_ringbuffer_peek(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_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch);
rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb); rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb);
#ifdef RT_USING_HEAP #ifdef RT_USING_HEAP
struct rt_ringbuffer* rt_ringbuffer_create(rt_uint16_t length); struct rt_ringbuffer* rt_ringbuffer_create(rt_uint32_t length);
void rt_ringbuffer_destroy(struct rt_ringbuffer *rb); void rt_ringbuffer_destroy(struct rt_ringbuffer *rb);
#endif #endif
@ -88,14 +85,14 @@ void rt_ringbuffer_destroy(struct rt_ringbuffer *rb);
* *
* @return Buffer size. * @return Buffer size.
*/ */
rt_inline rt_uint16_t rt_ringbuffer_get_size(struct rt_ringbuffer *rb) rt_inline rt_uint32_t rt_ringbuffer_get_size(struct rt_ringbuffer *rb)
{ {
RT_ASSERT(rb != RT_NULL); RT_ASSERT(rb != RT_NULL);
return rb->buffer_size; return rb->buffer_size;
} }
/** return the size of empty space in rb */ /** return the size of empty space in rb */
#define rt_ringbuffer_space_len(rb) ((rb)->buffer_size - (rt_int16_t)rt_ringbuffer_data_len(rb)) #define rt_ringbuffer_space_len(rb) ((rb)->buffer_size - rt_ringbuffer_data_len(rb))
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2021, RT-Thread Development Team * Copyright (c) 2006-2023, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
@ -37,7 +37,7 @@ rt_inline enum rt_ringbuffer_state rt_ringbuffer_status(struct rt_ringbuffer *rb
*/ */
void rt_ringbuffer_init(struct rt_ringbuffer *rb, void rt_ringbuffer_init(struct rt_ringbuffer *rb,
rt_uint8_t *pool, rt_uint8_t *pool,
rt_int16_t size) rt_int32_t size)
{ {
RT_ASSERT(rb != RT_NULL); RT_ASSERT(rb != RT_NULL);
RT_ASSERT(size > 0); RT_ASSERT(size > 0);
@ -63,9 +63,9 @@ RTM_EXPORT(rt_ringbuffer_init);
*/ */
rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb, rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
const rt_uint8_t *ptr, const rt_uint8_t *ptr,
rt_uint16_t length) rt_uint32_t length)
{ {
rt_uint16_t size; rt_uint32_t size;
RT_ASSERT(rb != RT_NULL); RT_ASSERT(rb != RT_NULL);
@ -116,9 +116,9 @@ RTM_EXPORT(rt_ringbuffer_put);
*/ */
rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb, rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb,
const rt_uint8_t *ptr, const rt_uint8_t *ptr,
rt_uint16_t length) rt_uint32_t length)
{ {
rt_uint16_t space_length; rt_uint32_t space_length;
RT_ASSERT(rb != RT_NULL); RT_ASSERT(rb != RT_NULL);
@ -177,7 +177,7 @@ RTM_EXPORT(rt_ringbuffer_put_force);
*/ */
rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb, rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
rt_uint8_t *ptr, rt_uint8_t *ptr,
rt_uint16_t length) rt_uint32_t length)
{ {
rt_size_t size; rt_size_t size;
@ -192,7 +192,7 @@ rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
/* less data */ /* less data */
if (size < length) if (size < length)
length = (rt_uint16_t)size; length = size;
if (rb->buffer_size - rb->read_index > length) if (rb->buffer_size - rb->read_index > length)
{ {
@ -248,7 +248,7 @@ 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) if ((rt_size_t)(rb->buffer_size - rb->read_index) > size)
{ {
rb->read_index += (rt_uint16_t)size; rb->read_index += size;
return size; return size;
} }
@ -423,7 +423,7 @@ RTM_EXPORT(rt_ringbuffer_reset);
* *
* @return Return a pointer to ring buffer object. When the return value is RT_NULL, it means this creation failed. * @return Return a pointer to ring buffer object. When the return value is RT_NULL, it means this creation failed.
*/ */
struct rt_ringbuffer *rt_ringbuffer_create(rt_uint16_t size) struct rt_ringbuffer *rt_ringbuffer_create(rt_uint32_t size)
{ {
struct rt_ringbuffer *rb; struct rt_ringbuffer *rb;
rt_uint8_t *pool; rt_uint8_t *pool;

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-07 ZXY the first version
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <string.h>
#include <ipc/ringbuffer.h>
#define RING_BUFFER_LEN 8
static struct ringbuffer *rb;
static char *str = "Hello, World new ringbuffer32";
typedef struct rb_example {
rt_uint32_t a;
rt_uint32_t b;
rt_uint32_t c;
} rb_example_t;
int ringbuffer_example(void)
{
rb_example_t data = {
.a = 1,
.b = 2,
};
struct rt_ringbuffer * rb = rt_ringbuffer_create(sizeof(rb_example_t) * 2);
RT_ASSERT(rb != RT_NULL);
rt_kprintf("Put data to ringbuffer, a: %d b: %d size: %d\n", data.a, data.b, sizeof(data));
rt_ringbuffer_put(rb, (rt_uint8_t *)&data, sizeof(data));
rb_example_t recv_data;
rt_size_t recv = rt_ringbuffer_get(rb, (rt_uint8_t *)&recv_data, sizeof(recv_data));
RT_ASSERT(recv == sizeof(recv_data));
rt_kprintf("Get data from ringbuffer, a: %d b: %d size: %d\n", recv_data.a, recv_data.b, sizeof(recv_data));
return 0;
}
MSH_CMD_EXPORT(ringbuffer_example, ringbuffer example);
int ringbuffer_force_example(void)
{
uint8_t test[6] = {1,2,3,4,5,6};
struct rt_ringbuffer * rb;
rb = rt_ringbuffer_create(4);
RT_ASSERT(rb != RT_NULL);
rt_kprintf("Put data to ringbuffer, %d %d %d %d %d %d\n", test[0],test[1],test[2],test[3],test[4],test[5]);
rt_ringbuffer_put_force(rb, (rt_uint8_t *)&test, sizeof(test));
uint8_t recv_data[4]={0};
rt_ringbuffer_get(rb, (rt_uint8_t *)&recv_data, sizeof(test));
rt_kprintf("Get data from ringbuffer, %d %d %d %d\n", recv_data[0],recv_data[1],recv_data[2],recv_data[3]);
rt_kprintf("write mirror: %d read mirror: %d\n", rb->write_mirror,rb->read_mirror);
return 0;
}
MSH_CMD_EXPORT(ringbuffer_force_example, ringbuffer example);
static void consumer_thread_entry(void *arg)
{
char ch;
while (1)
{
if (1 == rt_ringbuffer_getchar(rb, &ch))
{
rt_kprintf("[Consumer] <- %c\n", ch);
}
rt_thread_mdelay(500);
}
}
static void ringbuffer_sample(int argc, char** argv)
{
rt_thread_t tid;
rt_uint16_t i = 0;
rb = rt_ringbuffer_create(RING_BUFFER_LEN);
if (rb == RT_NULL)
{
rt_kprintf("Can't create ringbffer");
return;
}
tid = rt_thread_create("consumer", consumer_thread_entry, RT_NULL,
1024, RT_THREAD_PRIORITY_MAX/3, 20);
if (tid == RT_NULL)
{
rt_ringbuffer_destroy(rb);
}
rt_thread_startup(tid);
while (str[i] != '\0')
{
rt_kprintf("[Producer] -> %c\n", str[i]);
rt_ringbuffer_putchar(rb, str[i++]);
rt_thread_mdelay(500);
}
rt_thread_delete(tid);
rt_ringbuffer_destroy(rb);
}
MSH_CMD_EXPORT(ringbuffer_sample, Start a producer and a consumer with a ringbuffer);