Merge branch 'doc/esp_ringbuf_acquire_complete_v4.0' into 'release/v4.0'
esp_ringbuf: add documents for SendAcquire and SendComplete (backport v4.0) See merge request espressif/esp-idf!7104
This commit is contained in:
commit
e5d25fb51e
2 changed files with 175 additions and 38 deletions
63
docs/_static/diagrams/ring-buffer/ring_buffer_send_acquire_complete.diag
vendored
Normal file
63
docs/_static/diagrams/ring-buffer/ring_buffer_send_acquire_complete.diag
vendored
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
#Diagram demonstrating reading and returning an item in a No-Split/Allow-Split ring buffer
|
||||||
|
#Buffer of 128 bytes, with 4 items of 16, 20, 8 and 24 bytes. First 3 items are read and returned
|
||||||
|
|
||||||
|
packetdiag ring_buffer_send_acquire_complete {
|
||||||
|
node_width = 6
|
||||||
|
node_height = 24
|
||||||
|
default_fontsize = 12
|
||||||
|
colwidth = 128
|
||||||
|
|
||||||
|
#Initial
|
||||||
|
0-7: 8 [color = lightblue];
|
||||||
|
8-23: 16 Available [color = lightyellow];
|
||||||
|
24-127: Free
|
||||||
|
|
||||||
|
#Acquire item 1, 2, 3
|
||||||
|
128-135: 8 [color = lightblue];
|
||||||
|
136-151: 16 Available [color = lightyellow];
|
||||||
|
152-179: 20 Acquired [color = lightgrey];
|
||||||
|
180-195: 8 Acquired [color = lightgrey];
|
||||||
|
196-227: 24 Acquired [color = lightgrey];
|
||||||
|
228-255: 28 Free
|
||||||
|
|
||||||
|
#Complete item 2
|
||||||
|
256-263: 8 [color = lightblue];
|
||||||
|
264-279: 16 Available [color = lightyellow];
|
||||||
|
280-307: 20 Acquired [color = lightgrey];
|
||||||
|
308-315: 8 [color = pink];
|
||||||
|
316-323: 8 Completed [color = pink];
|
||||||
|
324-355: 24 Acquired [color = lightgrey];
|
||||||
|
356-383: 28 Free
|
||||||
|
|
||||||
|
#Complete item 3
|
||||||
|
384-391: 8 [color = lightblue];
|
||||||
|
392-407: 16 Available [color = lightyellow];
|
||||||
|
408-435: 20 Acquired [color = lightgrey];
|
||||||
|
436-443: 8 [color = pink];
|
||||||
|
444-451: 8 Completed [color = pink];
|
||||||
|
452-459: 8 [color = pink];
|
||||||
|
460-483: 24 Completed [color = pink];
|
||||||
|
484-511: 28 Free
|
||||||
|
|
||||||
|
#Complete item 1
|
||||||
|
512-519: 8 [color = lightblue];
|
||||||
|
520-535: 16 Available [color = lightyellow];
|
||||||
|
536-543: 8 [color = pink];
|
||||||
|
544-563: 20 Completed [color = pink];
|
||||||
|
564-571: 8 [color = pink];
|
||||||
|
572-579: 8 Completed [color = pink];
|
||||||
|
580-587: 8 [color = pink];
|
||||||
|
588-611: 24 Completed [color = pink];
|
||||||
|
612-639: 28 Free
|
||||||
|
|
||||||
|
#Return item 3
|
||||||
|
640-647: 8 [color = lightblue];
|
||||||
|
648-663: 16 Available [color = lightyellow];
|
||||||
|
664-671: 8 [color = lightblue];
|
||||||
|
672-691: 20 Available [color = lightyellow];
|
||||||
|
692-699: 8 [color = lightblue];
|
||||||
|
700-707: 8 Available [color = lightyellow];
|
||||||
|
708-715: 8 [color = lightblue];
|
||||||
|
716-739: 24 Available [color = lightyellow];
|
||||||
|
740-767: 28 Free
|
||||||
|
}
|
|
@ -23,14 +23,17 @@ Ring Buffers
|
||||||
The ESP-IDF FreeRTOS ring buffer is a strictly FIFO buffer that supports arbitrarily sized items.
|
The ESP-IDF FreeRTOS ring buffer is a strictly FIFO buffer that supports arbitrarily sized items.
|
||||||
Ring buffers are a more memory efficient alternative to FreeRTOS queues in situations where the
|
Ring buffers are a more memory efficient alternative to FreeRTOS queues in situations where the
|
||||||
size of items is variable. The capacity of a ring buffer is not measured by the number of items
|
size of items is variable. The capacity of a ring buffer is not measured by the number of items
|
||||||
it can store, but rather by the amount of memory used for storing items. Items are sent to
|
it can store, but rather by the amount of memory used for storing items. You may apply for a
|
||||||
ring buffers by copy, however for efficiency reasons **items are retrieved by reference**. As a
|
piece of memory on the ring buffer to send an item, or just use the API to copy your data and send
|
||||||
result, all retrieved items **must also be returned** in order for them to be removed from
|
(according to the send API you call). For efficiency reasons,
|
||||||
the ring buffer completely. The ring buffers are split into the three following types:
|
**items are always retrieved from the ring buffer by reference**. As a result, all retrieved
|
||||||
|
items *must also be returned* in order for them to be removed from the ring buffer completely.
|
||||||
|
The ring buffers are split into the three following types:
|
||||||
|
|
||||||
**No-Split** buffers will guarantee that an item is stored in contiguous memory and will not
|
**No-Split** buffers will guarantee that an item is stored in contiguous memory and will not
|
||||||
attempt to split an item under any circumstances. Use no-split buffers when items must occupy
|
attempt to split an item under any circumstances. Use no-split buffers when items must occupy
|
||||||
contiguous memory.
|
contiguous memory. *Only this buffer type allows you getting the data item address and writting
|
||||||
|
to the item by yourself.*
|
||||||
|
|
||||||
**Allow-Split** buffers will allow an item to be split when wrapping around if doing so will allow
|
**Allow-Split** buffers will allow an item to be split when wrapping around if doing so will allow
|
||||||
the item to be stored. Allow-split buffers are more memory efficient than no-split buffers but
|
the item to be stored. Allow-split buffers are more memory efficient than no-split buffers but
|
||||||
|
@ -42,7 +45,8 @@ do not need to be maintained (e.g. a byte stream).
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
No-split/allow-split buffers will always store items at 32-bit aligned addresses. Therefore when
|
No-split/allow-split buffers will always store items at 32-bit aligned addresses. Therefore when
|
||||||
retrieving an item, the item pointer is guaranteed to be 32-bit aligned.
|
retrieving an item, the item pointer is guaranteed to be 32-bit aligned. This is useful
|
||||||
|
especially when you need to send some data to the DMA.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
Each item stored in no-split/allow-split buffers will **require an additional 8 bytes for a header**.
|
Each item stored in no-split/allow-split buffers will **require an additional 8 bytes for a header**.
|
||||||
|
@ -76,6 +80,46 @@ and :cpp:func:`xRingbufferSend` to create a ring buffer then send an item to it.
|
||||||
printf("Failed to send item\n");
|
printf("Failed to send item\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
The following example demonstrates the usage of :cpp:func:`xRingbufferSendAcquire` and
|
||||||
|
:cpp:func:`xRingbufferSendComplete` instead of :cpp:func:`xRingbufferSend` to apply for the
|
||||||
|
memory on the ring buffer (of type `RINGBUF_TYPE_NOSPLIT`) and then send an item to it. This way
|
||||||
|
adds one more step, but allows getting the address of the memory to write to, and writing to the
|
||||||
|
memory yourself.
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
#include "freertos/ringbuf.h"
|
||||||
|
#include "soc/lldesc.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
lldesc_t dma_desc;
|
||||||
|
uint8_t buf[1];
|
||||||
|
} dma_item_t;
|
||||||
|
|
||||||
|
#define DMA_ITEM_SIZE(N) (sizeof(lldesc_t)+(((N)+3)&(~3)))
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
//Retrieve space for DMA descriptor and corresponding data buffer
|
||||||
|
//This has to be done with SendAcquire, or the address may be different when copy
|
||||||
|
dma_item_t item;
|
||||||
|
UBaseType_t res = xRingbufferSendAcquire(buf_handle,
|
||||||
|
&item, DMA_ITEM_SIZE(buffer_size), pdMS_TO_TICKS(1000));
|
||||||
|
if (res != pdTRUE) {
|
||||||
|
printf("Failed to acquire memory for item\n");
|
||||||
|
}
|
||||||
|
item->dma_desc = (lldesc_t) {
|
||||||
|
.size = buffer_size,
|
||||||
|
.length = buffer_size,
|
||||||
|
.eof = 0,
|
||||||
|
.owner = 1,
|
||||||
|
.buf = &item->buf,
|
||||||
|
};
|
||||||
|
//Actually send to the ring buffer for consumer to use
|
||||||
|
res = xRingbufferSendComplete(buf_handle, &item);
|
||||||
|
if (res != pdTRUE) {
|
||||||
|
printf("Failed to send item\n");
|
||||||
|
}
|
||||||
|
|
||||||
The following example demonstrates retrieving and returning an item from a **no-split ring buffer**
|
The following example demonstrates retrieving and returning an item from a **no-split ring buffer**
|
||||||
using :cpp:func:`xRingbufferReceive` and :cpp:func:`vRingbufferReturnItem`
|
using :cpp:func:`xRingbufferReceive` and :cpp:func:`vRingbufferReturnItem`
|
||||||
|
@ -194,6 +238,36 @@ Byte buffers treat data as a sequence of bytes and does not incur any overhead
|
||||||
Referring to the diagram above, the 18, 3, and 27 byte items are sequentially written to the
|
Referring to the diagram above, the 18, 3, and 27 byte items are sequentially written to the
|
||||||
byte buffer and **merged into a single item of 48 bytes**.
|
byte buffer and **merged into a single item of 48 bytes**.
|
||||||
|
|
||||||
|
Using SendAcquire and SendComplete
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Items in no-split buffers are acquired (by SendAcquire) in strict FIFO order and must be sent to
|
||||||
|
the buffer by SendComplete for the data to be accessible by the consumer. Multiple items can be
|
||||||
|
sent or acquired without calling SendComplete, and the items do not necessarily need to be
|
||||||
|
completed in the order they were acquired. However the receiving of data items must occur in FIFO
|
||||||
|
order, therefore not calling SendComplete the earliest acquired item will prevent the subsequent
|
||||||
|
items from being received.
|
||||||
|
|
||||||
|
The following diagrams illustrate what will happen when SendAcquire/SendComplete don't happen in
|
||||||
|
the same order. At the beginning, there is already an data item of 16 bytes sent to the ring
|
||||||
|
buffer. Then SendAcquire is called to acquire space of 20, 8, 24 bytes on the ring buffer.
|
||||||
|
|
||||||
|
.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_send_acquire_complete.diag
|
||||||
|
:caption: SendAcquire/SendComplete items in no-split ring buffers
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
After that, we fill (use) the buffers, and send them to the ring buffer by SendComplete in the
|
||||||
|
order of 8, 24, 20. When 8 bytes and 24 bytes data are sent, the consumer still can only get the
|
||||||
|
16 bytes data item. Due to the usage if 20 bytes item is not complete, it's not available, nor
|
||||||
|
the following data items.
|
||||||
|
|
||||||
|
When the 20 bytes item is finally completed, all the 3 data items can be received now, in the
|
||||||
|
order of 20, 8, 24 bytes, right after the 16 bytes item existing in the buffer at the beginning.
|
||||||
|
|
||||||
|
Allow-split/byte buffers do not allow using SendAcquire/SendComplete since acquired buffers are
|
||||||
|
required to be complete (not wrapped).
|
||||||
|
|
||||||
|
|
||||||
Wrap around
|
Wrap around
|
||||||
^^^^^^^^^^^
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue