33Ring Buffers
44############
55
6- A :dfn: `ring buffer ` is a circular buffer of 32-bit words, whose contents
7- are stored in first-in-first-out order. Data items can be enqueued and dequeued
8- from a ring buffer in chunks of up to 1020 bytes. Each data item also has
9- two associated metadata values: a type identifier and a 16-bit integer value,
10- both of which are application-specific.
6+ A :dfn: `ring buffer ` is a circular buffer, whose contents are stored in
7+ first-in-first-out order. Two content data modes are supported:
8+
9+ * **Data item mode **: Multiple 32-bit word data items with metadata
10+ can be enqueued and dequeued from the ring buffer in
11+ chunks of up to 1020 bytes. Each data item also has two
12+ associated metadata values: a type identifier and a 16-bit
13+ integer value, both of which are application-specific.
14+ * **Byte mode **: raw bytes can be enqueued and dequeued.
1115
1216.. contents ::
1317 :local:
@@ -21,27 +25,67 @@ by its memory address.
2125
2226A ring buffer has the following key properties:
2327
24- * A **data buffer ** of 32-bit words. The data buffer contains the data items
25- that have been added to the ring buffer but not yet removed.
28+ * A **data buffer ** of 32-bit words or bytes. The data buffer contains the data
29+ items or raw bytes that have been added to the ring buffer but not yet
30+ removed.
2631
27- * A **data buffer size **, measured in 32-bit words. This governs the maximum
28- amount of data (including metadata values) the ring buffer can hold.
32+ * A **data buffer size **, measured in 32-bit words or bytes . This governs the
33+ maximum amount of data (including metadata values) the ring buffer can hold.
2934
3035A ring buffer must be initialized before it can be used. This sets its
3136data buffer to empty.
3237
38+ Data item mode
39+ ==============
40+
41+ A **data item mode ** ring buffer instance is declared using
42+ :cpp:func: `RING_BUF_ITEM_DECLARE_POW2() ` or
43+ :cpp:func: `RING_BUF_ITEM_DECLARE_SIZE() ` and accessed using
44+ :cpp:func: `ring_buf_item_put() ` and :cpp:func: `ring_buf_item_get() `.
45+
3346A ring buffer **data item ** is an array of 32-bit words from 0 to 1020 bytes
34- in length. When a data item is **enqueued ** its contents are copied
35- to the data buffer, along with its associated metadata values (which occupy
36- one additional 32-bit word).
37- If the ring buffer has insufficient space to hold the new data item
38- the enqueue operation fails.
39-
40- A data items is **dequeued ** from a ring buffer by removing the oldest
41- enqueued item. The contents of the dequeued data item, as well as its
42- two metadata values, are copied to areas supplied by the retriever.
43- If the ring buffer is empty, or if the data array supplied by the retriever
44- is not large enough to hold the data item's data, the dequeue operation fails.
47+ in length. When a data item is **enqueued ** (:cpp:func: `ring_buf_item_put() `)
48+ its contents are copied to the data buffer, along with its associated metadata
49+ values (which occupy one additional 32-bit word). If the ring buffer has
50+ insufficient space to hold the new data item the enqueue operation fails.
51+
52+ A data items is **dequeued ** (:cpp:func: `ring_buf_item_get() `) from a ring
53+ buffer by removing the oldest enqueued item. The contents of the dequeued data
54+ item, as well as its two metadata values, are copied to areas supplied by the
55+ retriever. If the ring buffer is empty, or if the data array supplied by the
56+ retriever is not large enough to hold the data item's data, the dequeue
57+ operation fails.
58+
59+ Byte mode
60+ =========
61+
62+ A **byte mode ** ring buffer instance is declared using
63+ :cpp:func: `RING_BUF_DECLARE_SIZE() ` and accessed using:
64+ :cpp:func: `ring_buf_put_claim() `, :cpp:func: `ring_buf_put_finish() `,
65+ :cpp:func: `ring_buf_get_claim() `, :cpp:func: `ring_buf_get_finish() `,
66+ :cpp:func: `ring_buf_put() ` and :cpp:func: `ring_buf_get() `.
67+
68+ Data can be copied into the ring buffer (see
69+ :cpp:func: `ring_buf_put() `) or ring buffer memory can be used
70+ directly by the user. In the latter case, the operation is split into three stages:
71+
72+ 1. allocating the buffer (:cpp:func: `ring_buf_put_claim() `) when
73+ user requests the destination location where data can be written.
74+ #. writing the data by the user (e.g. buffer written by DMA).
75+ #. indicating the amount of data written to the provided buffer
76+ (:cpp:func: `ring_buf_put_finish() `). The amount
77+ can be less than or equal to the allocated amount.
78+
79+ Data can be retrieved from a ring buffer through copying
80+ (see :cpp:func: `ring_buf_get() `) or accessed directly by address. In the latter
81+ case, the operation is split
82+ into three stages:
83+
84+ 1. retrieving source location with valid data written to a ring buffer
85+ (see :cpp:func: `ring_buf_get_claim() `).
86+ #. processing data
87+ #. freeing processed data (see :cpp:func: `ring_buf_get_finish() `).
88+ The amount freed can be less than or equal or to the retrieved amount.
4589
4690Concurrency
4791===========
@@ -58,12 +102,13 @@ shouldn't be needed.
58102Internal Operation
59103==================
60104
61- The ring buffer always maintains an empty 32-bit word in its data buffer
62- to allow it to distinguish between empty and full states.
105+ The ring buffer always maintains an empty 32-bit word (byte in bytes mode) in
106+ its data buffer to allow it to distinguish between empty and full states.
63107
64108If the size of the data buffer is a power of two, the ring buffer
65109uses efficient masking operations instead of expensive modulo operations
66- when enqueuing and dequeuing data items.
110+ when enqueuing and dequeuing data items. This option is applicable only for
111+ data item mode.
67112
68113Implementation
69114**************
@@ -74,8 +119,8 @@ Defining a Ring Buffer
74119A ring buffer is defined using a variable of type :c:type: `struct ring_buf `.
75120It must then be initialized by calling :cpp:func: `ring_buf_init() `.
76121
77- The following code defines and initializes an empty ring buffer
78- (which is part of a larger data structure). The ring buffer's data buffer
122+ The following code defines and initializes an empty ** data item mode ** ring
123+ buffer (which is part of a larger data structure). The ring buffer's data buffer
79124is capable of holding 64 words of data and metadata information.
80125
81126.. code-block :: c
@@ -106,14 +151,23 @@ which can be accessed using efficient masking operations.
106151 /* Buffer with 2^8 (or 256) words */
107152 RING_BUF_ITEM_DECLARE_POW2(my_ring_buf, 8);
108153
109- The following code defines a ring buffer with an arbitrary- sized data buffer,
110- which can be accessed using less efficient modulo operations.
154+ The following code defines an application-specific sized ** byte mode ** ring
155+ buffer enqueued and dequeued as raw bytes:
111156
112157.. code-block :: c
113158
114159 #define MY_RING_BUF_WORDS 93
115160 RING_BUF_ITEM_DECLARE_SIZE(my_ring_buf, MY_RING_BUF_WORDS);
116161
162+ The following code defines a ring buffer with an arbitrary-sized data buffer,
163+ which can be accessed using less efficient modulo operations. Ring buffer is
164+ intended to be used for raw bytes.
165+
166+ .. code-block :: c
167+
168+ #define MY_RING_BUF_BYTES 93
169+ RING_BUF_DECLARE_SIZE(my_ring_buf, MY_RING_BUF_BYTES);
170+
117171 Enqueuing Data
118172==============
119173
@@ -145,6 +199,43 @@ can be specified.
145199 ...
146200 }
147201
202+ Bytes are copied to a **byte mode ** ring buffer by calling
203+ :cpp:func: `ring_buf_put() `.
204+
205+ .. code-block :: c
206+
207+ u8_t my_data[MY_RING_BUF_BYTES];
208+ u32_t ret;
209+
210+ ret = ring_buf_put(&ring_buf, my_data, SIZE_OF(my_data));
211+ if (ret != SIZE_OF(my_data)) {
212+ /* not enough room, partial copy. */
213+ ...
214+ }
215+
216+ Data can be added to a **byte mode ** ring buffer by directly accessing the
217+ ring buffer's memory. For example:
218+
219+ .. code-block :: c
220+
221+ u32_t size;
222+ u32_t rx_size;
223+ u8_t *data;
224+ int err;
225+
226+ /* Allocate buffer within a ring buffer memory. */
227+ size = ring_buf_put_claim(&ring_buf, &data, MY_RING_BUF_BYTES);
228+
229+ /* Work directly on a ring buffer memory. */
230+ rx_size = uart_rx(data, size);
231+
232+ /* Indicate amount of valid data. rx_size can be equal or less than size. */
233+ err = ring_buf_put_finish(&ring_buf, rx_size);
234+ if (err != 0) {
235+ /* No space to put requested amount of data to ring buffer. */
236+ ...
237+ }
238+
148239 Retrieving Data
149240===============
150241
@@ -171,15 +262,63 @@ A data item is removed from a ring buffer by calling
171262 ...
172263 }
173264
265+ Data bytes are copied out from a **byte mode ** ring buffer by calling
266+ :cpp:func: `ring_buf_get() `. For example:
267+
268+ .. code-block :: c
269+
270+ u8_t my_data[MY_DATA_BYTES];
271+ size_t ret;
272+
273+ ret = ring_buf_get(&ring_buf, my_data, sizeof(my_data));
274+ if (ret != sizeof(my_size)) {
275+ /* Less bytes copied. */
276+ } else {
277+ /* Requested amount of bytes retrieved. */
278+ ...
279+ }
280+
281+ Data can be retrieved from a **byte mode ** ring buffer by direct
282+ operations on the ring buffer's memory. For example:
283+
284+ .. code-block :: c
285+
286+ u32_t size;
287+ u32_t proc_size;
288+ u8_t *data;
289+ int err;
290+
291+ /* Get buffer within a ring buffer memory. */
292+ size = ring_buf_get_claim(&ring_buf, &data, MY_RING_BUF_BYTES);
293+
294+ /* Work directly on a ring buffer memory. */
295+ proc_size = process(data, size);
296+
297+ /* Indicate amount of data that can be freed. proc_size can be equal or less
298+ * than size.
299+ */
300+ err = ring_buf_get_finish(&ring_buf, proc_size);
301+ if (err != 0) {
302+ /* proc_size exceeds amount of valid data in a ring buffer. */
303+ ...
304+ }
305+
174306 APIs
175307****
176308
177309The following ring buffer APIs are provided by :file: `include/ring_buffer.h `:
178310
179311* :cpp:func: `RING_BUF_ITEM_DECLARE_POW2() `
180312* :cpp:func: `RING_BUF_ITEM_DECLARE_SIZE() `
313+ * :cpp:func: `RING_BUF_DECLARE_SIZE() `
181314* :cpp:func: `ring_buf_init() `
182315* :cpp:func: `ring_buf_is_empty() `
183316* :cpp:func: `ring_buf_space_get() `
184317* :cpp:func: `ring_buf_item_put() `
185318* :cpp:func: `ring_buf_item_get() `
319+ * :cpp:func: `ring_buf_put() `
320+ * :cpp:func: `ring_buf_put_claim() `
321+ * :cpp:func: `ring_buf_put_finish() `
322+ * :cpp:func: `ring_buf_get() `
323+ * :cpp:func: `ring_buf_get_claim() `
324+ * :cpp:func: `ring_buf_get_finish() `
0 commit comments