Important
This core is in BETA.
Features may change, and bugs may be present. Use for testing only and provide feedback to help us improve.
Arduino Core for Zephyr
This repository is a downstream fork of the Arduino Core for Zephyr RTOS-based boards that includes support for Arduino software tools, allowing it to be seamlessly used by the Arduino IDE, Arduino CLI and Arduino App Lab.
What is Zephyr?
Zephyr RTOS is an open-source, real-time operating system designed for low-power, resource-constrained devices. It's modular, scalable, and supports multiple architectures.
Installation
Install the core and its toolchains via Board Manager:
- Download and install the latest Arduino IDE (only versions
2.x.xare supported). - Open the 'Settings / Preferences' window.
- Open the 'Boards Manager' from the side menu and search for 'Zephyr'.
- If it doesn't appear, add the following URL to the 'Additional Boards Manager URLs' field:
https://downloads.arduino.cc/packages/package_zephyr_index.json(if you have multiple URLs, separate them with a comma).
- If it doesn't appear, add the following URL to the 'Additional Boards Manager URLs' field:
- Install the
Arduino Zephyr Boardsplatform.
Alternatively, to install the core using the command line, run the following command with the Arduino CLI:
First Use
To get started with your board:
- Put the board in bootloader mode by double-clicking the RESET button.
- Run the
Burn Bootloaderoption from the IDE/CLI.- Note that due to limitations in the Arduino IDE, you may need to select any programmer from the
Programmersmenu.
- Note that due to limitations in the Arduino IDE, you may need to select any programmer from the
- Once the bootloader is installed, you can load your first sketch by placing the board into bootloader mode again.
Note
After the initial setup, future sketches will be loaded automatically without needing to reset the board.
Troubleshooting
Common Issues
Q: My Sketch doesn't start (Serial doesn't appear)
A: Connect a USB-to-UART adapter to the default UART (eg. TX0/RX0 on Giga, TX/RX on Nano) and read the error message (with the sketch compiled in Default mode). If you don't own a USB-to-UART adapter, compile the sketch in Debug mode; this will force the shell to wait until you open the Serial Monitor. Then, run sketch command and probably you'll be able to read the error (if generated by llext). For OS crashes, the USB-to-UART adapter is the only way to collect the crash.
Q: I did it and I get the error: llext: Undefined symbol with no entry in symbol table ...
A: This means you are trying to use a Zephyr function which has not yet been exported. Open llext_exports.c, add the function you need and recompile/upload the loader.
Q: I want to use a Zephyr subsystem which is not compiled in
A: Open the .conf file for your board, add the required CONFIG_, recompile/upload the loader.
Q: I get an OS crash, like os: ***** USAGE FAULT *****
A: This is usually due to a buffer overflow or coding error in the user's own code. However, since the project is still in beta , a good bug report could help identify any issues in our code.
Q: I get an out of memory error
A: Since collecting bug reports is very important at this time, we are keeping Zephyr's shell enabled to allow loading a full sketch (which requires a large stack). Adjust your board's .conf file to reduce the stack size if your platform doesn't have enough RAM.
Libraries
Included with the core:
Separately supplied:
- ArduinoBLE: This library is enabled only for the Arduino Nano 33 BLE. Please use this branch to test it.
Under the hood
Unlike traditional Arduino implementations, where the final output is a standalone binary loaded by a bootloader, this core generates a freestanding elf file. This file is dynamically loaded by a precompiled Zephyr firmware, referred to as the loader.
The loader is responsible for managing the interaction between your sketches and the underlying Zephyr system. After the initial bootloader installation, the loader takes over the sketch loading process automatically.
To ensure flexibility, the loader project is designed to be generic. Any necessary modifications for specific boards should be made in the corresponding "DTS overlay" or a special "fixup" file, using appropriate guards to maintain compatibility.
The behavior of the loader can be adjusted through the Mode menu of the IDE:
Standard: The sketch is loaded automatically.Debug: The user must typesketchin Zephyr's shell, which is accessible via the default Serial.
The most important components of this project are:
- Zephyr based loader
- LLEXT
- Actual core with variants and the usual platform and boards files
- ArduinoCore-API
- zephyr-sketch-tool
Shortcut: using the Core in Arduino IDE/CLI without installing Zephyr
Tip
If you are only interested in developing features in the core
or libraries, and do not want to set up a full Zephyr build
environment, you can use the sync-zephyr-artifacts
utility to download a pre-built version of the files needed to compile
sketches and flash the loader.
To do so, after cloning this repo, compile the sync-zephyr-artifacts
utility via go build and run it as sync-zephyr-artifacts . to retrieve
the precompiled files for the current revision of the core.
Next, follow the instructions in Using the Core in Arduino IDE/CLI or Using the Core in the Arduino App Lab to start using the core in your preferred Arduino software. Remember to update the loader on your board as well.
Setup a Zephyr build environment
Warning
If you checked out this repo before 0.3.2 was released, please note that
development has switched to the main branch; the old arduino branch will
be removed in the short future. Please follow this
migration guide
to update your local branches and outstanding PRs.
In this section, we'll guide you through setting up your environment to work on and update the Zephyr core.
Shell scripts are available to simplify the installation process (Windows is not directly supported at the moment , but there are some tricks - see below).
Clone the repository
git clone https://github.com/arduino/ArduinoCore-zephyr
Pre-requirements
Before running the installation script, ensure that Python, pip and venv are installed on your system. The script will automatically install west and manage the necessary dependencies.
On Ubuntu or similar apt-based distros
On macOS
Make sure you have Homebrew installed. Then run:
xcode-select --install
# Install required tools and libraries
brew install python cmake ninja zstd jq git
Note: Homebrew's Python installation already includes pip, setuptools and venv.
On Windows
Building natively on Windows is not currently supported; however, it is possible to setup and build the loader using WSL. Once you have that installed, you will need to follow these instructions as if you had Ubuntu.
There are two strategies to set up the sources for building the loader on Windows:
- Install the sources in the native Windows filesystem (NTFS, FAT32, etc) and within WSL, cd to the root directory where you installed your sources, like:
/mnt/d/github/ArduinoCore-zephyr. - Install the sources within the WSL file system, like:
~/git/ArduinoCore-zephyr
There are pros and cons to both strategies:
- Builds on the native Windows file system are relatively very slow, but once done, you can use the results directly within the Arduino IDE.
- Builds on WSL's file system are a lot faster, however, you need to copy the resulting build back to somewhere in your Windows directory structure. Use this location in the Arduino IDE as mentioned below in the Using the Core in Arduino IDE/CLI section.
After bootstrap.sh has completed, you may also have to update the cores\arduino\api link to the path of the ArduinoCore-API's api folder.
Run the bootstrap script
./extra/bootstrap.sh
This will take care of installing west, the Zephyr build tool. It will then
download all packages required for a Zephyr build in addition to the toolchains
in the Zephyr SDK.
Note
This core is validated with version v0.16.8 of the SDK. Compatibility with later versions has not been tested yet.
Regenerate the compiled core files
Build the Loader
The loader is compiled for each board by running the ./extra/build.sh script.
The target can be specified either with the Arduino board name (as defined in
boards.txt), or with the Zephyr board name and any additional arguments that
may be required by the Zephyr build system.
For example, to build for the Arduino Portenta H7, you can use either the Arduino name:
or the Zephyr board target:
The firmwares will be copied to the firmware folder, and the associated variant will be updated.
Flash the Loader
To flash the loader, run:
The appears in the build output when you run the build script. For example:
Build target: arduino_portenta_h7@1.0.0//m7
Build variant: arduino_portenta_h7_stm32h747xx_m7
-- west build: generating a build system
...
In this case, you would flash with:
This can also be performed via the "Burn bootloader" action in the IDE if the core is properly installed, as detailed below.
Using the Core in Arduino IDE/CLI
After running the bootstrap.sh script, you can create a symlink from the
ArduinoCore-zephyr folder to ${sketchbook}/hardware/arduino-git/zephyr, so
that the boards.txt file in this repository will be also available as
${sketchbook}/hardware/arduino-git/zephyr/boards.txt.
Once this is done, your development folder will appear in the IDE/CLI package
list as arduino-git:zephyr, and the Fully Qualified Board Name (FQBN) to use
will be arduino-git:zephyr:name_from_boards_txt.
Remember to also install and/or update the officially published core in the IDE Board Manager to get the latest tools and dependencies. Installation.
Using the Core in the Arduino App Lab
Warning
Arduino App Lab expects a hardcoded FQBN (arduino:zephyr:unoq for the UNO Q), so the technique used for Arduino IDE/CLI does not work. A small workaround is required.
- Disable the release core
This ensures the installation of the development version of the core will be used instead of the release installation.
- Install your custom core
Place your custom core in the following path:
- Flash the new loader
Build and flash the loader from your custom core to overwrite the release version. For example, on UNO Q:
Revert to release core
If you want to use the official core again, change the directory names so the one in ~/.arduino15 is zephyr, and the one in your sketchbook's hardware folder is zephyr.disable:
mv ~/Arduino/hardware/arduino/zephyr ~/Arduino/hardware/arduino/zephyr.disable
Adding a new target
Tip
While Zephyr supports a lot of different hardware targets, only the few currently used by the Arduino core are installed by default. To add the support for every Zephyr target to your workspace, run the following commands:
west config -d manifest.project-filter
west sdk install --version 0.17.0
west update
To add a new board that is already supported by mainline Zephyr with the target $your_board, follow these steps:
-
Get the variant name from your board by running
extra/get_variant_name.sh $your_board. -
Create a folder in the
variants/directory with the same name as the variant for your new board. -
Create the DTS
and Kconfig.overlay files in that directory..conf The overlay must include:
- A flash partition called
user_sketch, typically located near the end of the flash. - A
zephyr,usersection containing the description for GPIOs, Analog, UART, SPI and I2C devices. Feel free to leave some fields empty in case Zephyr support is missing. This will result in some APIs not being available at runtime (eg.analogWriteif PWM section is empty).
The Kconfig file must include any board-specific options required by this target.
- A flash partition called
-
Build the Loader: run
./extra/build.sh $your_board(with any additional arguments as required) and start debugging the errors. -
Update the
boards.txt: add an entry for your board, manually filling the required fields.Make sure to set:
build.zephyr_targetandbuild.zephyr_argsto the arguments used in thebuild.shcall;build.zephyr_halsto the (space-separated list of) HAL modules required by the board;build.variantto the variant name identified above.
-
Implement touch support: if your board supports the "1200bps touch" method, implement
_on_1200_bpsin a file located inside the variant folder of your board.
Bug Reporting
To report a bug, open the issues and follow the instructions. Any issue opened without the needed information will be discarded.
Contributions
Contributions are always welcome. The preferred way to receive code contribution is by submitting a Pull request.
Warning
At this stage of development, we only accept Pull requests for bug fixes and features. We do not accept support for new targets.
Upcoming features
- USB: switch to
USB_DEVICE_STACK_NEXTto support PluggableUSB - Relocate RODATA in flash to accommodate sketches with large assets
- Provide better error reporting for failed llext operations
- Replace
llext_exports.cwith proper symbols generation (via includes) - Fix corner cases with
std::includes (like) - Get rid of all warnings
Acknowledgments
This effort would have been very hard without the GSoC project and the Zephyr community.