doc: remove obsolete v1 changes/porting docs
doc/kernel/overview/changes.rst contains information about changes from kernel release 1.5 ("Version 1 Kernel") to the combined "Version 2 Kernel" and doc/porting/application.rst talked about how to change applications using Version 1 interfaces to the Version 2 interface. This information remains in the online tagged versions of the documentation, but it's time to remove this from the current documentation set. (Also removing example porting code.) Fixes issue #1524 Signed-off-by: David B. Kinder <david.b.kinder@intel.com>
This commit is contained in:
parent
c1930ed346
commit
37340c7353
|
@ -1,161 +0,0 @@
|
|||
.. _changes_v2:
|
||||
|
||||
Changes from Version 1 Kernel
|
||||
#############################
|
||||
|
||||
The current Zephyr kernel incorporates numerous changes from
|
||||
kernels found in the 1.5 and earlier releases, and improves
|
||||
ease of use for developers.
|
||||
|
||||
Some of the benefits of these changes are:
|
||||
|
||||
* elimination of separate microkernel and nanokernel build types,
|
||||
* elimination of the MDEF in microkernel-based applications,
|
||||
* simplifying and streamlining the kernel API,
|
||||
* easing restrictions on the use of kernel objects,
|
||||
* reducing memory footprint by merging duplicated services, and
|
||||
* improving performance by reducing context switching.
|
||||
|
||||
The most significant changes are discussed below.
|
||||
|
||||
Application Design
|
||||
******************
|
||||
|
||||
The earlier microkernel and nanokernel portions of Zephyr have been merged into
|
||||
a single entity, which is simply referred to as "the kernel". Consequently,
|
||||
there is now only a single way to design and build Zephyr applications.
|
||||
|
||||
The task and fiber context types have been merged into a single type,
|
||||
known as a "thread". Setting a thread's priority to a negative priority
|
||||
makes it a "cooperative thread", which operates in a fiber-like manner;
|
||||
setting it to a non-negative priority makes it a "preemptive thread",
|
||||
which operates in a task-like manner.
|
||||
|
||||
Kernel objects can now be used by both task-like threads and fiber-like
|
||||
threads. (The previous kernel did not permit fibers to use microkernel
|
||||
objects, and could result in undesirable busy-waiting when nanokernel
|
||||
objects were used by tasks.)
|
||||
|
||||
Kernel objects now typically allow multiple threads to wait on a given
|
||||
object. (The previous kernel restricted waiting on certain types of
|
||||
kernel object to a single thread.)
|
||||
|
||||
Kernel object APIs now always execute in the context of the invoking thread.
|
||||
(The previous kernel required microkernel object APIs to context switch
|
||||
the thread to the microkernel server fiber, followed by another context
|
||||
switch back to the invoking thread.)
|
||||
|
||||
The MDEF has been eliminated. Consequently, all kernel objects are now defined
|
||||
directly in code.
|
||||
|
||||
.. _kernel_api_changes:
|
||||
|
||||
Kernel APIs
|
||||
***********
|
||||
|
||||
Most kernel APIs have been renamed or have had changes to their arguments
|
||||
(or both) to make them more intuitive, and to improve consistency.
|
||||
The **k_** and **K_** prefixes are now used by most kernel APIs.
|
||||
|
||||
A previous kernel operation that can be invoked from a task, a fiber,
|
||||
or an ISR using distinct APIs is now invoked from a thread or an ISR
|
||||
using a single common API.
|
||||
|
||||
Many kernel APIs now return 0 to indicate success and a non-zero error code
|
||||
to indicate the reason for failure. (The previous kernel supported only
|
||||
two error codes, rather than an unlimited number of them.)
|
||||
|
||||
Threads
|
||||
*******
|
||||
|
||||
A task-like thread can now make itself temporarily non-preemptible
|
||||
by locking the kernel's scheduler (rather than by locking interrupts).
|
||||
|
||||
It is now possible to pass up to 3 arguments to a thread's entry point.
|
||||
(The previous kernel allowed 2 arguments to be passed to a fiber
|
||||
and allowed no arguments to be passed to a task.)
|
||||
|
||||
It is now possible to delay the start of a statically-defined threads.
|
||||
(The previous kernel only permitted delaying of fibers spawned at run time.)
|
||||
|
||||
A task can no longer specify an "task abort handler" function
|
||||
that is invoked automatically when the task terminates or aborts.
|
||||
|
||||
An application can no longer use "task groups" to alter the operation
|
||||
of a set of related tasks by invoking a single kernel API.
|
||||
However, applications can provide their own APIs to achieve a similar effect.
|
||||
|
||||
The kernel now spawns both a "main thread" and an "idle thread" during
|
||||
startup. (The previous kernel spawned only a single thread.)
|
||||
|
||||
The kernel's main thread performs system initialization and then invokes
|
||||
:cpp:func:`main()`. If no :cpp:func:`main()` is defined by the application,
|
||||
the main thread terminates.
|
||||
|
||||
System initialization code can now perform blocking operations,
|
||||
during which time the kernel's idle thread executes.
|
||||
|
||||
Timing
|
||||
******
|
||||
|
||||
Most kernel APIs now specify timeout intervals in milliseconds, rather than
|
||||
in system clock ticks. This change makes things more intuitive for most
|
||||
developers. However, the kernel still implements timeouts using the
|
||||
tick-based system clock.
|
||||
|
||||
The previous nanokernel timer and microkernel timer object types have been
|
||||
merged into a single type.
|
||||
|
||||
Memory Allocation
|
||||
*****************
|
||||
|
||||
The microkernel memory map object has been renamed to "memory slab", to better
|
||||
reflect its management of equal-size memory blocks.
|
||||
|
||||
It is now possible to specify the alignment used by the memory blocks
|
||||
belonging to a memory slab or a memory pool.
|
||||
|
||||
It is now possible to define a memory pool directly in code.
|
||||
|
||||
It is now possible to allocate and free memory in a malloc()-like manner
|
||||
from a heap data pool.
|
||||
|
||||
Synchronization
|
||||
***************
|
||||
|
||||
The previous nanokernel semaphore and microkernel semaphore object types have been
|
||||
merged into a single type. The new type can now be used as a binary semaphore,
|
||||
as well as a counting semaphore.
|
||||
|
||||
An application can no longer use a "semaphore group" to allow a thread to wait
|
||||
on multiple semaphores simultaneously. Until the kernel incorporates a
|
||||
:cpp:func:`select()` or :cpp:func:`poll()` capability an application wishing
|
||||
to wait on multiple semaphores must either test them individually in a
|
||||
non-blocking manner or use an additional mechanism, such as an event object,
|
||||
to signal the application that one of the semaphores is available.
|
||||
|
||||
The previous microkernel event object type is renamed to "alert" and is now presented as
|
||||
a relative to Unix-style signaling. Due to improvements to the implementation
|
||||
of semaphores, alerts are now less efficient to use for basic synchronization
|
||||
than semaphores; consequently, alerts should now be reserved for scenarios
|
||||
requiring the use of a callback function.
|
||||
|
||||
Data Passing
|
||||
************
|
||||
|
||||
The previous microkernel FIFO object type has been renamed to "message queue",
|
||||
to avoid confusion with the nanokernel FIFO object type.
|
||||
|
||||
It is now possible to specify the alignment used by the data items
|
||||
stored in a message queue (aka microkernel FIFO).
|
||||
|
||||
The previous microkernel mailbox object type no longer supports the explicit message
|
||||
priority concept. Messages are now implicitly ordered based on the priority
|
||||
of the sending thread.
|
||||
|
||||
The mailbox object type now supports sending asynchronous
|
||||
messages using a message buffer. (The previous kernel only supported
|
||||
asynchronous messages using a message block.)
|
||||
|
||||
It is now possible to specify the alignment used by a pipe object's
|
||||
buffer.
|
|
@ -25,4 +25,3 @@ include: fitness wearables, smart watches, and IoT wireless gateways.
|
|||
:maxdepth: 1
|
||||
|
||||
source_tree.rst
|
||||
changes.rst
|
||||
|
|
|
@ -1,133 +0,0 @@
|
|||
.. _application_porting_guide:
|
||||
|
||||
Legacy Applications Porting Guide
|
||||
##################################
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
This document is still work in progress.
|
||||
|
||||
This guide will help you move your applications from the nanokernel/microkernel
|
||||
model to the unified kernel. The unified kernel was introduced with
|
||||
:ref:`zephyr_1.6` which was released late 2016.
|
||||
|
||||
A list of the major changes that came with the unified kernel can be found in
|
||||
the section :ref:`changes_v2`.
|
||||
|
||||
|
||||
API Changes
|
||||
***********
|
||||
|
||||
As described in the section :ref:`kernel_api_changes` the kernel now has one
|
||||
unified and consistent API with new naming.
|
||||
|
||||
Same Arguments
|
||||
==============
|
||||
|
||||
In many cases, a simple search and replace is enough to move from the legacy to
|
||||
the new APIs, for example:
|
||||
|
||||
* :cpp:func:`task_abort()` -> :cpp:func:`k_thread_abort()`
|
||||
* :cpp:func:`task_sem_count_get()` -> :cpp:func:`k_sem_count_get()`
|
||||
|
||||
Additional Arguments
|
||||
====================
|
||||
The number of arguments to some APIs have changed,
|
||||
|
||||
* :cpp:func:`nano_sem_init()` -> :cpp:func:`k_sem_init()`
|
||||
|
||||
This function now accepts 2 additional arguments:
|
||||
|
||||
- Initial semaphore count
|
||||
- Permitted semaphore count
|
||||
|
||||
When porting your application, make sure you have set the right arguments. For
|
||||
example, calls to the old API:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
nano_sem_init(sem)
|
||||
|
||||
depending on the usage becomes in most cases:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
k_sem_init(sem, 0, UINT_MAX);
|
||||
|
||||
Return Codes
|
||||
============
|
||||
|
||||
Many kernel APIs now return 0 to indicate success and a non-zero error code
|
||||
to indicate the reason for failure. You should pay special attention to this
|
||||
change when checking for return codes from kernel APIs, for example:
|
||||
|
||||
* :cpp:func:`k_sem_take()` now returns 0 on success, in the legacy API
|
||||
:cpp:func:`nano_sem_take()` returned 1 when a semaphore is available.
|
||||
|
||||
|
||||
Application Porting
|
||||
*******************
|
||||
|
||||
The existing :ref:`synchronization_sample` from the Zephyr tree will be used to
|
||||
guide you with porting a legacy application to the new kernel.
|
||||
|
||||
The code has been ported to the new kernel and is shown below:
|
||||
|
||||
.. literalinclude:: sync_v2.c
|
||||
:linenos:
|
||||
:language: c
|
||||
:lines: 9-
|
||||
|
||||
Porting a Nanokernel Application
|
||||
=================================
|
||||
|
||||
Below is the code for the application using the legacy kernel:
|
||||
|
||||
.. literalinclude:: sync_v1_nano.c
|
||||
:linenos:
|
||||
:language: c
|
||||
:lines: 9-
|
||||
|
||||
Porting a Microkernel Application
|
||||
=================================
|
||||
|
||||
The MDEF feature of the legacy kernel has been eliminated. Consequently, all
|
||||
kernel objects are now defined directly in code.
|
||||
|
||||
Below is the code for the application using the legacy kernel:
|
||||
|
||||
.. literalinclude:: sync_v1.c
|
||||
:linenos:
|
||||
:language: c
|
||||
:lines: 9-
|
||||
|
||||
|
||||
A microkernel application defines the used objects in an MDEF file, for this
|
||||
porting sample using the :ref:`synchronization_sample`, the file is shown below:
|
||||
|
||||
.. literalinclude:: v1.mdef
|
||||
:linenos:
|
||||
|
||||
In the unified kernel the semaphore will be defined in the code as follows:
|
||||
|
||||
.. literalinclude:: sync_v2.c
|
||||
:linenos:
|
||||
:language: c
|
||||
:lines: 51-54
|
||||
|
||||
The threads (previously named tasks) are defined in the code as follows, for
|
||||
thread A:
|
||||
|
||||
.. literalinclude:: sync_v2.c
|
||||
:linenos:
|
||||
:language: c
|
||||
:lines: 88-89
|
||||
|
||||
Thread B (taskB in the microkernel) will be spawned dynamically from thread A
|
||||
(See :ref:`spawning_thread` section):
|
||||
|
||||
.. literalinclude:: sync_v2.c
|
||||
:linenos:
|
||||
:language: c
|
||||
:lines: 80-82
|
|
@ -11,5 +11,4 @@ architectures, SoCs and boards.
|
|||
|
||||
arch.rst
|
||||
board_porting.rst
|
||||
application.rst
|
||||
ip-stack-migrate.rst
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
/* hello.c - Hello World demo */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <misc/printk.h>
|
||||
|
||||
/*
|
||||
* Microkernel version of hello world demo has two tasks that utilize
|
||||
* semaphores and sleeps to take turns printing a greeting message at
|
||||
* a controlled rate.
|
||||
*/
|
||||
|
||||
|
||||
/* specify delay between greetings (in ms); compute equivalent in ticks */
|
||||
|
||||
#define SLEEPTIME 500
|
||||
#define SLEEPTICKS (SLEEPTIME * sys_clock_ticks_per_sec / 1000)
|
||||
|
||||
/*
|
||||
*
|
||||
* @param taskname task identification string
|
||||
* @param mySem task's own semaphore
|
||||
* @param otherSem other task's semaphore
|
||||
*
|
||||
*/
|
||||
void helloLoop(const char *taskname, ksem_t mySem, ksem_t otherSem)
|
||||
{
|
||||
while (1) {
|
||||
task_sem_take(mySem, TICKS_UNLIMITED);
|
||||
|
||||
/* say "hello" */
|
||||
printk("%s: Hello World from %s!\n", taskname, CONFIG_ARCH);
|
||||
|
||||
/* wait a while, then let other task have a turn */
|
||||
task_sleep(SLEEPTICKS);
|
||||
task_sem_give(otherSem);
|
||||
}
|
||||
}
|
||||
|
||||
void taskA(void)
|
||||
{
|
||||
/* taskA gives its own semaphore, allowing it to say hello right away */
|
||||
task_sem_give(TASKASEM);
|
||||
|
||||
/* invoke routine that allows task to ping-pong hello messages with taskB */
|
||||
helloLoop(__func__, TASKASEM, TASKBSEM);
|
||||
}
|
||||
|
||||
void taskB(void)
|
||||
{
|
||||
/* invoke routine that allows task to ping-pong hello messages with taskA */
|
||||
helloLoop(__func__, TASKBSEM, TASKASEM);
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
/* main.c - Synchronisation demo */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <misc/printk.h>
|
||||
|
||||
|
||||
/*
|
||||
* Nanokernel version of hello world demo has a task and a fiber that utilize
|
||||
* semaphores and timers to take turns printing a greeting message at
|
||||
* a controlled rate.
|
||||
*/
|
||||
|
||||
|
||||
/* specify delay between greetings (in ms); compute equivalent in ticks */
|
||||
|
||||
#define SLEEPTIME 500
|
||||
#define SLEEPTICKS (SLEEPTIME * sys_clock_ticks_per_sec / 1000)
|
||||
|
||||
#define STACKSIZE 2000
|
||||
|
||||
char __stack fiberStack[STACKSIZE];
|
||||
|
||||
struct nano_sem nanoSemTask;
|
||||
struct nano_sem nanoSemFiber;
|
||||
|
||||
void fiberEntry(void)
|
||||
{
|
||||
struct nano_timer timer;
|
||||
u32_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(&nanoSemFiber, TICKS_UNLIMITED);
|
||||
|
||||
/* say "hello" */
|
||||
printk("%s: Hello World!\n", __func__);
|
||||
|
||||
/* wait a while, then let task have a turn */
|
||||
nano_fiber_timer_start(&timer, SLEEPTICKS);
|
||||
nano_fiber_timer_test(&timer, TICKS_UNLIMITED);
|
||||
nano_fiber_sem_give(&nanoSemTask);
|
||||
}
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
struct nano_timer timer;
|
||||
u32_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" */
|
||||
printk("%s: Hello World!\n", __func__);
|
||||
|
||||
/* wait a while, then let fiber have a turn */
|
||||
nano_task_timer_start(&timer, SLEEPTICKS);
|
||||
nano_task_timer_test(&timer, TICKS_UNLIMITED);
|
||||
nano_task_sem_give(&nanoSemFiber);
|
||||
|
||||
/* now wait for fiber to let us have a turn */
|
||||
nano_task_sem_take(&nanoSemTask, TICKS_UNLIMITED);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
/* main.c - Hello World demo */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <misc/printk.h>
|
||||
|
||||
/*
|
||||
* The hello world demo has two threads that utilize semaphores and sleeping
|
||||
* to take turns printing a greeting message at a controlled rate. The demo
|
||||
* shows both the static and dynamic approaches for spawning a thread; a real
|
||||
* world application would likely use the static approach for both threads.
|
||||
*/
|
||||
|
||||
|
||||
/* size of stack area used by each thread */
|
||||
#define STACKSIZE 1024
|
||||
|
||||
/* scheduling priority used by each thread */
|
||||
#define PRIORITY 7
|
||||
|
||||
/* delay between greetings (in ms) */
|
||||
#define SLEEPTIME 500
|
||||
|
||||
|
||||
/*
|
||||
* @param my_name thread identification string
|
||||
* @param my_sem thread's own semaphore
|
||||
* @param other_sem other thread's semaphore
|
||||
*/
|
||||
void helloLoop(const char *my_name,
|
||||
struct k_sem *my_sem, struct k_sem *other_sem)
|
||||
{
|
||||
while (1) {
|
||||
/* take my semaphore */
|
||||
k_sem_take(my_sem, K_FOREVER);
|
||||
|
||||
/* say "hello" */
|
||||
printk("%s: Hello World from %s!\n", my_name, CONFIG_ARCH);
|
||||
|
||||
/* wait a while, then let other thread have a turn */
|
||||
k_sleep(SLEEPTIME);
|
||||
k_sem_give(other_sem);
|
||||
}
|
||||
}
|
||||
|
||||
/* define semaphores */
|
||||
|
||||
K_SEM_DEFINE(threadA_sem, 1, 1); /* starts off "available" */
|
||||
K_SEM_DEFINE(threadB_sem, 0, 1); /* starts off "not available" */
|
||||
|
||||
|
||||
/* threadB is a dynamic thread that is spawned by threadA */
|
||||
|
||||
void threadB(void *dummy1, void *dummy2, void *dummy3)
|
||||
{
|
||||
ARG_UNUSED(dummy1);
|
||||
ARG_UNUSED(dummy2);
|
||||
ARG_UNUSED(dummy3);
|
||||
|
||||
/* invoke routine to ping-pong hello messages with threadA */
|
||||
helloLoop(__func__, &threadB_sem, &threadA_sem);
|
||||
}
|
||||
|
||||
char __noinit __stack threadB_stack_area[STACKSIZE];
|
||||
|
||||
|
||||
/* threadA is a static thread that is spawned automatically */
|
||||
|
||||
void threadA(void *dummy1, void *dummy2, void *dummy3)
|
||||
{
|
||||
ARG_UNUSED(dummy1);
|
||||
ARG_UNUSED(dummy2);
|
||||
ARG_UNUSED(dummy3);
|
||||
|
||||
/* spawn threadB */
|
||||
k_thread_spawn(threadB_stack_area, STACKSIZE, threadB, NULL, NULL, NULL,
|
||||
PRIORITY, 0, K_NO_WAIT);
|
||||
|
||||
/* invoke routine to ping-pong hello messages with threadB */
|
||||
helloLoop(__func__, &threadA_sem, &threadB_sem);
|
||||
}
|
||||
|
||||
K_THREAD_DEFINE(threadA_id, STACKSIZE, threadA, NULL, NULL, NULL,
|
||||
PRIORITY, 0, K_NO_WAIT);
|
|
@ -1,11 +0,0 @@
|
|||
% Application : Hello demo
|
||||
|
||||
% TASK NAME PRIO ENTRY STACK GROUPS
|
||||
% ==================================
|
||||
TASK TASKA 7 taskA 1024 [EXE]
|
||||
TASK TASKB 7 taskB 1024 [EXE]
|
||||
|
||||
% SEMA NAME
|
||||
% =============
|
||||
SEMA TASKASEM
|
||||
SEMA TASKBSEM
|
Loading…
Reference in a new issue