Moves the Microkernel Object documentation to a new Microkernel Services section within the Kernel Primer. Labels, cross-references, figures, headings and filenames were updated to reflect the new structure. Change-Id: Ia2a91410a94caa8a97bb8211db5afc84b5dc0974 Signed-off-by: Rodrigo Caballero <rodrigo.caballero.abraham@intel.com>
188 lines
6.6 KiB
ReStructuredText
188 lines
6.6 KiB
ReStructuredText
.. _microkernel_fifos:
|
||
|
||
Microkernel FIFOs
|
||
#################
|
||
|
||
Definition
|
||
**********
|
||
|
||
The FIFO is defined in :file:`include/microkernel/fifo.h` as a simple
|
||
first-in, first-out queue that handle small amounts of fixed size data.
|
||
FIFO objects have a buffer that stores a number of data transmits, and
|
||
are the most efficient way to pass small amounts of data between tasks.
|
||
FIFO objects are suitable for asynchronously transferring small amounts
|
||
of data, such as parameters, between tasks.
|
||
|
||
Function
|
||
********
|
||
|
||
|
||
FIFO objects store data in a statically allocated buffer defined within
|
||
the project’s MDEF file. The depth of the FIFO object buffer is only
|
||
limited by the available memory on the platform. Individual FIFO data
|
||
objects can be at most 40 bytes in size, and are stored in an ordered
|
||
first-come, first-serve basis, not by priority.
|
||
|
||
FIFO objects are asynchronous. When using a FIFO object, the sender can
|
||
add data even if the receiver is not ready yet. This only applies if
|
||
there is sufficient space on the buffer to store the sender's data.
|
||
|
||
FIFO objects are anonymous. The kernel object does not store the sender
|
||
or receiver identity. If the sender identification is required, it is
|
||
up to the caller to store that information in the data placed into the
|
||
FIFO. The receiving task can then check it. Alternatively, mailboxes
|
||
can be used to specify the sender and receiver identities.
|
||
|
||
FIFO objects read and write actions are always fixed-size block-based.
|
||
The width of each FIFO object block is specified in the project file.
|
||
If a task calls :c:func:`task_fifo_get()` and the call succeeds, then
|
||
the fixed number of bytes is copied from the FIFO object into the
|
||
addresses of the destination pointer.
|
||
|
||
Usage
|
||
*****
|
||
|
||
Defining a FIFO in MDEF File
|
||
============================
|
||
|
||
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.
|
||
|
||
Add an entry for a FIFO in the project .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
|
||
|
||
|
||
Defining FIFO within the Code
|
||
=============================
|
||
|
||
In addition to defining FIFOs in MDEF file, it is also possible to
|
||
define FIFOs inside code. The macro ``DEFINE_FIFO(fifo_name)``
|
||
can be used for this purpose.
|
||
|
||
For example, the following code can be used to define a global FIFO
|
||
``PRIV_FIFO``.
|
||
|
||
.. code-block:: c
|
||
|
||
DEFINE_FIFO(PRIV_FIFO, depth, width);
|
||
|
||
The FIFO ``PRIV_FIFO`` can be used in the same style as those FIFOs
|
||
defined in MDEF file.
|
||
|
||
It is possible to utilize this FIFO in another source file, simply
|
||
add:
|
||
|
||
.. code-block:: c
|
||
|
||
extern const kfifo_t PRIV_FIFO;
|
||
|
||
to that file. The FIFO ``PRIV_FIFO`` can be then used there.
|
||
|
||
|
||
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. |
|
||
+----------------------------------------+-----------------------------------+
|