Adds the basic kernel objects' documentation describing the function of tasks, fiber and interrupt service routines. Adds the nanokernel objects' docuementation describing the function of the most important nanokernel objects. Adds the microkernel objects' documentation describing the function of the most important microkernel objects. Changes the index.rst file to include the Object Documentation. Change-Id: Ib35d973cc3575a7ecc32c4ab175e05cb298e3306 Signed-off-by: Rodrigo Caballero <rodrigo.caballero.abraham@intel.com> Signed-off-by: Anas Nashif <anas.nashif@intel.com>
456 lines
22 KiB
ReStructuredText
456 lines
22 KiB
ReStructuredText
.. _microkernelObjects:
|
||
|
||
Microkernel Objects
|
||
###################
|
||
|
||
Section Scope
|
||
*************
|
||
|
||
This section provides an overview of the most important microkernel
|
||
objects, and their operation.
|
||
|
||
Each object contains a definition, a function description, and a table
|
||
of Application Program Interfaces (API) including the context that may
|
||
call them. Please refer to the API documentation for further details
|
||
regarding each object’s functionality.
|
||
|
||
Microkernel FIFO Objects
|
||
************************
|
||
|
||
Definition
|
||
==========
|
||
|
||
Tiny Mountain FIFO object 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 VPF 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.
|
||
|
||
Initialization
|
||
==============
|
||
FIFO objects are created by defining them in a project file, for example
|
||
:file:`projName.vpf`. Specify the name of the FIFO object, the width in
|
||
bytes of a single entry, the number of entries, and, if desired, the
|
||
location defined in the architecture file to be used for the FIFO. Use
|
||
the following syntax in the VPF file to define a FIFO:
|
||
|
||
.. code-block:: console
|
||
|
||
FIFO %name %depthNumEntries %widthBytes [ bufSegLocation ]
|
||
|
||
An example of a FIFO entry for use in the VPF file:
|
||
|
||
.. code-block:: console
|
||
|
||
% FIFO NAME DEPTH WIDTH
|
||
|
||
% ============================
|
||
|
||
FIFO FIFOQ 2 4
|
||
|
||
|
||
Application Program Interfaces
|
||
==============================
|
||
The FIFO object APIs allow to putting data on the queue, receiving data
|
||
from the queue, finding the number of messages in the queue, and
|
||
emptying the queue.
|
||
|
||
+----------------------------------------+-------------------------------------------------+
|
||
| **Call** | **Description** |
|
||
+----------------------------------------+-------------------------------------------------+
|
||
| :c:func:`task_fifo_put()` | Put data on a FIFO, and fail |
|
||
| | if the FIFO is full. |
|
||
+----------------------------------------+-------------------------------------------------+
|
||
| :c:func:`task_fifo_put_wait()` | Put data on a FIFO, waiting |
|
||
| | for room in the FIFO. |
|
||
+----------------------------------------+-------------------------------------------------+
|
||
| :c:func:`task_fifo_put_wait_timeout()` | Put data on a FIFO, waiting |
|
||
| | for room in the FIFO, or a time out. |
|
||
+----------------------------------------+-------------------------------------------------+
|
||
| :c:func:`task_fifo_get()` | Get data off a FIFO, |
|
||
| | returning immediately if no data is available. |
|
||
+----------------------------------------+-------------------------------------------------+
|
||
| :c:func:`task_fifo_get_wait()` | Get data off a FIFO, |
|
||
| | waiting until data is available. |
|
||
+----------------------------------------+-------------------------------------------------+
|
||
| :c:func:`task_fifo_get_wait_timeout()` | Get data off a FIFO, |
|
||
| | waiting until data is available, or a time out. |
|
||
+----------------------------------------+-------------------------------------------------+
|
||
| :c:func:`task_fifo_purge()` | Empty the FIFO buffer, and |
|
||
| | signal any waiting receivers with an error. |
|
||
+----------------------------------------+-------------------------------------------------+
|
||
| :c:func:`task_fifo_size_get()` | Read the number of filled |
|
||
| | entries in a FIFO. |
|
||
+----------------------------------------+-------------------------------------------------+
|
||
|
||
Pipe Objects
|
||
************
|
||
|
||
Definition
|
||
==========
|
||
|
||
Microkernel pipes are defined in :file:`kernel/microkernel/k_pipe.c`.
|
||
Pipes allow any task to put any amount of data in or out. Pipes are
|
||
conceptually similar to FIFO objects in that they communicate
|
||
anonymously in a time-ordered, first-in, first-out manner, to exchange
|
||
data between tasks. Like FIFO objects, pipes can have a buffer, but
|
||
un-buffered operation is also possible. The main difference between
|
||
FIFO objects and pipes is that pipes handle variable-sized data.
|
||
|
||
Function
|
||
========
|
||
|
||
Pipes accept and send variable-sized data, and can be configured to work
|
||
with or without a buffer. Buffered pipes are time-ordered. The incoming
|
||
data is stored on a first-come, first-serve basis in the buffer; it is
|
||
not sorted by priority.
|
||
|
||
Pipes have no size limit. The size of the data transfer and the size of
|
||
the buffer have no limit except for the available memory. Pipes allow
|
||
senders or receivers to perform partial read and partial write
|
||
operations.
|
||
|
||
Pipes support both synchronous and asynchronous operations. If a pipe is
|
||
unbuffered, the sender can asynchronously put data into the pipe, or
|
||
wait for the data to be received, and the receiver can attempt to
|
||
remove data from the pipe, or wait on the data to be available.
|
||
Buffered pipes are synchronous by design.
|
||
|
||
Pipes are anonymous. The pipe transfer does not identify the sender or
|
||
receiver. Alternatively, mailboxes can be used to specify the sender
|
||
and receiver identities.
|
||
|
||
Initialization
|
||
==============
|
||
|
||
|
||
A target pipe has to be defined in the project file, for example
|
||
:file:`projName.vpf`. Specify the name of the pipe, the size of the
|
||
buffer in bytes, and the memory location for the pipe buffer as defined
|
||
in the linker script. The buffer’s memory is allocated on the processor
|
||
that manages the pipe. Use the following syntax in the VPF file to
|
||
define a pipe:
|
||
|
||
.. code-block:: console
|
||
|
||
PIPE %name %buffersize [%bufferSegment]
|
||
|
||
An example of a pipe entry for use in the VPF file:
|
||
|
||
.. code-block:: console
|
||
|
||
% PIPE NAME BUFFERSIZE [BUFFER_SEGMENT]
|
||
|
||
% ===================================================
|
||
|
||
PIPE PIPE_ID 256
|
||
|
||
|
||
Application Program Interfaces
|
||
==============================
|
||
|
||
The pipes APIs allow to sending and receiving data to and from a pipe.
|
||
|
||
+----------------------------------------+----------------------------------------+
|
||
| **Call** | **Description** |
|
||
+----------------------------------------+----------------------------------------+
|
||
| :c:func:`task_pipe_put()` | Put data on a pipe |
|
||
+----------------------------------------+----------------------------------------+
|
||
| :c:func:`task_pipe_put_wait()` | Put data on a pipe with a delay. |
|
||
+----------------------------------------+----------------------------------------+
|
||
| :c:func:`task_pipe_put_wait_timeout()` | Put data on a pipe with a timed delay. |
|
||
+----------------------------------------+----------------------------------------+
|
||
| :c:func:`task_pipe_get()` | Put data on a pipe. |
|
||
+----------------------------------------+----------------------------------------+
|
||
| :c:func:`task_pipe_get_wait()` | Put data on a pipe with a delay. |
|
||
+----------------------------------------+----------------------------------------+
|
||
| :c:func:`task_pipe_get_wait_timeout()` | Put data on a pipe with a timed delay. |
|
||
+----------------------------------------+----------------------------------------+
|
||
| :c:func:`task_pipe_put_async()` | Put data on a pipe asynchronously. |
|
||
+----------------------------------------+----------------------------------------+
|
||
|
||
Mailbox Objects
|
||
***************
|
||
|
||
Definition
|
||
==========
|
||
|
||
A Tiny Mountain mailbox object is defined in include
|
||
:file:`/microkernel/mail.h`. Mailboxes are a flexible way to pass data
|
||
and for tasks to exchange messages.
|
||
|
||
|
||
Function
|
||
========
|
||
|
||
Each transfer within a mailbox can vary in size. The size of a data
|
||
transfer is only limited by the available memory on the platform.
|
||
Transmitted data is not buffered in the mailbox itself. Instead, the
|
||
buffer is either allocated from a memory pool block, or in block of
|
||
memory defined by the user.
|
||
|
||
Mailboxes can work synchronously and asynchronously. Asynchronous
|
||
mailboxes require the sender to allocate a buffer from a memory pool
|
||
block, while synchronous mailboxes will copy the sender data to the
|
||
receiver buffer.
|
||
|
||
The transfer contains one word of information that identifies either the
|
||
sender, or the receiver, or both. The sender task specifies the task it
|
||
wants to send to. The receiver task specifies the task it wants to
|
||
receive from. Then the mailbox checks the identity of the sender and
|
||
receiver tasks before passing the data.
|
||
|
||
Initialization
|
||
==============
|
||
|
||
A mailbox has to be defined in the project file, for example
|
||
:file:`projName.vpf`, which will specify the object type, and the name
|
||
of the mailbox. Use the following syntax in the VPF file to define a
|
||
Mailbox:
|
||
|
||
.. code-block:: console
|
||
|
||
MAILBOX %name
|
||
|
||
An example of a mailbox entry for use in the VPF file:
|
||
|
||
.. code-block:: console
|
||
|
||
% MAILBOX NAME
|
||
|
||
% =================
|
||
|
||
MAILBOX MYMBOX
|
||
|
||
|
||
|
||
Application Program Interfaces
|
||
==============================
|
||
|
||
|
||
Mailbox APIs provide flexibility and control for transferring data
|
||
between tasks.
|
||
|
||
+--------------------------------------------+---------------------------------------------------------------------+
|
||
| **Call** | **Description** |
|
||
+--------------------------------------------+---------------------------------------------------------------------+
|
||
| :c:func:`task_mbox_put()` | Attempt to put data in a |
|
||
| | mailbox, and fail if the receiver isn’t waiting. |
|
||
+--------------------------------------------+---------------------------------------------------------------------+
|
||
| :c:func:`task_mbox_put_wait()` | Puts data in a mailbox, |
|
||
| | and waits for it to be received. |
|
||
+--------------------------------------------+---------------------------------------------------------------------+
|
||
| :c:func:`task_mbox_put_wait_timeout()` | Puts data in a mailbox, |
|
||
| | and waits for it to be received, with a timeout. |
|
||
+--------------------------------------------+---------------------------------------------------------------------+
|
||
| :c:func:`task_mbox_put_async()` | Puts data in a mailbox |
|
||
| | asynchronously. |
|
||
| | |
|
||
+--------------------------------------------+---------------------------------------------------------------------+
|
||
| :c:func:`task_mbox_get()` | Gets k_msg message |
|
||
| | header information from a mailbox and gets mailbox data, or returns |
|
||
| | immediately if the sender isn’t ready. |
|
||
+--------------------------------------------+---------------------------------------------------------------------+
|
||
| :c:func:`task_mbox_get_wait()` | Gets k_msg message |
|
||
| | header information from a mailbox and gets mailbox data, and waits |
|
||
| | until the sender is ready with data. |
|
||
+--------------------------------------------+---------------------------------------------------------------------+
|
||
| :c:func:`task_mbox_get_wait_timeout()` | Gets k_msg message |
|
||
| | header information from a mailbox and gets mailbox data, and waits |
|
||
| | until the sender is ready with a timeout. |
|
||
+--------------------------------------------+---------------------------------------------------------------------+
|
||
| :c:func:`task_mbox_data_get()` | Gets mailbox data and |
|
||
| | puts it in a buffer specified by a pointer. |
|
||
| | |
|
||
+--------------------------------------------+---------------------------------------------------------------------+
|
||
| :c:func:`task_mbox_data_get_async_block()` | Gets the mailbox data |
|
||
| | and puts it in a memory pool block. |
|
||
| | |
|
||
+--------------------------------------------+---------------------------------------------------------------------+
|
||
|
||
Semaphore Objects
|
||
*****************
|
||
|
||
Definition
|
||
==========
|
||
|
||
The microkernel semaphore is defined in
|
||
:file:`kernel/microkernel/k_sema.c` and are an implementation of
|
||
traditional counting semaphores. Semaphores are used to synchronize
|
||
application task activities.
|
||
|
||
Function
|
||
========
|
||
|
||
Semaphores are initialized by the system. At start the semaphore is
|
||
un-signaled and no task is waiting for it. Any task in the system can
|
||
signal a semaphore. Every signal increments the count value associated
|
||
with the semaphore. When several tasks wait for the same semaphore at
|
||
the same time, they are held in a prioritized list. If the semaphore is
|
||
signaled, the task with the highest priority is released. If more tasks
|
||
of that priority are waiting, the first one that requested the
|
||
semaphore wakes up. Other tasks can test the semaphore to see if it is
|
||
signaled. If not signaled, tasks can either wait, with or without a
|
||
timeout, until signaled or return immediately with a failed status.
|
||
|
||
Initialization
|
||
==============
|
||
|
||
A semaphore has to be defined in the project file, for example
|
||
:file:`projName.vpf`, which will specify the object type, and the name
|
||
of the semaphore. Use the following syntax in the VPF file to define a
|
||
semaphore::
|
||
|
||
.. code-block:: console
|
||
|
||
SEMA %name %node
|
||
|
||
An example of a semaphore entry for use in the VPF file:
|
||
|
||
.. code-block:: console
|
||
|
||
% SEMA NAME
|
||
|
||
% =================
|
||
|
||
SEMA SEM_TASKDONE
|
||
|
||
|
||
|
||
Application Program Interfaces
|
||
==============================
|
||
|
||
Semaphore APIs allow signaling a semaphore. They also provide means to
|
||
reset the signal count.
|
||
|
||
+----------------------------------------+---------------------------------------------------+
|
||
| **Call** | **Description** |
|
||
+----------------------------------------+---------------------------------------------------+
|
||
| :c:func:`isr_sem_give()` | Signal a semaphore from an ISR. |
|
||
+----------------------------------------+---------------------------------------------------+
|
||
| :c:func:`task_sem_give()` | Signal a semaphore from a task. |
|
||
+----------------------------------------+---------------------------------------------------+
|
||
| :c:func:`task_sem_take()` | Test a semaphore from a task. |
|
||
+----------------------------------------+---------------------------------------------------+
|
||
| :c:func:`task_sem_take_wait()` | Wait on a semaphore from a task. |
|
||
+----------------------------------------+---------------------------------------------------+
|
||
| :c:func:`task_sem_take_wait_timeout()` | Wait on a semaphore, with a timeout, from a task. |
|
||
+----------------------------------------+---------------------------------------------------+
|
||
| :c:func:`task_sem_group_reset()` | Sets a list of semaphores to zero. |
|
||
+----------------------------------------+---------------------------------------------------+
|
||
| :c:func:`task_sem_group_give()` | Signals a list of semaphores from a task. |
|
||
+----------------------------------------+---------------------------------------------------+
|
||
| :c:func:`task_sem_reset()` | Sets a semaphore to zero. |
|
||
+----------------------------------------+---------------------------------------------------+
|
||
|
||
Event Objects
|
||
*************
|
||
|
||
Definition
|
||
==========
|
||
|
||
Event objects are microkernel synchronization objects that tasks can
|
||
signal and test. Fibers and interrupt service routines may signal
|
||
events but they cannot test or wait on them. Use event objects for
|
||
situations in which multiple signals come in but only one test is
|
||
needed to reset the event. Events do not count signals like a semaphore
|
||
does due to their binary behavior. An event needs only one signal to be
|
||
available and only needs to be tested once to become clear and
|
||
unavailable.
|
||
|
||
Function
|
||
========
|
||
|
||
Events were designed for interrupt service routines and nanokernel
|
||
fibers that need to wake up a waiting task. The event signal can be
|
||
passed to a task to trigger an event test to RC_OK. Events are the
|
||
easiest and most efficient way to wake up a task to synchronize
|
||
operations between the two levels.
|
||
|
||
A feature of events are the event handlers. Event handlers are attached
|
||
to events. They perform simple processing in the nanokernel before a
|
||
context switch is made to a blocked task. This way, signals can be
|
||
interpreted before the system requires to reschedule a fiber or task.
|
||
|
||
Only one task may wait for an event. If a second task tests the same
|
||
event the call returns a fail. Use semaphores for multiple tasks to
|
||
wait on a signal from them.
|
||
|
||
Initialization
|
||
==============
|
||
|
||
|
||
An event has to be defined in the project file, :file:`projName.vpf`.
|
||
Specify the name of the event, the name of the processor node that
|
||
manages it, and its event-handler function. Use the following syntax:
|
||
|
||
.. code-block:: console
|
||
|
||
EVENT name handler
|
||
|
||
.. note::
|
||
|
||
In the project file, you can specify the name of the event and the
|
||
event handler, but not the event's number.
|
||
|
||
Define application events in the project’s VPF file. Define the driver’s
|
||
events in either the project’s VPF file or a BSP-specific VPF file.
|
||
|
||
Application Program Interfaces
|
||
==============================
|
||
|
||
Event APIs allow signaling or testing an event (blocking or
|
||
non-blocking), and setting the event handler.
|
||
|
||
If the event is in a signaled state, the test function returns
|
||
successfully and resets the event to the non-signaled state. If the
|
||
event is not signaled at the time of the call, the test either reports
|
||
failure immediately in case of a non-blocking call, or blocks the
|
||
calling task into a until the event signal becomes available.
|
||
|
||
+------------------------------------------+------------------------------------------------------------+
|
||
| **Call** | **Description** |
|
||
+------------------------------------------+------------------------------------------------------------+
|
||
| :c:func:`fiber_event_send()` | Signal an event from a fiber. |
|
||
+------------------------------------------+------------------------------------------------------------+
|
||
| :c:func:`task_event_set_handler()` | Installs or removes an event handler function from a task. |
|
||
+------------------------------------------+------------------------------------------------------------+
|
||
| :c:func:`task_event_send()` | Signal an event from a task. |
|
||
+------------------------------------------+------------------------------------------------------------+
|
||
| :c:func:`task_event_recv()` | Waits for an event signal. |
|
||
+------------------------------------------+------------------------------------------------------------+
|
||
| :c:func:`task_event_recv_wait()` | Waits for an event signal with a delay. |
|
||
+------------------------------------------+------------------------------------------------------------+
|
||
| :c:func:`task_event_recv_wait_timeout()` | Waits for an event signal with a delay and a timeout. |
|
||
+------------------------------------------+------------------------------------------------------------+
|
||
| :c:func:`isr_event_send()` | Signal an event from an ISR |
|
||
+------------------------------------------+------------------------------------------------------------+
|