Zephyr is an open source RTOS (real-time operating system) project that is being widely adopted for resource-constrained systems, from environmental sensors to smart watches and IoT wireless gateways. BayLibre is a member of the Zephyr Project and has been a core contributor since the project began. We have ported Zephyr to the 64-bit ARM and 64-bit RISC-V architectures. Our engineers also maintain core parts of Zephyr.
Zephyr v3.1.0 was released at the beginning of June, and four BayLibre engineers contributed 111 commits to the release. This includes Valerio Setti who we are excited to have as our newest contributor to Zephyr.
Architecture support: ARM64
- Nicolas Pitre simplified the user mode transition code to make it smaller and faster.
- Nicolas made an improvement to avoid executing ISRs (interrupt service routines) using the thread stack as it might not be appropriately sized, and the IRQ stack is already set up for this use.
- Nicolas optimized the arch_switch() implementation for lower latency by avoiding a full exception roundtrip on every context switch.
Architecture: RISC-V
- Nicolas Pitre contributed a new implementation of RISC-V PMP support. Physical Memory Protection (PMP) is RISC-V parlance for a memory protection unit (MPU). The PMP entries, also known as slots, allow machine mode (the most privileged mode) to protect certain memory regions from user mode threads.
- Nicolas also added a new Stackguard implementation. Stackguard uses the PMP to prevent many types of stack overflow by making any access to the bottom stack area raise a CPU exception. Each thread has its set of pre-computed PMP entries and those are written to PMP registers at context switch time. Previously, the stackguard wasn’t properly enforced and that is now fixed.
- Nicolas greatly simplified and optimized the exception handling code
- Nicolas added RISC-V support for semi-hosting with QEMU or OpenOCD. Semi-hosting is a mechanism that enables code running on the microcontroller board to communicate and use the input/output facilities on a host computer that is running a debugger.
- Nicolas cleaned up the RISC-V assembly code quite extensively to improve its readability.
Board support
- Valerio Setti added support for R-Car H3 Salvator-X board.
Core
- Nicolas simplified the ring buffer implementation, the code is now entirely relying only on simple ALU operations (add, sub and compare).
- Nicolas made it possible to use memset/memcpy alternatives during early boot for architectures that can’t safely use the regular optimized memset because hardware isn’t yet sufficiently initialized may override this with their own safe implementation.
- Carlo Caione improved device tree handling during build time by adding a new cmake function
External Memory
- External flash is extremely useful when a large application code doesn’t entirely fit on the internal flash. Part of the application can be stored in flash and the processor can XIP (execute-in-place) the code directly from flash. However, Zephyr lacked a way at build time to move code to a different memory region.
- Carlo Caione used the code_relocation feature to dynamically build linker script snippets so that code can be XIP-ed from the destination region.
- Carlo extended the nocopy sample to the Nordic nRF5340dk board which has external QSPI flash that can be used to do XIP from.
- Carlo added functionality for Zephyr to generate memory regions based on the new device tree ‘zephyr,memory-region’ attribute. Variables can then be placed in these sections by using compiler attributes.
IPC (Inter Processor Communication)
- Carlo Caione added a nocopy function to the IPC service API. The function can be called to get an empty TX buffer so that the application can directly put its data into the sending buffer without copying it from an application buffer.
- Carlo also added this new nocopy capability to the static vrings backend.
PCIe
- Neil Armstrong continued work on PCIe Host Controller support on non-x86 platforms by adding:
- Generic controller MSI/MSI-X API
- Generic core functions for Generic Host PCIe Controllers
- Implementation of MSI/MSI-X support for generic controllers & ECAM
- API for the ARM GIC ITS (Interrupt Translation Service) to retrieve the MSI base address to be configured in the MSI/MSI-X table.
Logging
- Valerio Setti introduced a new config option to print the timestamp as the Linux’s kernel format. This can be utilized by AMP (asymmetric multi-processor) platforms in which logs from Linux and Zephyr must be interleaved in order to get a comprehensive view of the entire system.
- Valerio also fixed the logging subsystem to properly handle both 64-bit and 32-bit timestamps
System Calls
- System call arguments have been working properly for 64-bit builds with normal compiler optimizations enabled, but Nicolas Pitre discovered this was not the case for 64-bit debug builds. Nicolas explains his journey to fix system call argument marshalling in his recent Embedded Recipes talk in Paris.
- The end results is that Nicolas removed the pointer dereference roundtrip and associated casts which fixed the corruption of the system call arguments in 64-bit debug builds. Nicolas also introduced a union to perform the type transition which produces the same assembly code while also making the silencing warnings from the compiler.
If your team needs help with Zephyr or any other embedded software such as Linux or Android, then please don’t hesitate to reach out to the experts at BayLibre.
You can also follow BayLibre on Twitter, LinkedIn and Mastodon for more.