Skip to content

Commit f63b2d3

Browse files
xtremekforeverrauhul
authored andcommitted
Add full content for IntegrateWithZephyr.md, including west integration instructions
1 parent 309b249 commit f63b2d3

File tree

1 file changed

+139
-8
lines changed

1 file changed

+139
-8
lines changed

Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md

Lines changed: 139 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44

55
For an introduction and motivation into Embedded Swift, please see "[A Vision for Embedded Swift](https://github.com/swiftlang/swift-evolution/blob/main/visions/embedded-swift.md)", a Swift Evolution document highlighting the main goals and approaches.
66

7-
Refer to the [nrfx-blink-sdk](../../../../nrfx-blink-sdk/) project for a complete working "blinky" example that can be used as a starting point. However, for a formal introduction to setting up a Swift Zephyr project and explanations into the various options, continue reading this document.
7+
The following document outlines how to setup a Swift to Zephyr project for an emulated ARM Cortex M0, explaining a few key concepts along the way. For a complete working example on real hardware, however, refer to the [nrfx-blink-sdk](../../../../nrfx-blink-sdk/) project that is compatible with nRF or other boards.
88

99
## Zephyr Setup
1010

1111
Before setting up a Swift project that works with Zephyr, you need to setup dependencies and a Zephyr workspace as per the [Getting Started Guide](https://docs.zephyrproject.org/latest/develop/getting_started/index.html). Regardless of your platform (macOS or Linux), ensure that you can build the blinky example without errors before starting with Swift integration:
1212

1313
```bash
1414
cd ~/zephyrproject/zephyr
15-
west build -p always -b <your-board-name> samples/basic/blinky
15+
west build -p always -b reel_board samples/basic/blinky
1616
```
1717

1818
By default, the `main` revision of the Zephyr sources are checked out when calling `west init`, which contains pre-release and development changes that may cause instability and changing APIs that are not desirable. To checkout a specific release version of Zephyr, use the following commands:
@@ -43,12 +43,13 @@ SwiftZephyrProject/prj.conf
4343

4444
These are the minimum required files in order to build a Zephyr project. By convention, source files should be placed in the src/ subdirectory, but this is not a hard requirement. Also, `prj.conf` is required even if it is empty, or the project will not build.
4545

46-
Inside of `src/BridgingHeader.h`, add the following content as a minimum:
46+
Inside of `src/BridgingHeader.h`, add the following content:
4747

4848
```c
4949
#pragma once
5050

5151
#include <autoconf.h>
52+
#include <zephyr/kernel.h>
5253
```
5354

5455
The `src/Main.swift` file must contain a `static func main()` as follows:
@@ -57,12 +58,17 @@ The `src/Main.swift` file must contain a `static func main()` as follows:
5758
@main
5859
struct Main {
5960
static func main() {
60-
// code
61+
print("Hello Zephyr from Swift!")
62+
63+
while true {
64+
k_msleep(1000)
65+
print("Loop")
66+
}
6167
}
6268
}
6369
```
6470

65-
Since Embedded Swift requires posix_memalign to be defined, add the following to `src/Stubs.c` to define it:
71+
Since Embedded Swift requires `posix_memalign` to be defined, add the following to `src/Stubs.c` to define it:
6672

6773
```c
6874
#include <stdlib.h>
@@ -86,6 +92,12 @@ posix_memalign(void **memptr, size_t alignment, size_t size)
8692
}
8793
```
8894
95+
Finally, add the following line to `prj.conf` so that the output of `print()` statements is sent to stdout:
96+
97+
```conf
98+
CONFIG_STDOUT_CONSOLE=y
99+
```
100+
89101
### CMakeLists.txt Setup
90102

91103
The `CMakeLists.txt` setup is more involved and complex since target, compilation flags, and library linking must be specified for Swift. First, some initial setup and flags:
@@ -101,11 +113,11 @@ set(CMAKE_Swift_COMPILATION_MODE wholemodule)
101113
project(SwiftZephyrProject Swift)
102114
```
103115

104-
The following flags have been curated to work well with the `armv7em-none-none-eabi` target with `swiftc`. Some flags may need to change depending on the chosen target:
116+
Next, set the compiler target to the arch you are building for. For this example we use `armv6m-none-none-eabi` which is compatible with the [Cortex-M0](https://docs.zephyrproject.org/latest/boards/qemu/cortex_m0/doc/index.html) which we will compile for in a later step. The `mfloat-abi=soft`, `-fshort-enums`, and `-fno-pic` flags are specifically for 32-bit arm architectures, so for other architectures they can be removed. However, the other flags and required for building Swift for Embedded and against Zephyr:
105117

106118
```cmake
107-
# Use the armv7em-none-none-eabi target triple for Swift
108-
set(CMAKE_Swift_COMPILER_TARGET armv7em-none-none-eabi)
119+
# Use the armv6m-none-none-eabi target triple for Swift
120+
set(CMAKE_Swift_COMPILER_TARGET armv6m-none-none-eabi)
109121
110122
# Set global Swift compiler flags
111123
add_compile_options(
@@ -176,3 +188,122 @@ target_include_directories(app_swift PRIVATE
176188
# Link the Swift target into the primary target
177189
target_link_libraries(app PRIVATE app_swift)
178190
```
191+
192+
### Building and Running
193+
194+
To build the project, ensure that the Zephyr workspace is sourced first:
195+
196+
```bash
197+
source ~/zephyrproject/.venv/bin/activate
198+
```
199+
200+
Run the following command to configure the project with CMake:
201+
202+
```console
203+
(.venv)> cmake -B build -G Ninja -DBOARD=qemu_cortex_m0 -DUSE_CCACHE=0 .
204+
Loading Zephyr default modules (Zephyr base (cached)).
205+
...
206+
-- Configuring done (7.6s)
207+
-- Generating done (0.2s)
208+
-- Build files have been written to: ~/SwiftZephyrProject/build
209+
```
210+
211+
Then, the project can be built using `cmake --build`:
212+
213+
```console
214+
(.venv)> cmake --build build
215+
[1/135] Preparing syscall dependency handling
216+
217+
[2/135] Generating include/generated/zephyr/version.h
218+
-- Zephyr version: 4.1.0 (~/zephyrproject/zephyr), build: v4.1.0
219+
[130/135] Linking C executable zephyr/zephyr_pre0.elf
220+
~/zephyr-sdk-0.17.0/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld.bfd: warning: orphan section `.swift_modhash' from `app/libapp.a(Main.swift.obj)' being placed in section `.swift_modhash'
221+
[135/135] Linking C executable zephyr/zephyr.elf
222+
~/zephyr-sdk-0.17.0/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld.bfd: warning: orphan section `.swift_modhash' from `app/libapp.a(Main.swift.obj)' being placed in section `.swift_modhash'
223+
Memory region Used Size Region Size %age Used
224+
FLASH: 14674 B 256 KB 5.60%
225+
RAM: 4032 B 16 KB 24.61%
226+
IDT_LIST: 0 GB 32 KB 0.00%
227+
Generating files from ~/SwiftZephyrProject/build/zephyr/zephyr.elf for board: qemu_cortex_m0
228+
```
229+
230+
Finally, to run the example in the qemu emulator, use `ninja run`:
231+
232+
```console
233+
(.venv)> ninja -C build run
234+
ninja: Entering directory `build'
235+
[0/1] To exit from QEMU enter: 'CTRL+a, x'[QEMU] CPU: cortex-m0
236+
*** Booting Zephyr OS build v4.1.0 ***
237+
Hello Zephyr from Swift!
238+
Loop
239+
Loop
240+
Loop
241+
```
242+
243+
Congrats, you now have a Swift project running using Zephyr!
244+
245+
## West Integration
246+
247+
Up to now we have setup a project that works perfectly fine when used with just CMake and Ninja. However, projects can also be integrated with West, which is the official CLI tool used for Zephyr projects. To use `west`, start by adding a `west.yml` file to the root of the project:
248+
249+
```yml
250+
manifest:
251+
remotes:
252+
- name: zephyrproject-rtos
253+
url-base: https://github.com/zephyrproject-rtos
254+
255+
projects:
256+
- name: zephyr
257+
remote: zephyrproject-rtos
258+
revision: v4.1.0
259+
import:
260+
name-allowlist:
261+
- cmsis # required by the ARM port
262+
```
263+
264+
It is recommended to set the `revision` to a tagged version of Zephyr instead of always getting the main revision, which could have changing APIs.
265+
266+
Next, set the `ZEPHYR_BASE` environment variable to tell `west` where the Zephyr workspace is located:
267+
268+
```bash
269+
(.venv)> export ZEPHYR_BASE=~/zephyrproject/zephyr
270+
```
271+
272+
This could even be set as a global env variable for the user in `~/.bashrc` or `~/.zshrc` if desired.
273+
274+
With this, `west` commands now can be run instead of having to use `cmake` and `ninja` to build and run:
275+
276+
```bash
277+
(.venv)> west build -b qemu_cortex_m0 . -p always
278+
...
279+
(.venv)> west build -t run
280+
-- west build: running target run
281+
[0/1] To exit from QEMU enter: 'CTRL+a, x'[QEMU] CPU: cortex-m0
282+
*** Booting Zephyr OS build v4.1.0 ***
283+
Hello Zephyr from Swift!
284+
Loop
285+
Loop
286+
Loop
287+
Loop
288+
```
289+
290+
This setup may also desirable since `west flash` is also available and can be used instead of invoking the flashing tools manually.
291+
292+
If compiling a firmware for a real/physical board such as the `nrf52840dk/nrf52840`, `west flash` will work if the SEGGER J-Link host tools are installed. As an example, with the [nrfx-blink-sdk](../../../../nrfx-blink-sdk/) project:
293+
294+
```console
295+
> cd nrfx-blink-sdk
296+
> source ~/zephyrproject/.venv/bin/activate
297+
(.venv)> export ZEPHYR_BASE=~/zephyrproject/zephyr
298+
(.venv)> west build -b nrf52840dk/nrf52840 . -p always
299+
...
300+
(.venv)> west flash -r jlink
301+
-- west flash: rebuilding
302+
ninja: no work to do.
303+
-- west flash: using runner jlink
304+
-- runners.jlink: reset after flashing requested
305+
-- runners.jlink: JLink version: 8.26
306+
-- runners.jlink: Flashing file: ~/swift-embedded-examples/nrfx-blink-sdk/build/zephyr/zephyr.hex
307+
```
308+
309+
The `-r jlink` param is needed for this example to use the J-Link tools instead of using `nrfjprog`, which is the default for this board and also [deprecated](https://www.nordicsemi.com/Products/Development-tools/nRF-Command-Line-Tools).

0 commit comments

Comments
 (0)