mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-09-15 06:01:56 +00:00
Revises description to follow the pattern used for other microkernel object types. Expands the description to provide additional useful details about the operation and use of FIFOs. Change-Id: If4d84c301922158c2c7cae26cb1520294397876a Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
211 lines
7.3 KiB
ReStructuredText
211 lines
7.3 KiB
ReStructuredText
.. _microkernel_fifos:
|
|
|
|
FIFOs
|
|
#####
|
|
|
|
Concepts
|
|
********
|
|
|
|
The microkernel's FIFO object type is an implementation of a traditional
|
|
first in, first out queue.
|
|
|
|
A FIFO allows tasks to asynchronously send and receive fixed-size data items.
|
|
Each FIFO has an associated ring buffer for holding data items that have been
|
|
sent but not yet received.
|
|
|
|
Any number of FIFOs can be defined in a microkernel system. Each FIFO has a
|
|
name that uniquely identifies it. In addition, a FIFO defines the size of
|
|
the data items it handles and the maximum number of data items that can be
|
|
queued in its ring buffer, both of which must be greater than zero.
|
|
|
|
A task sends a data item by specifying a pointer to an area containing the data
|
|
to be sent; the size of the data area must equal the FIFO's data item size.
|
|
The data is given directly to a receiving task (if one is waiting) or copied
|
|
to the FIFO's ring buffer (if space is available). When a FIFO is full
|
|
the sending task may choose to wait for space to become available.
|
|
|
|
Any number of tasks may wait on a full FIFO simultaneously; when space for
|
|
a data item becomes available it is given to the highest priority task that
|
|
has waited the longest.
|
|
|
|
A task receives a data item by specifying a pointer to an area to receive
|
|
the data; the size of the receiving area must equal the FIFO's data item size.
|
|
The data is copied from the FIFO's ring buffer (if it contains data items)
|
|
or taken directly from a sending task (if the FIFO is empty). When a FIFO
|
|
is empty the task may choose to wait for a data item to become available.
|
|
|
|
Any number of tasks may wait on an empty FIFO simultaneously; when a data item
|
|
becomes available it is given to the highest priority task that has waited
|
|
the longest.
|
|
|
|
|
|
Purpose
|
|
*******
|
|
|
|
Use a FIFO to transfer small data items between tasks in an asynchronous and
|
|
anonymous manner.
|
|
|
|
.. note::
|
|
A FIFO can be used to transfer large data items, if desired. However,
|
|
it is often preferable to send pointers to large data items to avoid
|
|
copying the data. The microkernel's memory map and memory pool object
|
|
types can be helpful for data transfers of this sort.
|
|
|
|
A synchronous transfer can be achieved using the microkernel's mailbox
|
|
object type.
|
|
|
|
A non-anonymous transfer can be achieved by having the sending task
|
|
embed its name in the data it sends, where it can be retrieved by
|
|
the receiving task. However, there is no straightforward way for the
|
|
sending task to determine the name of the task that received its data.
|
|
The microkernel's mailbox object type *does* support non-anonymous data
|
|
transfer.
|
|
|
|
|
|
Usage
|
|
*****
|
|
|
|
Defining a FIFO
|
|
===============
|
|
|
|
The following parameters must be defined:
|
|
|
|
*name*
|
|
This specifies a unique name for the FIFO.
|
|
|
|
*depth*
|
|
This specifies the maximum number of data items
|
|
that can exist at any one time.
|
|
|
|
*width*
|
|
This specifies the size (in bytes) of each data item.
|
|
|
|
Public FIFO
|
|
-----------
|
|
|
|
Define the FIFO in the application's .MDEF file using the following syntax:
|
|
|
|
.. code-block:: console
|
|
|
|
FIFO name depth width
|
|
|
|
For example, the file :file:`projName.mdef` defines a FIFO
|
|
that holds up to 10 items that are each 12 bytes long as follows:
|
|
|
|
.. code-block:: console
|
|
|
|
% FIFO NAME DEPTH WIDTH
|
|
% =============================
|
|
FIFO SIGNAL_FIFO 10 12
|
|
|
|
A public FIFO can be referenced from any source file that includes
|
|
the file :file:`zephyr.h`.
|
|
|
|
|
|
Private FIFO
|
|
------------
|
|
|
|
Define the FIFO in a source file using the following syntax:
|
|
|
|
.. code-block:: c
|
|
|
|
DEFINE_FIFO(fifo_name, depth, width)
|
|
|
|
For example, the following code defines a private FIFO named ``PRIV_FIFO``.
|
|
|
|
.. code-block:: c
|
|
|
|
DEFINE_FIFO(PRIV_FIFO, 10, 12);
|
|
|
|
To utilize this FIFO from a different source file use the following syntax:
|
|
|
|
.. code-block:: c
|
|
|
|
extern const kfifo_t PRIV_FIFO;
|
|
|
|
|
|
Example: Writing to a FIFO
|
|
==========================
|
|
|
|
This code uses a FIFO to pass data items from a producing task to
|
|
one or more consuming tasks. If the FIFO fills up because the consumers
|
|
can't keep up, throw away all existing data so newer data can be saved.
|
|
|
|
.. code-block:: c
|
|
|
|
void producer_task(void)
|
|
{
|
|
struct data_item_t data;
|
|
|
|
while (1) {
|
|
/* create data item to send (e.g. measurement, timestamp, ...) */
|
|
data = ...
|
|
|
|
/* send data to consumers */
|
|
while (task_fifo_put(SIGNAL_FIFO, &data) != RC_OK) {
|
|
/* FIFO is full */
|
|
task_fifo_purge(SIGNAL_FIFO);
|
|
}
|
|
|
|
/* data item was successfully added to FIFO */
|
|
}
|
|
}
|
|
|
|
Example: Reading from a FIFO
|
|
============================
|
|
|
|
This code uses a FIFO to process data items from generated by
|
|
one or more producing tasks.
|
|
|
|
.. code-block:: c
|
|
|
|
void consumer_task(void)
|
|
{
|
|
struct data_item_t data;
|
|
|
|
while (1) {
|
|
/* get a data item */
|
|
task_fifo_get_wait(SIGNAL_FIFO, &data);
|
|
|
|
/* process data item */
|
|
...
|
|
}
|
|
}
|
|
|
|
|
|
APIs
|
|
****
|
|
|
|
The following APIs for a microkernel FIFO are provided by microkernel.h.
|
|
|
|
+----------------------------------------+-----------------------------------+
|
|
| Call | Description |
|
|
+========================================+===================================+
|
|
| :c:func:`task_fifo_put()` | Write item to a FIFO, or fail and |
|
|
| | continue if it is full. |
|
|
+----------------------------------------+-----------------------------------+
|
|
| :c:func:`task_fifo_put_wait()` | Write item to a FIFO, or wait |
|
|
| | for room to write if it is full. |
|
|
+----------------------------------------+-----------------------------------+
|
|
| :c:func:`task_fifo_put_wait_timeout()` | Write item to a FIFO, or wait for |
|
|
| | a specified time period if it |
|
|
| | is full. |
|
|
+----------------------------------------+-----------------------------------+
|
|
| :c:func:`task_fifo_get()` | Read item from a FIFO, or fail |
|
|
| | and continue if it is empty. |
|
|
+----------------------------------------+-----------------------------------+
|
|
| :c:func:`task_fifo_get_wait()` | Read item from a FIFO, or wait |
|
|
| | for an item if it is empty. |
|
|
+----------------------------------------+-----------------------------------+
|
|
| :c:func:`task_fifo_get_wait_timeout()` | Read item from a FIFO, or wait |
|
|
| | for an item for a specified time |
|
|
| | period if it is empty. |
|
|
+----------------------------------------+-----------------------------------+
|
|
| :c:func:`task_fifo_purge()` | Discard all items in a FIFO and |
|
|
| | unblock any tasks waiting to read |
|
|
| | or write an item. |
|
|
+----------------------------------------+-----------------------------------+
|
|
| :c:func:`task_fifo_size_get()` | Read the number of items |
|
|
| | currently in a FIFO. |
|
|
+----------------------------------------+-----------------------------------+
|