1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2021-08-14 Jackistang add comments for function interface.
9 */
10 #ifndef RINGBUFFER_H__
11 #define RINGBUFFER_H__
12
13 #include <rtdef.h>
14 #include <rtconfig.h>
15 #include <rtthread.h>
16
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20
21 /* ring buffer */
22 struct rt_ringbuffer
23 {
24 rt_uint8_t *buffer_ptr;
25 /* use the msb of the {read,write}_index as mirror bit. You can see this as
26 * if the buffer adds a virtual mirror and the pointers point either to the
27 * normal or to the mirrored buffer. If the write_index has the same value
28 * with the read_index, but in a different mirror, the buffer is full.
29 * While if the write_index and the read_index are the same and within the
30 * same mirror, the buffer is empty. The ASCII art of the ringbuffer is:
31 *
32 * mirror = 0 mirror = 1
33 * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
34 * | 0 | 1 | 2 | 3 | 4 | 5 | 6 ||| 0 | 1 | 2 | 3 | 4 | 5 | 6 | Full
35 * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
36 * read_idx-^ write_idx-^
37 *
38 * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
39 * | 0 | 1 | 2 | 3 | 4 | 5 | 6 ||| 0 | 1 | 2 | 3 | 4 | 5 | 6 | Empty
40 * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
41 * read_idx-^ ^-write_idx
42 */
43
44 rt_uint32_t read_mirror : 1;
45 rt_uint32_t read_index : 31;
46 rt_uint32_t write_mirror : 1;
47 rt_uint32_t write_index : 31;
48 /* as we use msb of index as mirror bit, the size should be signed and
49 * could only be positive. */
50 rt_int32_t buffer_size;
51 };
52
53 enum rt_ringbuffer_state
54 {
55 RT_RINGBUFFER_EMPTY,
56 RT_RINGBUFFER_FULL,
57 /* half full is neither full nor empty */
58 RT_RINGBUFFER_HALFFULL,
59 };
60
61 /**
62 * RingBuffer for DeviceDriver
63 *
64 * Please note that the ring buffer implementation of RT-Thread
65 * has no thread wait or resume feature.
66 */
67 void rt_ringbuffer_init(struct rt_ringbuffer *rb, rt_uint8_t *pool, rt_int32_t size);
68 void rt_ringbuffer_reset(struct rt_ringbuffer *rb);
69 rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb, const rt_uint8_t *ptr, rt_uint32_t length);
70 rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb, const rt_uint8_t *ptr, rt_uint32_t length);
71 rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch);
72 rt_size_t rt_ringbuffer_putchar_force(struct rt_ringbuffer *rb, const rt_uint8_t ch);
73 rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb, rt_uint8_t *ptr, rt_uint32_t length);
74 rt_size_t rt_ringbuffer_peek(struct rt_ringbuffer *rb, rt_uint8_t **ptr);
75 rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch);
76 rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb);
77
78 #ifdef RT_USING_HEAP
79 struct rt_ringbuffer* rt_ringbuffer_create(rt_uint32_t length);
80 void rt_ringbuffer_destroy(struct rt_ringbuffer *rb);
81 #endif
82
83 /**
84 * @brief Get the buffer size of the ring buffer object.
85 *
86 * @param rb A pointer to the ring buffer object.
87 *
88 * @return Buffer size.
89 */
rt_ringbuffer_get_size(struct rt_ringbuffer * rb)90 rt_inline rt_uint32_t rt_ringbuffer_get_size(struct rt_ringbuffer *rb)
91 {
92 RT_ASSERT(rb != RT_NULL);
93 return rb->buffer_size;
94 }
95
96 /** return the size of empty space in rb */
97 #define rt_ringbuffer_space_len(rb) ((rb)->buffer_size - rt_ringbuffer_data_len(rb))
98
99
100 #ifdef __cplusplus
101 }
102 #endif
103
104 #endif
105