mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-11 14:26:05 +00:00
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>
337 lines
15 KiB
ReStructuredText
337 lines
15 KiB
ReStructuredText
.. _nanokernelObjects:
|
||
|
||
Nanokernel Objects
|
||
##################
|
||
|
||
Section Scope
|
||
*************
|
||
|
||
This section provides an overview of the most important nanokernel
|
||
objects. The information contained here is an aid to better understand
|
||
how Tiny Mountain operates at the nanokernel level.
|
||
|
||
Document Format
|
||
***************
|
||
|
||
|
||
Each object is broken off to its own section, containing a definition, a
|
||
functional description, the object initialization syntax, and a table
|
||
of Application Program Interfaces (APIs) with the context which may
|
||
call them. Please refer to the API documentation for further details
|
||
regarding each object’s functionality.
|
||
|
||
Nanokernel FIFO
|
||
***************
|
||
|
||
Definition
|
||
==========
|
||
|
||
|
||
The FIFO object is defined in :file:`kernel/nanokernel/nano_fifo.c`.
|
||
This is a linked list of memory that allows the caller to store data of
|
||
any size. The data is stored in first-in-first-out order.
|
||
|
||
Function
|
||
========
|
||
|
||
|
||
Multiple processes can wait on the same FIFO object. Data is passed to
|
||
the first fiber that waited on the FIFO, and then to the background
|
||
task if no fibers are waiting. Through this mechanism the FIFO object
|
||
can synchronize or communicate between more than two contexts through
|
||
its API. Any ISR, fiber, or task can attempt to get data from a FIFO
|
||
without waiting on the data to be stored.
|
||
|
||
.. note::
|
||
|
||
The FIFO object reserves the first WORD in each stored memory
|
||
block as a link pointer to the next item. The size of the WORD
|
||
depends on the platform and can be 16 bit, 32 bit, etc.
|
||
|
||
Application Program Interfaces
|
||
==============================
|
||
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
| **Context** | **Interfaces** |
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
| **Initialization** | :c:func:`nano_fifo_init()` |
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
| **Interrupt Service Routines** | :c:func:`nano_isr_fifo_get()`, :c:func:`nano_isr_fifo_put()` |
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
| **Fibers** | :c:func:`nano_fiber_fifo_get()`, :c:func:`nano_fiber_fifo_get_wait()`, :c:func:`nano_fiber_fifo_put()` |
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
| **Tasks** | :c:func:`nano_task_fifo_get()`, :c:func:`nano_task_fifo_get_wait()`, :c:func:`nano_task_fifo_put()` |
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
|
||
Nanokernel LIFO Object
|
||
**********************
|
||
|
||
Definition
|
||
==========
|
||
|
||
<<<<<<< HEAD
|
||
The LIFO is defined in :file:`kernel/nanokernel/core/nano_lifo.c`. It
|
||
=====================================================================
|
||
The LIFO is defined in :file:`kernel/nanokernel/nano_lifo.c`. It
|
||
>>>>>>> 4fb7905fc834d5993a5613eee2c0f9bfc8d2943f
|
||
consists of a linked list of memory blocks that uses the first word in
|
||
each block as a next pointer. The data is stored in last-in-first-out
|
||
order.
|
||
|
||
Function
|
||
========
|
||
|
||
When a message is added to the LIFO, the data is stored at the head of
|
||
the list. Messages taken off the LIFO object are taken from the head.
|
||
|
||
The LIFO object requires the first 32-bit word to be empty in order to
|
||
maintain the linked list.
|
||
|
||
The LIFO object does not store information about the size of the
|
||
messages.
|
||
|
||
The LIFO object remembers one waiting context. When a second context
|
||
starts waiting for data from the same LIFO object, the first context
|
||
remains waiting and never reaches the runnable state.
|
||
|
||
Application Program Interfaces
|
||
==============================
|
||
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
| **Context** | **Interfaces** |
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
| **Initialization** | :c:func:`nano_lifo_init()` |
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
| **Interrupt Service Routines** | :c:func:`nano_isr_lifo_get()`, :c:func:`nano_isr_lifo_put()` |
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
| **Fibers** | :c:func:`nano_fiber_lifo_get()`, :c:func:`nano_fiber_lifo_get_wait()`, :c:func:`nano_fiber_lifo_put()` |
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
| **Tasks** | :c:func:`nano_task_lifo_get()`, :c:func:`nano_task_lifo_get_wait()`, :c:func:`nano_task_lifo_put()` |
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
|
||
Nanokernel Semaphore
|
||
********************
|
||
|
||
|
||
Definition
|
||
==========
|
||
|
||
The nanokernel semaphore is defined in
|
||
:file:`kernel/nanokernel/nano_sema.c` and implements a counting
|
||
semaphore that sends signals from one fiber to another.
|
||
|
||
Function
|
||
========
|
||
|
||
Nanokernel semaphore objects can be used from an ISR, a fiber, or the
|
||
background task. Interrupt handlers can use the nanokernel’s semaphore
|
||
object to reschedule a fiber waiting for the interrupt.
|
||
|
||
Only one context can wait on a semaphore at a time. The semaphore starts
|
||
with a count of 0 and remains that way if no context is pending on it.
|
||
Each 'give' operation increments the count by 1. Following multiple
|
||
'give' operations, the same number of 'take' operations can be
|
||
performed without the calling context having to wait on the semaphore.
|
||
Thus after n 'give' operations a semaphore can 'take' n times without
|
||
pending. If a second context waits for the same semaphore object, the
|
||
first context is lost and never wakes up.
|
||
|
||
Application Program Interfaces
|
||
==============================
|
||
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
| Context | Interfaces |
|
||
+================================+========================================================================================================+
|
||
| **Initialization** | :c:func:`nano_sem_init()` |
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
| **Interrupt Service Routines** | :c:func:`nano_isr_sem_give()`, :c:func:`nano_isr_sem_take()` |
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
| **Fibers** | :c:func:`nano_fiber_sem_give()`, :c:func:`nano_fiber_sem_take()`, :c:func:`nano_fiber_sem_take_wait()` |
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
| **Tasks** | :c:func:`nano_task_sem_give()`, :c:func:`nano_task_sem_take()`, :c:func:`nano_task_sem_take_wait()` |
|
||
+--------------------------------+--------------------------------------------------------------------------------------------------------+
|
||
|
||
Timer Objects
|
||
*************
|
||
|
||
Definition
|
||
==========
|
||
|
||
The timer objects is defined in :file:`kernel/nanokernel/nano_timer.c`
|
||
and implements digital counters that either increment or decrement at a
|
||
fixed frequency. Timers can be called from a task or fiber context.
|
||
|
||
Function
|
||
========
|
||
|
||
Only a fiber or task context can call timers. Timers can only be used in
|
||
a nanokernel if it is not part of a microkernel. Timers are optional in
|
||
nanokernel-only systems. The nanokernel timers are simple. The
|
||
:c:func:`nano_node_tick_delta()` routine is not reentrant and should
|
||
only be called from a single context, unless it is certain other
|
||
contexts are not using the elapsed timer.
|
||
|
||
|
||
Application Program Interfaces
|
||
==============================
|
||
|
||
+--------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------+
|
||
| **Context** | **Interface** |
|
||
+--------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------+
|
||
| **Initialization** | :c:func:`nano_timer_init()` |
|
||
+--------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------+
|
||
| **Interrupt Service Routines** | |
|
||
+--------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------+
|
||
| **Fibers** | :c:func:`nano_fiber_timer_test()`, :c:func:`nano_fiber_timer_wait()`, :c:func:`nano_fiber_timer_start()`, :c:func:`nano_fiber_timer_stop()` |
|
||
+--------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------+
|
||
| **Tasks** | :c:func:`nano_task_timer_test()`, :c:func:`nano_task_timer_wait()`, :c:func:`nano_task_timer_start()`, :c:func:`nano_task_timer_stop()` |
|
||
+--------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------+
|
||
|
||
Semaphore, Timer, and Fiber Example
|
||
***********************************
|
||
|
||
|
||
The following example is pulled from the file:
|
||
:file:`samples/microkernel/apps/hello_world/src/hello.c`.
|
||
|
||
Example Code
|
||
============
|
||
|
||
.. code-block:: c
|
||
|
||
#include <nanokernel.h>
|
||
|
||
#include <nanokernel/cpu.h>
|
||
|
||
/* specify delay between greetings (in ms); compute equivalent in ticks */
|
||
|
||
#define SLEEPTIME
|
||
|
||
#define SLEEPTICKS (SLEEPTIME * CONFIG_TICKFREQ / 1000)
|
||
|
||
#define STACKSIZE 2000
|
||
|
||
char fiberStack[STACKSIZE];
|
||
|
||
struct nano_sem nanoSemTask;
|
||
|
||
struct nano_sem nanoSemFiber;
|
||
|
||
void fiberEntry (void)
|
||
|
||
{
|
||
struct nano_timer timer;
|
||
uint32_t data[2] = {0, 0};
|
||
|
||
nano_sem_init (&nanoSemFiber);
|
||
nano_timer_init (&timer, data);
|
||
|
||
while (1)
|
||
{
|
||
/* wait for task to let us have a turn */
|
||
nano_fiber_sem_take_wait (&nanoSemFiber);
|
||
|
||
/* say "hello" */
|
||
PRINT ("%s: Hello World!\n", __FUNCTION__);
|
||
|
||
/* wait a while, then let task have a turn */
|
||
nano_fiber_timer_start (&timer, SLEEPTICKS);
|
||
nano_fiber_timer_wait (&timer);
|
||
nano_fiber_sem_give (&nanoSemTask);
|
||
}
|
||
|
||
}
|
||
|
||
void main (void)
|
||
|
||
{
|
||
struct nano_timer timer;
|
||
uint32_t data[2] = {0, 0};
|
||
|
||
task_fiber_start (&fiberStack[0], STACKSIZE,
|
||
(nano_fiber_entry_t) fiberEntry, 0, 0, 7, 0);
|
||
|
||
nano_sem_init (&nanoSemTask);
|
||
nano_timer_init (&timer, data);
|
||
|
||
while (1)
|
||
{
|
||
/* say "hello" */
|
||
PRINT ("%s: Hello World!\n", __FUNCTION__);
|
||
|
||
/* wait a while, then let fiber have a turn */
|
||
nano_task_timer_start (&timer, SLEEPTICKS);
|
||
nano_task_timer_wait (&timer);
|
||
nano_task_sem_give (&nanoSemFiber);
|
||
|
||
/* now wait for fiber to let us have a turn */
|
||
nano_task_sem_take_wait (&nanoSemTask);
|
||
}
|
||
|
||
}
|
||
|
||
Step-by-Step Description
|
||
========================
|
||
|
||
A quick breakdown of the major objects in use
|
||
by this sample includes:
|
||
|
||
- One fiber, executing in the :c:func:`fiberEntry()` routine.
|
||
|
||
- The background task, executing in the :c:func:`main()` routine.
|
||
|
||
- Two semaphores (*nanoSemTask*, *nanoSemFiber*),
|
||
|
||
- Two timers:
|
||
|
||
+ One local to the fiber (timer)
|
||
|
||
+ One local to background task (timer)
|
||
|
||
First, the background task starts executing main(). The background task
|
||
calls task_fiber_start initializing and starting the fiber. Since a
|
||
fiber is available to be run, the background task is pre-empted and the
|
||
fiber begins running.
|
||
|
||
Execution jumps to fiberEntry. nanoSemFiber and the fiber-local timer
|
||
before dropping into the while loop, where it takes and waits on
|
||
nanoSemFiber. task_fiber_start.
|
||
|
||
The background task initializes nanoSemTask and the task-local timer.
|
||
|
||
The following steps repeat endlessly:
|
||
|
||
#. The background task execution begins at the top of the main while
|
||
loop and prints, “main: Hello World!”
|
||
|
||
#. The background task then starts a timer for SLEEPTICKS in the
|
||
future, and waits for that timer to expire.
|
||
|
||
|
||
#. Once the timer expires, it signals the fiber by giving the
|
||
nanoSemFiber semaphore, which in turn marks the fiber as runnable.
|
||
|
||
#. The fiber, now marked as runnable, pre-empts the background
|
||
process, allowing execution to jump to the fiber.
|
||
nano_fiber_sem_take_wait.
|
||
|
||
#. The fiber then prints, “fiberEntry: Hello World!” It starts a time
|
||
for SLEEPTICKS in the future and waits for that timer to expire. The
|
||
fiber is marked as not runnable, and execution jumps to the
|
||
background task.
|
||
|
||
#. The background task then takes and waits on the nanoSemTask
|
||
semaphore.
|
||
|
||
#. Once the timer expires, the fiber signals the background task by
|
||
giving the nanoSemFiber semaphore. The background task is marked as
|
||
runnable, but code execution continues in the fiber, since fibers
|
||
take priority over the background task. The fiber execution
|
||
continues to the top of the while loop, where it takes and waits on
|
||
nanoSemFiber. The fiber is marked as not runnable, and the
|
||
background task is scheduled.
|
||
|
||
#. The background task execution picks up after the call to
|
||
:c:func:`nano_task_sem_take_wait()`. It jumps to the top of the
|
||
while loop.
|