| .. _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 by name 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. | |
| +----------------------------------------+-----------------------------------+ |