1 /* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 */ 9 #ifndef RINGBUFFER_H__ 10 #define RINGBUFFER_H__ 11 12 #ifdef __cplusplus 13 extern "C" { 14 #endif 15 16 #include <rtthread.h> 17 18 /* ring buffer */ 19 struct rt_ringbuffer 20 { 21 rt_uint8_t *buffer_ptr; 22 /* use the msb of the {read,write}_index as mirror bit. You can see this as 23 * if the buffer adds a virtual mirror and the pointers point either to the 24 * normal or to the mirrored buffer. If the write_index has the same value 25 * with the read_index, but in a different mirror, the buffer is full. 26 * While if the write_index and the read_index are the same and within the 27 * same mirror, the buffer is empty. The ASCII art of the ringbuffer is: 28 * 29 * mirror = 0 mirror = 1 30 * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+ 31 * | 0 | 1 | 2 | 3 | 4 | 5 | 6 ||| 0 | 1 | 2 | 3 | 4 | 5 | 6 | Full 32 * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+ 33 * read_idx-^ write_idx-^ 34 * 35 * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+ 36 * | 0 | 1 | 2 | 3 | 4 | 5 | 6 ||| 0 | 1 | 2 | 3 | 4 | 5 | 6 | Empty 37 * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+ 38 * read_idx-^ ^-write_idx 39 * 40 * The tradeoff is we could only use 32KiB of buffer for 16 bit of index. 41 * But it should be enough for most of the cases. 42 * 43 * Ref: http://en.wikipedia.org/wiki/Circular_buffer#Mirroring */ 44 rt_uint16_t read_mirror : 1; 45 rt_uint16_t read_index : 15; 46 rt_uint16_t write_mirror : 1; 47 rt_uint16_t write_index : 15; 48 /* as we use msb of index as mirror bit, the size should be signed and 49 * could only be positive. */ 50 rt_int16_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_int16_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_uint16_t length); 70 rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb, const rt_uint8_t *ptr, rt_uint16_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_uint16_t length); 74 rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch); 75 rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb); 76 77 #ifdef RT_USING_HEAP 78 struct rt_ringbuffer* rt_ringbuffer_create(rt_uint16_t length); 79 void rt_ringbuffer_destroy(struct rt_ringbuffer *rb); 80 #endif 81 82 rt_inline rt_uint16_t rt_ringbuffer_get_size(struct rt_ringbuffer *rb) 83 { 84 RT_ASSERT(rb != RT_NULL); 85 return rb->buffer_size; 86 } 87 88 /** return the size of empty space in rb */ 89 #define rt_ringbuffer_space_len(rb) ((rb)->buffer_size - rt_ringbuffer_data_len(rb)) 90 91 92 #ifdef __cplusplus 93 } 94 #endif 95 96 #endif 97