Skip to content

Commit 26031f7

Browse files
nordic-krchnashif
authored andcommitted
lib: ring_buffer: add raw byte access mode
Extended ring buffer to allow storing raw bytes in it. API has been extended keeping 'data item' mode untouched. Signed-off-by: Krzysztof Chruscinski <[email protected]>
1 parent ff5f00f commit 26031f7

File tree

5 files changed

+675
-66
lines changed

5 files changed

+675
-66
lines changed

doc/kernel/other/ring_buffers.rst

Lines changed: 166 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@
33
Ring 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

2226
A 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

3035
A ring buffer must be initialized before it can be used. This sets its
3136
data 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+
3346
A 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

4690
Concurrency
4791
===========
@@ -58,12 +102,13 @@ shouldn't be needed.
58102
Internal 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

64108
If the size of the data buffer is a power of two, the ring buffer
65109
uses 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

68113
Implementation
69114
**************
@@ -74,8 +119,8 @@ Defining a Ring Buffer
74119
A ring buffer is defined using a variable of type :c:type:`struct ring_buf`.
75120
It 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
79124
is 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

177309
The 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

Comments
 (0)