0% found this document useful (0 votes)
208 views

ELC 2021 Zephyr Startup v0.2

Uploaded by

Y Y
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
208 views

ELC 2021 Zephyr Startup v0.2

Uploaded by

Y Y
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 17

Zephyr Project:

RTOS Startup and Initialization Flow

David Leach, NXP Semiconductors


ELC 2021

#lfelc
Architecture

• Highly Configurable, Highly Modular


• Cooperative and Preemptive
Threading
• Memory and Resources are typically
statically allocated
• Integrated device driver interface
• Memory Protection: Stack overflow
protection, Kernel object and device
driver permission tracking, Thread
isolation
• Bluetooth® Low Energy (BLE 5.1)
with both host and BLE Mesh
• 802.15.4 OpenThread
• Native, fully featured and optimized
networking stack

#ossummit #lfelc #ospocon


#ospocon
Simplified initialization flow

#ospocon
Zephyr Early Startup
• Goal of early startup sequence:

– Prepares the system for running C code

• If the architecture supports it, the


processor will be in thread mode at
privileged level

• Reset Entry point

– typically located in arch/<arch>/core/reset.S

• Common steps for all architectures:

– Setup an initial stack (z_interrupt_stacks).


– zero the BSS section
– copy initialized data from ROM to RAM

* startup for Cortex-M architectures shown

#ospocon
RISCV early startup view

• Similar flow to ARM early startup.


• No hook (yet) via
CONFIG_PLATFORM_SPECIFIC_INIT

#ospocon
Kernel Initialization

• dummy_thread required for the “prepare


scheduler” phase.
– thread marked as _THREAD_DUMMY to
avoid execution from scheduler

• Initialize the static device objects to prepare for


run level initializations and general usage

• initialize PRE_KERNEL_1 devices

• Initialize PRE_KERNEL_2 devices

#ospocon
Preparing Scheduler

• Primary initialization performed in


prepare_multithreading()
– Kernel ready queues are initialized
– main thread is initialized and marked as started &
ready
– idle threads (per-CPU) are initialized and marked
as ready

• Context switch initiated


– z_main_thread is selected as it is the only thread
started and ready to run

#ospocon
bg_thread_main: final system initialization
• Zephyr Kernel & Scheduler now running. Kernel
services are fully available for the rest of the
initialization.

• Initialization objects and application components


are initialized

• Initialize any static threads

• If CONFIG_SMP then initialize SMP level objects


and components.

• Call application main(). This can be the Zephyr


defined main(), which only returns, or an
application supplied main().

#ospocon
Device Drivers and System Driver

• Zephyr provides APIs to instantiate device driver objects and


system drivers that need initialization functions called during the
kernel initialization flow.

– The initialization level at which configuration occurs.


– The initialization priority of the object, relative to other objects of the same
initialization level. Specified as an integer value in the range 0 to 99;

• Device Driver APIs


– DEVICE_DEFINE(dev_name, drv_name, init_fn, pm_control_fn, data_ptr, cfg_ptr, level, prio, api_ptr)
– DEVICE_DT_DEFINE(node_id, init_fn, pm_control_fn, data_ptr, cfg_ptr, level, prio, api_ptr, ...)
– DEVICE_DT_INST_DEFINE(inst, init_fn, pm_control_fn, data_ptr, cfg_ptr, level, prio, api_ptr, ...)

• System Driver APIs


– SYS_INIT(_init_fn, _level, _prio)
– SYS_DEVICE_DEFINE(drv_name, init_fn, pm_control_fn, level, prio)

#ossummit #lfelc #ospocon


Initialization Levels and Priorities
• Initialization Level must be one of the following symbols, which are listed in the order they are performed by the
kernel:

– PRE_KERNEL_1
• Used for initialization objects that have no dependencies, such as those that rely solely on hardware present in the processor/SOC. These
objects cannot use any kernel services during configuration, since they are not yet available.

– PRE_KERNEL_2
• Used for initialization objects that rely on objects initialized as part of the PRE_KERNEL_1 level. These objects cannot use any kernel
services during configuration, since they are not yet available.

– POST_KERNEL
• Used for initialization objects that require kernel services during configuration.

– APPLICATION
• Used for application components (i.e. non-kernel components) that need automatic configuration. The devices can use all services
provided by the kernel during configuration. Init functions at this level run on the kernel main task.

– SMP
• Initialization that requires kernel services during configuration after Symmetric Multi-Processing (SMP) initialization.

• The initialization priority of the object is relative to other objects of the same initialization level.

– Specified as an integer value in the range 0 to 99; Lower values have higher priority
– The order of multiple objects with the same priority level is undefined. Use different priority levels between related
objects if you wish to control initialization order of multiple object within the same initialization level.

#ossummit #lfelc #ospocon


Driver Examples
• The underlying device macro instantiates a struct init_entry device object with a section attribute
constructed as as “.z_init_<level>_prio<prio>_”

• drivers/serial/mcux_lpuart.c:
DEVICE_DT_INST_DEFINE(n,\
&mcux_lpuart_init,\
NULL,\
&mcux_lpuart_##n##_data,\
&mcux_lpuart_##n##_config,\
PRE_KERNEL_1,\
CONFIG_KERNEL_INIT_PRIORITY_DEVICE,\
&mcux_lpuart_driver_api);\

• soc/arm/nxp_imx/rt/soc_rt10xx.c:

SYS_INIT(imxrt_init, PRE_KERNEL_1, 0);

• An initLevel section in which contains the init device objects sorted by the constructed section
attribute names to ensures the priority order within an initialization level.

#ossummit #lfelc #ospocon


zephyr.map initlevel section
initlevel 0x7001273c 0xb0
0x7001273c __init_start = .
0x7001273c __init_PRE_KERNEL_1_start = .
*(SORT_BY_NAME(SORT_BY_ALIGNMENT(.z_init_PRE_KERNEL_1[0-9]_*)))
.z_init_PRE_KERNEL_10_
0x7001273c 0x8 zephyr/libzephyr.a(soc_rt10xx.c.obj)
.z_init_PRE_KERNEL_10_
0x70012744 0x8 zephyr/boards/arm/mimxrt1064_evk/libboards__arm__mimxrt1064_evk.a(pinmux.c.obj)
*(SORT_BY_NAME(SORT_BY_ALIGNMENT(.z_init_PRE_KERNEL_1[1-9][0-9]_*)))
.z_init_PRE_KERNEL_130_
0x7001274c 0x8 zephyr/kernel/libkernel.a(kheap.c.obj)
.z_init_PRE_KERNEL_130_
0x70012754 0x8 zephyr/kernel/libkernel.a(mem_slab.c.obj)
.z_init_PRE_KERNEL_150_
0x7001275c 0x8 zephyr/drivers/clock_control/libdrivers__clock_control.a(clock_control_mcux_ccm.c.obj)
.z_init_PRE_KERNEL_150_
0x70012764 0x8 zephyr/drivers/serial/libdrivers__serial.a(uart_mcux_lpuart.c.obj)
.z_init_PRE_KERNEL_150_
0x7001276c 0x8 zephyr/drivers/entropy/libdrivers__entropy.a(entropy_mcux_trng.c.obj)
.z_init_PRE_KERNEL_160_
0x70012774 0x8 zephyr/drivers/console/libdrivers__console.a(uart_console.c.obj)
0x7001277c __init_PRE_KERNEL_2_start = .
*(SORT_BY_NAME(SORT_BY_ALIGNMENT(.z_init_PRE_KERNEL_2[0-9]_*)))
.z_init_PRE_KERNEL_20_
0x7001277c 0x8 zephyr/boards/arm/mimxrt1064_evk/libboards__arm__mimxrt1064_evk.a(pinmux.c.obj)
.z_init_PRE_KERNEL_20_
0x70012784 0x8 zephyr/drivers/timer/libdrivers__timer.a(sys_clock_init.c.obj)
*(SORT_BY_NAME(SORT_BY_ALIGNMENT(.z_init_PRE_KERNEL_2[1-9][0-9]_*)))

#ossummit #lfelc #ospocon


Statically Defined Threads
• K_THREAD_DEFINE() is used to statically define and create an entry in the _static_thread_data_area.

• K_THREAD_DEFINE(name, stack_size, entry, p1, p2, p3, prio, options, delay)

• z_init_static_threads() will iterate through the list of static threads to initialize and schedule each of them.

• samples/net/sockets/packet/src/packet.c:

K_THREAD_DEFINE(receiver_thread_id, STACK_SIZE,
recv_packet, NULL, NULL, NULL,
THREAD_PRIORITY, 0, -1);
K_THREAD_DEFINE(sender_thread_id, STACK_SIZE,
send_packet, NULL, NULL, NULL,
THREAD_PRIORITY, 0, -1);

• zephyr.map:

_static_thread_data_area
0x8000088c 0x60 load address 0x70017c90
0x8000088c __static_thread_data_list_start = .
*(SORT_BY_NAME(SORT_BY_ALIGNMENT(.__static_thread_data.static.*)))
.__static_thread_data.static._k_thread_data_receiver_thread_id
0x8000088c 0x30 app/libapp.a(packet.c.obj)
0x8000088c _k_thread_data_receiver_thread_id
.__static_thread_data.static._k_thread_data_sender_thread_id
0x800008bc 0x30 app/libapp.a(packet.c.obj)
0x800008bc _k_thread_data_sender_thread_id
0x800008ec __static_thread_data_list_end = .

#ossummit #lfelc #ospocon


#ospocon
Reference

• Orientation:
– https://zephyrproject.org/
– https://docs.zephyrproject.org/latest/index.html

• Github:
– https://github.com/zephyrproject-rtos/zephyr
– https://github.com/zephyrproject-rtos/zephyr/wiki

• Mail Lists:
– https://lists.zephyrproject.org/g/main

• Zephyr Developer Summit


– https://github.com/zephyrproject-rtos/zephyr/wiki/2021-Zephyr-Developer-Summit
– “Real Time in the Real World, Scheduler Details for Practical Problems”, Andy Ross
• https://www.youtube.com/watch?v=6PpjYa1kJ1U
• https://drive.google.com/file/d/1zSMltFNkAqenjgd0X-rkCPy13ZHj4ltC/view?usp=sharing

#ossummit #lfelc #ospocon

You might also like