From 7d693da6be518a0b5ead3a037e0a3c5e59e82fb9 Mon Sep 17 00:00:00 2001 From: "Jesse L. Zamora" Date: Tue, 3 Jun 2025 07:48:35 -0400 Subject: [PATCH 1/4] Update architectures and flags for Zephyr guide --- .../SDKSupport/IntegrateWithZephyr.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md index 59a55bed..9e8a0d00 100644 --- a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md +++ b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md @@ -12,8 +12,9 @@ Zephyr [supports quite a few target architectures](https://docs.zephyrproject.or | Architecture | Details | Swift Triple | |--------------|---------------------|-------------------------| -| ARMv6-M | Cortex M0, M1, M3 | armv6m-none-none-eabi | -| ARMv7-M | Cortex M4, M7 | armv7em-none-none-eabi | +| ARMv6-M | Cortex M0, M0+, M1 | armv6m-none-none-eabi | +| ARMv7-M | Cortex M3 | armv7-none-none-eabi | +| ARMv7-EM | Cortex M4/M4F, M7 | armv7em-none-none-eabi | | ARMv8-M | Cortex M23-85 | aarch64-none-none-elf | | Intel | 32-bit (i686) | i686-unknown-none-elf | | Intel | 64-bit (x86_64) | x86_64-unknown-none-elf | @@ -134,7 +135,10 @@ Next, set the compiler target to the arch you are building for. For this example set(CMAKE_Swift_COMPILER_TARGET armv6m-none-none-eabi) ``` -After setting the target triple, some additional additional Swift compiler flags need to be defined: +After setting the target triple, some additional additional Swift compiler flags need to be defined. +Please note that the `-mfloat-abi=soft` flag may need to change to `-mfloat-abi=hard` for ARM CPUs +that support hard-float, such as the Cortex-M4F and Cortex-M7. This and the `-fshort-enums` flags +should not be required for non-ARM architectures such as Intel and RISC-V. ```cmake # Set global Swift compiler flags @@ -145,6 +149,12 @@ add_compile_options( # Enable function sections to enable dead code stripping on elf "$<$:SHELL:-Xfrontend -function-sections>" + # Use software floating point operations matching GCC + "$<$:SHELL:-Xcc -mfloat-abi=soft>" + + # Use compacted C enums matching GCC + "$<$:SHELL:-Xcc -fshort-enums>" + # Disable PIC "$<$:SHELL:-Xcc -fno-pic>" @@ -153,7 +163,7 @@ add_compile_options( ) ``` -There are quite a few other Zephyr flags that must also be imported in order to get Zephyr include paths and flags such `-mcpu`, `-mfloat-abi`, and so on: +There are quite a few other Zephyr flags that must also be imported in order to get Zephyr include paths and flags such `-mcpu`, `mthumb`, `-mabi`, and so on: ```cmake # Import TOOLCHAIN_C_FLAGS from Zephyr as -Xcc flags From 37085035753de8232edafcb406e8a8bca07cfa96 Mon Sep 17 00:00:00 2001 From: "Jesse L. Zamora" Date: Sat, 7 Jun 2025 12:56:18 -0400 Subject: [PATCH 2/4] Added back picolibc include dir, added more info --- .../SDKSupport/IntegrateWithZephyr.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md index 9e8a0d00..0080219a 100644 --- a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md +++ b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md @@ -2,11 +2,13 @@ Integrating Swift with Zephyr RTOS for embedded systems development +[Zephyr](https://www.zephyrproject.org/) is an open-source RTOS for embedded systems that is sponsored by the Linux Foundation. Since it depends on CMake primarily for its build system, it can easily be integrated to be used with Embedded Swift. + 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](https://github.com/apple/swift-embedded-examples/tree/main/nrfx-blink-sdk) project that is compatible with nRF or other boards. > Note: Embedded Swift is experimental. Public releases of Swift do not support Embedded Swift, yet. See for details. -## Zephyr Target Architecture Compatibility +## Target Architecture Compatibility Zephyr [supports quite a few target architectures](https://docs.zephyrproject.org/latest/introduction/index.html), but not all are supported by Embedded Swift. Please refer to the following table for an overview of Zephyr-supported architectures that are supported by Swift, along with the correct target triple to use: @@ -136,9 +138,6 @@ set(CMAKE_Swift_COMPILER_TARGET armv6m-none-none-eabi) ``` After setting the target triple, some additional additional Swift compiler flags need to be defined. -Please note that the `-mfloat-abi=soft` flag may need to change to `-mfloat-abi=hard` for ARM CPUs -that support hard-float, such as the Cortex-M4F and Cortex-M7. This and the `-fshort-enums` flags -should not be required for non-ARM architectures such as Intel and RISC-V. ```cmake # Set global Swift compiler flags @@ -160,10 +159,15 @@ add_compile_options( # Disable PIE "$<$:SHELL:-Xcc -fno-pie>" + + # Add Libc include paths + "$<$:SHELL:-Xcc -I -Xcc ${ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi/picolibc/include>" ) ``` -There are quite a few other Zephyr flags that must also be imported in order to get Zephyr include paths and flags such `-mcpu`, `mthumb`, `-mabi`, and so on: +- NOTE: The `-mfloat-abi=soft` flag may need to change to `-mfloat-abi=hard` for ARM CPUs that support hard-float, such as the Cortex-M4F and Cortex-M7. This and the `-fshort-enums` flags are not required for non-ARM architectures such as Intel and RISC-V. + +There are quite a few other Zephyr flags that can also be imported (optional) in order to get Zephyr include paths and flags such `-mcpu`, `mthumb`, `-mabi`, and so on: ```cmake # Import TOOLCHAIN_C_FLAGS from Zephyr as -Xcc flags @@ -299,7 +303,8 @@ manifest: - cmsis # required by the ARM port ``` -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. +- 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. +- Also, please note that depending on what architecture you are targeting, you may need to add more/different targets to the `name-allowlist`, which is useful to get needed dependencies when compiling a project from a CI. See the [Zephyr workflow from swift-embedded-examples](https://github.com/swiftlang/swift-embedded-examples/blob/main/.github/workflows/build-zephyr.yml) for an example of setting up a CI for Zephyr. Next, set the `ZEPHYR_BASE` environment variable to tell `west` where the Zephyr workspace is located: @@ -345,3 +350,4 @@ ninja: no work to do. ``` 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). + From 393545926a85506087db29b6d29aa795cac974ee Mon Sep 17 00:00:00 2001 From: "Jesse L. Zamora" Date: Sun, 8 Jun 2025 21:33:32 -0400 Subject: [PATCH 3/4] Add more information on linking customizations --- .../SDKSupport/IntegrateWithZephyr.md | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md index 0080219a..fe9f1ed8 100644 --- a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md +++ b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md @@ -351,3 +351,75 @@ ninja: no work to do. 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). +## Customizing the Linker + +The default linker configuration for building a Zephyr project from CMake works well for simple projects, but it can be customized as needed. The following sections show off some useful ways to customize linking Zephyr projects for Swift. + +### Stripping Out Unused Sections + +When compiling Swift to Zephyr projects, you may see some warnings about orphaned sections from the linker, like `.swift_modhash`: + +```console +~/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' +[135/135] Linking C executable zephyr/zephyr.elf +~/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 +``` + +These types of warnings can be suppressed by passing a custom linker script to Zephyr that discards the sections, especially if they are not needed. For example, a script called `sections.ld` can be created at the root of the project with the following contents: + +```ld +/DISCARD/ : { *(.swift_modhash*) } +/DISCARD/ : { *(.ARM.attributes*) *(.ARM.exidx) } +``` + +Then, in `CMakeLists.txt`, add the following line: + +```cmake +# Remove unused sections +zephyr_linker_sources(SECTIONS "sections.ld") +``` + +This can also help to reduce the size of the output elf/binary since unused sections are stripped out. Be careful what sections you strip out, however, as some sections may be required. + +### Linking Swift Libraries + +This example adds the `swiftUnicodeDataTables` library from Swift to be linked into the Zephyr project. This is useful for linking unicode symbols when using strings. See for more information on this. + +In order to add additional linker params, the CMake `target_link_libraries` invocation can be used against `zephyr_pre0` and `zephyr_final`, like this: + +```cmake +# The code is using a String as a Dictionary key and thus require linking with libswiftUnicodeDataTables.a +# We compute the path where this file reside, taking into accout how the toolchain is referenced (Swiftly or TOOLCHAINS env variable). +find_program(SWIFTLY "swiftly") +IF(SWIFTLY) + execute_process(COMMAND swiftly use --print-location OUTPUT_VARIABLE toolchain_path) + cmake_path(SET additional_lib_path NORMALIZE "${toolchain_path}/usr/lib/swift/embedded/${CMAKE_Swift_COMPILER_TARGET}") +ELSE() + get_filename_component(compiler_bin_dir ${CMAKE_Swift_COMPILER} DIRECTORY) + cmake_path(SET additional_lib_path NORMALIZE "${compiler_bin_dir}/../lib/swift/embedded/${CMAKE_Swift_COMPILER_TARGET}") +ENDIF() + +target_link_directories(zephyr_pre0 PRIVATE "${additional_lib_path}") +target_link_libraries(zephyr_pre0 + -Wl,--whole-archive + swiftUnicodeDataTables + -Wl,--no-whole-archive + ) + +target_link_directories(zephyr_final PRIVATE "${additional_lib_path}") +target_link_libraries(zephyr_final + -Wl,--whole-archive + swiftUnicodeDataTables + -Wl,--no-whole-archive + ) +``` + +Extra code is required to find the right paths where the `swiftUnicodeDataTables.a` file is located, depending on how Swift is installed. + +When this is built, depending on the target architecture, warnings may then be printed about 32-bit enums, like this: + +```console +~/zephyr-sdk-0.17.0/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld.bfd: warning: ~/.local/share/swiftly/toolchains/6.1.0/usr/lib/swift/embedded/armv6m-none-none-eabi/libswiftUnicodeDataTables.a(UnicodeWord.cpp.o) uses 32-bit enums yet the output is to use variable-size enums; use of enum values across objects may fail +``` + +To suppress these, simply add `-Wl,--no-enum-size-warning` to the `target_link_libraries` invocations. From 3139ef7a171a906f427093c6e246fde457d83a62 Mon Sep 17 00:00:00 2001 From: "Jesse L. Zamora" Date: Sun, 8 Jun 2025 21:36:02 -0400 Subject: [PATCH 4/4] Change title of IntegrateWithZephyr doc --- .../Documentation.docc/SDKSupport/IntegrateWithZephyr.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md index fe9f1ed8..8acae0c9 100644 --- a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md +++ b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithZephyr.md @@ -1,4 +1,4 @@ -# Integrating with Zephyr +# Zephyr RTOS SDK Integrating Swift with Zephyr RTOS for embedded systems development