diff --git a/Sources/EmbeddedSwift/Documentation.docc/CompilerDetails/ABI.md b/Sources/EmbeddedSwift/Documentation.docc/CompilerDetails/ABI.md index dfb2c89..54aee6a 100644 --- a/Sources/EmbeddedSwift/Documentation.docc/CompilerDetails/ABI.md +++ b/Sources/EmbeddedSwift/Documentation.docc/CompilerDetails/ABI.md @@ -30,7 +30,7 @@ The layout of Embedded Swift's class metadata is *different* from full Swift: - The **destructor pointer** is stored at **offset 1**. This function is invoked by Swift's deallocator when the class instance is destroyed. - The **ivar destroyer** is stored at **offset 2**. This function is invoked to destroy instance members when creation of the object is cancelled (e.g. in a failable initializer). - Lastly, the **vtable** is stored at **offset 3**: For each Swift class in the class's inheritance hierarchy, in order starting - from the root class and working down to the most derived class, the function pointers to the implementation of every method of the class in declaration order in stored. + from the root class and working down to the most derived class, the function pointers to the implementation of every method of the class in declaration order is stored. ### Witness Tables ABI diff --git a/Sources/EmbeddedSwift/Documentation.docc/CompilerDetails/Status.md b/Sources/EmbeddedSwift/Documentation.docc/CompilerDetails/Status.md index 96f9286..a1d156f 100644 --- a/Sources/EmbeddedSwift/Documentation.docc/CompilerDetails/Status.md +++ b/Sources/EmbeddedSwift/Documentation.docc/CompilerDetails/Status.md @@ -16,7 +16,7 @@ Implementation status of compiler and language features in Embedded Swift, compa | Metatypes | No, currently only allowed as unused arguments (type hints) | | Untyped throwing | No, intentionally unsupported long-term (typed throwing should be used instead) | | Weak references, unowned references | No | -| Non-final generic class methods | No, intentionally unsupported long-term, see <[Embedded Swift -- Non-final generic methods](NonFinalGenericMethods.md)>| +| Non-final generic class methods | No, intentionally unsupported long-term, see | | Parameter packs (variadic generics) | No, not yet supported | ## Embedded Standard Library Breakdown diff --git a/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/Introduction.md b/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/Introduction.md index 981e0cf..15d6921 100644 --- a/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/Introduction.md +++ b/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/Introduction.md @@ -17,10 +17,13 @@ Regular Swift is not a good fit for small constrained environments like microcon - Using compile-time specialization (monomorphization) for generic code - Minimizing dependencies on external libraries +It's also a good mental model to think of the Swift compiler in Embedded Swift mode as operating on a way a *traditional C compiler* does — specifically in the sense that the compiler produces an object file that does not call into or depend on symbols that are not explicitly used in the source code. This is achieved even for code that uses generics, protocols, tuples, arrays, and more — all the higher-level language features are "compiled out" (e.g. generics are specialized), and standard library code is pulled into the object file as needed (e.g. array implementation). + This results in properties that are a great fit for embedded software development: - **Small binaries** that can be as tiny as a few hundred bytes for "Hello World"-like programs (fully self-contained). -- **No hidden runtime costs** – Embedded Swift's runtime library does not manage any data structures behind your back, is itself less than a kilobyte in size, and it eligible to be removed if unused. +- **No hidden runtime costs** – Embedded Swift's runtime library does not manage any data structures behind your back, is itself less than a kilobyte in size, and is eligible to be removed if unused. +- **No hidden allocations** which would cause unpredictable performance cliffs. - **Full C/C++ interoperability** to directly interact with existing C libraries and hardware-specific code, making it easy to integrate with vendor SDKs. - **Modern language features** like optionals, generics, and strong type safety are all available in Embedded Swift. - **Full safety of Swift** is retained in Embedded Swift. @@ -38,7 +41,7 @@ For a detailed introduction and motivation into Embedded Swift, please see "[A V The Swift toolchain has the ability to produce code for almost any standard ARM and RISC-V platform, and that makes Embedded Swift versatile and not limited to specific platforms or hardware devices. This way, Embedded Swift can potentially target many different microcontroller families and embedded devices. -Boards with active community support include the Raspberry Pi Pico, various STM32 development boards, and several ESP32 variants, with more platforms being regularly added as the community grows. +Boards with active community support include the Raspberry Pi Pico, various STM32 development boards, various nRF52840 based boards and several ESP32 variants, with more platforms being regularly added as the community grows. ## Interoperability with existing SDKs diff --git a/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/LanguageSubset.md b/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/LanguageSubset.md index 9cd1bf7..1120fbb 100644 --- a/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/LanguageSubset.md +++ b/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/LanguageSubset.md @@ -14,9 +14,10 @@ Note that there are no behavior changes in Embedded Swift compared to full Swift - **Not available**: Values of protocol types ("existentials"), unless the protocol is restricted to be class-bound (derived from AnyObject). E.g. `let a: Hashable = ...` is not allowed. `Any` is also not allowed. See for details and alternatives of existentials. - **Not available**: Throwing errors or `any Error` type (in contrast with "typed throws", which *is* supported in Embedded Swift). - **Not available**: Metatypes, e.g. `let t = SomeClass.Type` or `type(of: value)` are not allowed. +- **Not available**: Standard library types that rely on the above, for example `Codable` and `KeyPath`, are not allowed. - **Not available**: Printing and stringification of arbitrary types (which is achieved via reflection in desktop Swift). - **Not available**: Using non-final generic class methods. See for details on this. -- **Not available**: Weak and unowned references. +- **Not available**: Weak and unowned references are not allowed (unsafe unowned references *are* available). ## Compilation facilities that are not available @@ -26,4 +27,4 @@ Note that there are no behavior changes in Embedded Swift compared to full Swift ## Further resources -The above lists are describing features that are removed from Embedded Swift *by design*. Since Embedded Swift is currently an experimental preview, there might also be features that are not yet implemented. See the in-development status at [Embedded Swift -- Status](EmbeddedSwiftStatus.md). +The above lists are describing features that are removed from Embedded Swift *by design*. Since Embedded Swift is currently an experimental preview, there might also be features that are not yet implemented. See the in-development status at . diff --git a/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/PicoGuide.md b/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/PicoGuide.md index 45ccb62..002c8a1 100644 --- a/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/PicoGuide.md +++ b/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/PicoGuide.md @@ -6,13 +6,11 @@ In this guide we'll be targeting a Raspberry Pi Pico as the embedded device that ## Installing Swift -If you don’t have Swift installed, [install it first](https://www.swift.org/install). Because Embedded Swift is experimental and only available in preview toolchains, make sure to install the "Development Snapshot" toolchain (main) instead of a release toolchain (6.0). If you're using a macOS machine, you will need to make sure the installed toolchain is selected as active e.g. by exporting the `TOOLCHAINS` environment variable: +> Warning: Embedded Swift is experimental. Use the latest downloadable 'Trunk Development' snapshot from swift.org to use Embedded Swift. Public releases of Swift do not yet support Embedded Swift. -```shell -$ export TOOLCHAINS=org.swift.59202405011a -``` +To install Swift for embedded development, follow the instructions in , which guides you through using `swiftly` to install the latest development snapshot with Embedded Swift support. -To test that you have Swift installed, run `swift --version` from your shell or terminal app. It should say "6.0-dev", meaning you have a "Development Snapshot" toolchain. +To test that you have Swift installed, run `swift --version` from your shell or terminal app. It should say "6.2-dev" or similar, confirming you have a "Development Snapshot" toolchain. ## Installing dependencies for embedded development @@ -25,7 +23,7 @@ $ export PICO_SDK_PATH=... # location to your Pico SDK $ export PICO_TOOLCHAIN_PATH=... # location to the Arm Embedded Toolchain ``` -If you have the Wi-Fi enabled Pico W board instead of the regular Pico, note that you will need a slightly different setup described in the [Pico W example project](https://github.com/apple/swift-embedded-examples/tree/main/pico-w-blink-sdk), and just specifying `PICO_BOARD=pico_w` is not going to work. +If you have the Wi-Fi enabled Pico W board instead of the regular Pico, note that you will need a slightly different setup described in the [Pico W example project](https://github.com/apple/swift-embedded-examples/tree/main/rpi-picow-blink-sdk), and just specifying `PICO_BOARD=pico_w` is not going to work. Install [CMake 3.29](https://cmake.org/) or newer. @@ -33,7 +31,7 @@ To test that you have all the necessary parts installed, you can run the followi ```shell $ swift --version -Apple Swift version 6.0-dev (LLVM b66077aefd3be08, Swift 84d36181a762913) +Apple Swift version 6.2-dev (LLVM 81ab6d9f7e4810f, Swift 9cc1947527bacea) $ cmake --version cmake version 3.29.2 $ echo $PICO_BOARD @@ -50,8 +48,8 @@ bin/ libexec/ ## Building a "blinky" embedded app -The standard "Hello, World" in embedded development is a program that repeatedly blinks an LED. Let's build one. The following setup can be also found in [swift-embedded-examples](https://github.com/apple/swift-embedded-examples/blob/main/pico-blink-sdk/README.md), but we're going to show below that all you need is just three files. -Let's create a new empty directory and prepare a simple structure for a CMake-based project that can be used on top the Pico SDK: +The standard "Hello, World" in embedded development is a program that repeatedly blinks an LED. Let's build one. The following setup can be also found in [swift-embedded-examples](https://github.com/apple/swift-embedded-examples/blob/main/rpi-pico-blink-sdk/README.md), but we're going to show below that all you need is just three files. +Let's create a new empty directory and prepare a simple structure for a CMake-based project that can be used on top of the Pico SDK: ``` embedded-swift-tutorial diff --git a/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/STM32BaremetalGuide.md b/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/STM32BaremetalGuide.md index 95d7fd7..c80b19e 100644 --- a/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/STM32BaremetalGuide.md +++ b/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/STM32BaremetalGuide.md @@ -350,8 +350,14 @@ $ brew install stlink $ st-info --probe ... TODO $ brew install minicom -$ minicom -... TODO +$ minicom --version +minicom version 2.10 (compiled Feb 22 2025) +Copyright (C) Miquel van Smoorenburg. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version +2 of the License, or (at your option) any later version. ``` Then let's fetch the elf2hex tool: diff --git a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/Baremetal.md b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/Baremetal.md index d5e9766..bb91bbb 100644 --- a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/Baremetal.md +++ b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/Baremetal.md @@ -1,3 +1,244 @@ # Baremetal use of Embedded Swift -🚧 Under construction... +Programming without an SDK for maximum control and minimal size + +## Overview + +Developing in "baremetal mode" means programming directly for the hardware without any operating system or SDK abstractions. This provides maximum control and minimum codesize, but requires deeper understanding of the hardware. + +Embedded Swift supports true baremetal development, where you directly program hardware peripherals by manipulating memory-mapped registers. This approach is suitable for: + +- Extremely resource-constrained environments +- Safety-critical applications that need deterministic behavior +- Projects requiring full control over every aspect of the hardware +- Educational purposes to understand how hardware and software interact + +## Key components of a baremetal project + +A complete baremetal project typically includes: + +1. **Startup code** - Sets up the initial environment before `main()` runs +2. **Interrupt vector table** - Maps hardware events to handler functions +3. **Linker script** - Defines memory layout and sections +4. **Hardware register definition code** - To interface with peripherals +5. **Runtime support** - E.g. implementations of functions like `memcpy` and `malloc` +6. **Application logic** - Your actual embedded application code + +For a full working example of all these components, see . The rest of this document provides general platform-independent guidance when working in baremetal mode. However, much of the problem space of baremetal development is outside of the scope of this documentation, and requires deeper familiary with your specific setup. This information is typically provided by your board vendor, the spec of the MCU, the ISA spec of the execution core, the C toolchain documentation, ELF file format spec, and other similar sources. + +## Hardware access patterns + +### 1. Direct memory access using pointers + +Note that using UnsafePointers to directly access registers at known addresses is not recommended in almost any situation because doing that correctly is tricky, it's inherently unsafe (and shifts the safety responsibility to the user) and can easily cause very hard to debug runtime problems. However, sometimes it might be neccessary to use this method. + +One common issue when directly accessing hardware registers is that the compiler may optimize away repeated reads or writes, thinking they're redundant. This is a problem that's inherent to pointers in most programming languages (including C and C++). + +```swift +// Accessing a register at address 0x40010000 +let gpioBase = 0x40010000 + +// ❌ Do not do this - the memory write might be optimized out +let gpioDataRegister = UnsafeMutablePointer(bitPattern: gpioBase)! +gpioDataRegister.pointee |= (1 << 5) // Set bit 5 +``` + +Hardware registers are volatile - their values can change independently of your program's execution (due to hardware events, interrupts, or peripheral operation). To ensure correct behavior, you must inform the compiler that these memory locations are volatile, preventing unwanted optimizations: + +```swift +// Need to use these flags: -enable-experimental-feature Volatile +import _Volatile + +// ✅ Use VolatileMappedRegister for volatile semantics +let gpioBase: UInt = 0x40010000 +let gpioDataRegister = VolatileMappedRegister(unsafeBitPattern: gpioBase) +... = gpioDataRegister.load() +gpioDataRegister.store(1 << 5) +``` + +Whenever possible, consider using Swift MMIO (see below) which does also provide proper volatile semantics, but more importantly provides type safety on individual registers and their fields. + +### 2. Using Swift MMIO for type-safe register access + +Swift MMIO provides strongly-typed access to memory-mapped hardware and can automatically generate register definitions from SVD files. It can provide a higher-level type-safe access to hardware registers, for example: + +```swift +// Type-safe register access +gpioa.odr.write { $0.odr5 = true } // Set pin 5 high +``` + +See [Swift MMIO](https://github.com/apple/swift-mmio/) for details and for a guided example of using it. + +## Creating a linker script and data segment relocation + +A baremetal project requires a custom linker script to properly place code and data in memory. This is a relatively complex task to get right, and requires understanding of the memory map, flash and RAM setup of your target device, as well as understanding the ELF file format and what code/data sections do you expect your entire program to use. + +Besides just defining the position of code at runtime, a linker script needs to also: +- Handle and coordinate the initialization of "zero-fill" global variables (aka the BSS section) +- Handle and coordinate the initialization of non-zero writable global variables (copying initial values from flash to RAM) + +Here's an incomplete sketch of an example linker script: + +``` +MEMORY +{ + flash (rx) : ORIGIN = 0x08000000, LENGTH = 1024K + sram (rwx) : ORIGIN = 0x20000000, LENGTH = 320K +} + +SECTIONS +{ + .text : { *(.vectors*) ; *(.text*) } > flash + .rodata : { *(.rodata*) ; *(.got*) } > flash + .bss : { *(.bss*) } > sram ; needs runtime handling + .data : { *(.data*) } > sram AT>flash ; needs runtime handling + + ... +} +``` + +A sketch of an example corresponding startup code (in C): + +```c +void ResetISR(void) { + // Initialize bss section + uint8_t *bss = &__bss_start; + while (bss < &__bss_end) *bss = 0; + + // Initialize read-write data section + extern uint8_t __data_start_flash, __data_start, __data_end; + uint8_t *src = &__data_start_flash; + uint8_t *dst = &__data_start; + while (dst < &__data_end) *dst++ = *src++; + + // Call main + extern int main(void); + main(); + + // If main returns, loop forever + while(1); +} +``` + +Both these code snippets are not fully functional, they are only demonstrating the complexity of what the linker script and startup code need to do to initialize global variables. + +Tip: If this handling is not done correctly, a typical symptom is that global variables "don't work", i.e. reading from them doesn't yield the right value, and writing to them doesn't persist. A good way to double check this is by using a debugger, dumping memory at runtime and checking if it matches the virtual memory layout of the ELF file. + +## Vector table and interrupts + +The vector table is a critical component that maps hardware interrupts and exceptions to specific handler functions in your code. It's typically placed at the beginning of flash memory and contains function pointers that the processor uses when responding to various events. + +The processor automatically jumps to the appropriate handler when an interrupt occurs by indexing into this table. If you don't provide a specific handler, it's common to point to a default handler that can help with debugging. + +Example vector table structure: + +```c +// Vector table for ARM Cortex-M +__attribute__((section(".vectors"))) const void *VectorTable[] = { + (void*)0x20008000, // Initial stack pointer + ResetISR, // Reset handler + DefaultHandler, // NMI handler + DefaultHandler, // Hard fault handler + // Additional vectors as needed +}; +``` + +If you want to actually handle an interrupt (e.g. a GPIO or UART interrupt) in your Swift code, you can forward declare the function in C, and define it using `@cdecl` in Swift: + +```c +// In startup.c or header file +void UART1_IRQHandler(void); +``` + +```swift +// In Swift code +@_cdecl("UART1_IRQHandler") +func uartInterruptHandler() { + // Handle UART interrupt in Swift + // Clear interrupt flags, process received data, etc. +} +``` + +However, note that Swift currently does not provide any form of synchronization or "interrupt safety" for the code that executes the interrupt. Namely, if your interrupt handler modifies global variables that are also accessed by your main program, you need to be careful about data races and ensure proper synchronization (such as using atomic operations or disabling interrupts during critical sections). Additionally, interrupt handlers should be kept short and fast to avoid blocking other important system events. + +## Building a minimal project + +To build an Embedded Swift baremetal project with SwiftPM, you will need a setup like this: + +- Your main application target defined in Package.swift. +- A helper C code helper target defined in Package.swift - this will contain your C startup code, vector table and possibly an assembly file. +- Invoke `swift build` with a `--triple` argument that specifies the target CPU architecture and output object file format. +- Use a `toolset.json` file that defines the common Swift and C compilation flags, and linking flags. This will e.g. enable the Embedded Swift mode when compiling Swift code, and point the linker at the right linker script. + +Example file structure: + +``` +MyBaremetalProject/ +├── Package.swift +├── toolset.json +├── Sources/ +│ ├── MyApp/ +│ │ └── main.swift +│ └── CStartup/ +│ ├── startup.c +│ ├── linker.ld +│ └── include/ +│ └── startup.h +└── README.md +``` + +Example toolset.json file: + +```json +{ + "schemaVersion": "1.0", + "swiftCompiler": { + "extraCLIOptions": [ + "-enable-experimental-feature", "Embedded", + "-Xclang-linker", "-nostdlib", + ] + }, + "linker": { + "extraCLIOptions": [ + "-T", "Sources/CStartup/linker.ld", + "--gc-sections", + ] + } +} +``` + +Example Package.swift file: + +```swift +// swift-tools-version: 5.9 +import PackageDescription + +let package = Package( + name: "MyBaremetalProject", + products: [ + .executable( + name: "MyBaremetalApp", + targets: ["MyApp"] + ) + ], + targets: [ + .executableTarget( + name: "MyApp", + dependencies: ["CStartup"], + swiftSettings: [ + .enableExperimentalFeature("Embedded") + ] + ), + .target( + name: "CStartup", + publicHeadersPath: "include" + ) + ] +) +``` + +Example compilation invocation: + +```bash +swift build --triple armv7em-none-eabi --toolset toolset.json +``` diff --git a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithPico.md b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithPico.md index 3ff9065..bec9dbc 100644 --- a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithPico.md +++ b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithPico.md @@ -6,12 +6,12 @@ Setting up a project that can seamlessly use C APIs from the Pico SDK. Development for [Raspberry Pi Pico and Pico W](https://www.raspberrypi.com/products/raspberry-pi-pico/) normally uses the [Pico SDK](https://github.com/raspberrypi/pico-sdk) and the vendor provides several [sample projects in the pico-examples repository](https://github.com/raspberrypi/pico-examples). The SDK and sample project setup is described in: -- https://www.raspberrypi.com/documentation/microcontrollers/c_sdk.html#sdk-setup -- https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf +- [https://www.raspberrypi.com/documentation/microcontrollers/c_sdk.html#sdk-setup](https://www.raspberrypi.com/documentation/microcontrollers/c_sdk.html#sdk-setup) +- [https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf](https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf) Before trying to use Swift with the Pico SDK, make sure your environment works and can build the provided C/C++ sample projects. -### CMake setup with a bridging header +## CMake setup with a bridging header The Pico SDK is using CMake as its build system, and so the simplest way to integrate with it is to also use CMake to build a Swift firmware application on top of the SDK and the libraries from it. The following describes an example set up of that on a "blinky" example (code that just blinks the built-in LED). @@ -50,42 +50,41 @@ Notice that we're using functions and variables defined in C in the Pico SDK. Fo #include "pico/stdlib.h" ``` -Finally, we need to define the application's build rules in CMake that will be using CMake logic from the Pico SDK. The following content of `CMakeLists.txt` shows how to *manually call swiftc, the Swift compiler* instead of using the recently added CMake native support for Swift, so that we can see the full Swift compilation command. +Finally, we need to define the application's build rules in CMake that will be using CMake logic from the Pico SDK. The following content of `CMakeLists.txt` leverages CMake 3.29's native Swift language support: ```cmake -cmake_minimum_required(VERSION 3.13) +cmake_minimum_required(VERSION 3.29) include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake) project(swift-blinky) pico_sdk_init() -execute_process(COMMAND xcrun -f swiftc OUTPUT_VARIABLE SWIFTC OUTPUT_STRIP_TRAILING_WHITESPACE) - -add_executable(swift-blinky) -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o - COMMAND - ${SWIFTC} - -target armv6m-none-none-eabi -Xcc -mfloat-abi=soft -Xcc -fshort-enums - -Xfrontend -function-sections -enable-experimental-feature Embedded -wmo -parse-as-library - $$\( echo '$' | tr '\;' '\\n' | sed -e 's/\\\(.*\\\)/-Xcc -I\\1/g' \) - $$\( echo '${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}' | tr ' ' '\\n' | sed -e 's/\\\(.*\\\)/-Xcc -I\\1/g' \) - -import-bridging-header ${CMAKE_CURRENT_LIST_DIR}/BridgingHeader.h - ${CMAKE_CURRENT_LIST_DIR}/Main.swift - -c -o ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o - DEPENDS - ${CMAKE_CURRENT_LIST_DIR}/BridgingHeader.h - ${CMAKE_CURRENT_LIST_DIR}/Main.swift -) -add_custom_target(swift-blinky-swiftcode DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o) + +# Enable Swift language support +enable_language(Swift) + +# Set Swift compilation mode to whole module optimization +set(CMAKE_Swift_COMPILATION_MODE wholemodule) + +add_executable(swift-blinky Main.swift) +set_target_properties(swift-blinky PROPERTIES + LINKER_LANGUAGE CXX) + +target_compile_options(swift-blinky PUBLIC "$<$:SHELL: + -enable-experimental-feature Embedded + -target armv6m-none-none-eabi -Xcc -mfloat-abi=soft -Xcc -fshort-enums + -Xfrontend -function-sections + -import-bridging-header ${CMAKE_CURRENT_LIST_DIR}/BridgingHeader.h +>") target_link_libraries(swift-blinky - pico_stdlib hardware_uart hardware_gpio - ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o + pico_stdlib hardware_uart hardware_gpio ) -add_dependencies(swift-blinky swift-blinky-swiftcode) + pico_add_extra_outputs(swift-blinky) ``` +## Configure and build + With these three files, we can now configure and build a Swift firmware for the Pico: ```bash @@ -94,7 +93,7 @@ $ export PICO_SDK_PATH= $ export PICO_TOOLCHAIN_PATH= $ ls -al -rw-r--r-- 1 kuba staff 39B Feb 2 22:08 BridgingHeader.h --rw-r--r-- 1 kuba staff 1.3K Feb 2 22:08 CMakeLists.txt +-rw-r--r-- 1 kuba staff 650B Feb 2 22:08 CMakeLists.txt -rw-r--r-- 1 kuba staff 262B Feb 2 22:08 Main.swift $ mkdir build $ cd build diff --git a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegratingWithPlatforms.md b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegratingWithPlatforms.md index ac43e34..2d14463 100644 --- a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegratingWithPlatforms.md +++ b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegratingWithPlatforms.md @@ -66,7 +66,7 @@ For detailed instructions on integrating with the Raspberry Pi Pico SDK, see . Note that only chips based on RISC-V architecture (e.g. ESP32-C3, ESP32-C6, ESP32-P4) are supported with Embedded Swift. The Xtensa ISA (used in e.g. ESP8266 or ESP32-S2 and ESP32-S3). +For ESP microcontrollers using the ESP-IDF framework, see . Note that only chips based on RISC-V architecture (e.g. ESP32-C3, ESP32-C6, ESP32-P4) are supported with Embedded Swift. The Xtensa ISA (used in e.g. ESP8266 or ESP32-S2 and ESP32-S3) is not supported. ### STM32