Создание встроенного приложения для микроконтроллера
Исходный код этого руководства можно найти на GitHub
В этом руководстве мы будем использовать Raspberry Pi Pico в качестве встроенного устройства, на котором будет выполняться наше приложение Swift. Если у вас его нет, не беспокойтесь! Вы все равно можете запустить приложение в онлайн-эмуляторе.
Установка Swift
Если Swift у вас не установлен, установите его сначала. Так как Embedded Swift экспериментальный и доступен только в предварительных инструментальных цепочках, убедитесь, что вы установили инструментальную цепочку «Development Snapshot» (main), а не релизную инструментальную цепочку (6.0). Если вы используете macOS, вам нужно убедиться, что Xcode установлен и выбран, выполнив xcode-select -p и проверив, что он указывает на путь установки Xcode. Далее, убедитесь, что установленная инструментальная цепочка разработки выбрана активной, например, путём экспорта переменной окружения TOOLCHAINS:
$ export TOOLCHAINS=org.swift.59202405011a
Чтобы проверить, что Swift установлен, выполните swift --version из вашей оболочки или приложения терминала. Должно отобразиться «6.0-dev», что означает, что у вас установлена инструментальная цепочка «Development Snapshot».
Установка зависимостей для разработки встроенных приложений
Установите Raspberry Pi Pico SDK и Arm Embedded Toolchain, следуя руководству Getting Started With Pico. Экспортируйте три переменные среды, чтобы они соответствовали вашей настройке и оборудованию:
$ export PICO_BOARD=pico
$ export PICO_SDK_PATH=... # location to your Pico SDK
$ export PICO_TOOLCHAIN_PATH=... # location to the Arm Embedded Toolchain
Если у вас есть плата Pico W с Wi-Fi вместо обычной Pico, обратите внимание, что вам потребуется немного другая настройка, описанная в примере проекта Pico W, и просто указание PICO_BOARD=pico_w не сработает.
Установите CMake 3.29 или более позднюю версию.
Чтобы проверить, что все необходимые части установлены, вы можете выполнить следующие команды в терминале:
$ swift --version
Apple Swift version 6.0-dev (LLVM b66077aefd3be08, Swift 84d36181a762913)
$ cmake --version
cmake version 3.29.2
$ echo $PICO_BOARD
pico
$ ls $PICO_SDK_PATH
CMakeLists.txt README.md external/ pico_sdk_version.cmake tools/
CONTRIBUTING.md cmake/ lib/ src/
LICENSE.TXT docs/ pico_sdk_init.cmake test/
$ ls $PICO_TOOLCHAIN_PATH
13.2.Rel1-darwin-arm64-arm-none-eabi-manifest.txt include/ share/
arm-none-eabi/ lib/
bin/ libexec/
Сборка приложения «blinky» для встроенной системы
Стандартное «Hello, World» во встроенной разработке — это программа, которая периодически мигает светодиодом. Давайте создадим такую. Следующую настройку также можно найти в swift-embedded-examples, но мы покажем ниже, что вам нужно всего три файла. Создайте новую пустую директорию и подготовьте простую структуру для проекта CMake, который может использоваться поверх Pico SDK:
embedded-swift-tutorial
├── BridgingHeader.h
├── CMakeLists.txt
└── Main.swift
Файлы Main.swift и BridgingHeader.h могут изначально содержать следующее основное содержимое:
// Main.swift
let led = UInt32(PICO_DEFAULT_LED_PIN)
gpio_init(led)
gpio_set_dir(led, /*out*/true)
while true {
gpio_put(led, true)
sleep_ms(250)
gpio_put(led, false)
sleep_ms(250)
}
// BridgingHeader.h
#include "pico/stdlib.h"Для сборки поверх поддержки CMake Pico SDK нам понадобится немного больше логики CMake в файле CMakeLists.txt:
# CMakeLists.txt
cmake_minimum_required(VERSION 3.29)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
set(CMAKE_Swift_COMPILATION_MODE wholemodule)
set(CMAKE_Swift_COMPILER_WORKS YES)
project(blinky)
pico_sdk_init()
enable_language(Swift)
add_executable(blinky Main.swift)
set_target_properties(blinky PROPERTIES LINKER_LANGUAGE CXX)
# Clear the default COMPILE_OPTIONS which include C specific compiler flags that the Swift compiler will not accept
# Instead, set those options to only apply when compiling C code.
set_target_properties(pico_standard_link PROPERTIES INTERFACE_COMPILE_OPTIONS "")
target_compile_options(pico_standard_link INTERFACE "$<$<COMPILE_LANGUAGE:C>:SHELL: -ffunction-sections -fdata-sections>")
set(SWIFT_INCLUDES)
foreach(dir ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES})
string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-Xcc ")
string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-I${dir} ")
endforeach()
target_compile_options(blinky PUBLIC "$<$<COMPILE_LANGUAGE:Swift>: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
${SWIFT_INCLUDES}
>")
target_link_libraries(blinky pico_stdlib hardware_uart hardware_gpio)
pico_add_extra_outputs(blinky)
Теперь мы готовы сконфигурировать и собрать этот микропрограммный код для Pico. Выполните следующие команды:
$ cmake -B build -G Ninja . # configure step
$ cmake --build build # build step
Сборка должна быть успешной и создать микропрограммный код в нескольких форматах (ELF, HEX, UF2), включая некоторые файлы дампов информации (DIS, ELF.MAP):
$ ls -al build/blinky*
-rwxr-xr-x 1 kuba staff 8.0K Jan 1 12:00 build/blinky.bin*
-rw-r--r-- 1 kuba staff 145K Jan 1 12:00 build/blinky.dis
-rwxr-xr-x 1 kuba staff 30K Jan 1 12:00 build/blinky.elf*
-rw-r--r-- 1 kuba staff 222K Jan 1 12:00 build/blinky.elf.map
-rw-r--r-- 1 kuba staff 23K Jan 1 12:00 build/blinky.hex
-rw-r--r-- 1 kuba staff 16K Jan 1 12:00 build/blinky.uf2
Запуск микропрограммного кода на устройстве
Если у вас есть Raspberry Pi Pico, мы сейчас загрузим собранный микропрограммный код и запустим его. Если у вас его нет, перейдите к следующему разделу и запустите тот же самый файл микропрограммного кода в эмуляторе вместо этого.
Подключите плату Raspberry Pi Pico через USB-кабель к вашему Mac и убедитесь, что она находится в режиме загрузки микропрограммного кода USB Mass Storage. Обычно это так, если вы еще никогда не загружали микропрограммный код — Pico загружается в режим загрузки микропрограммного кода, если его память не содержит никакого действительного микропрограммного кода. После загрузки действительного микропрограммного кода устройство выполнит этот микропрограммный код после подключения. Чтобы вернуться в режим загрузки микропрограммного кода, удерживайте нажатой кнопку BOOTSEL при подключении платы.
Pico должен отобразиться как подключённый том в /Volumes (в данном случае как RPI-RP2):
$ ls -al /Volumes
lrwxr-xr-x 1 root wheel 1B Jan 1 12:00 Macintosh HD@ -> /
drwx------ 1 kuba staff 16K Dec 31 1969 RPI-RP2/
Скопируйте файл UF2 в этот том:
$ cp build/blinky.uf2 /Volumes/RPI-RP2
Это автоматически установит микропрограммный код на Pico, перезагрузит его и запустит микропрограммный код.
Теперь зелёный светодиод должен мигать периодически. Ура! Наше первое приложение Embedded Swift работает на встроенном устройстве!
Запуск микропрограммного кода в эмуляторе
Если у вас нет физического Pico или вы хотите быстро итерировать, Wokwi — это бесплатный онлайн-эмулятор различных встроенных микроконтроллеров, включая Raspberry Pi Pico. Он выполняет тот же двоичный файл микропрограммного кода, который вы обычно загружаете на физическое устройство, и эмулирует одну инструкцию за раз.
Откройте новый проект Pico в Wokwi. Вместо использования редактора кода для написания кода C, нажмите F1 и выберите «Загрузить микропрограммный код и запустить симуляцию». Затем выберите файл UF2, который создал наш процесс сборки.
После загрузки файла UF2 в Wokwi симуляция начнётся, и светодиод начнёт периодически мигать. Ура! Наше первое приложение Embedded Swift работает в эмуляторе!
Дополнительный материал: Создание простого приложения для вашей ОС хоста с помощью Embedded Swift
Хотя настольные операционные системы, такие как macOS и Linux, не являются типичными целевыми платформами для Embedded Swift, вы абсолютно можете создавать код для них с помощью режима Embedded Swift. Это полезно для экспериментов, опробования Embedded Swift или для быстрого итерационного процесса над идеей некоторого кода, которому физическое устройство не нужно для работы.
Самое простое приложение в Embedded Swift может быть просто стандартным «Hello, World»:
// HelloEmbedded.swift
print("Hello, Embedded Swift 😊")
И создание исполняемого файла может быть выполнено вызовом компилятора swiftc напрямую, но мы хотим добавить флаги для включения Embedded Swift и Whole Module Optimization.
$ swiftc HelloEmbedded.swift -o HelloEmbedded -enable-experimental-feature Embedded -wmo
Это создаст обычный двоичный исполняемый файл, но обратите внимание, что он очень небольшой по размеру и что он фактически не зависит от среды выполнения Swift в операционной системе (все двоичные файлы Embedded Swift содержат зависимости среды выполнения + stdlib внутри):
$ ls -al
-rwxr-xr-x 1 kuba staff 18K May 16 17:19 HelloEmbedded*
-rw-r--r-- 1 kuba staff 59B May 16 17:16 HelloEmbedded.swift
$ otool -L HelloEmbedded
HelloEmbedded:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1000.0.0)
Давайте запустим его:
$ ./HelloEmbedded
Hello, Embedded Swift 😊
Ура! Наше первое приложение Embedded Swift для хост-платформы работает!
Куда двигаться дальше
- Документ Embedded Swift Vision Document даст вам общее представление о подходах и целях Embedded Swift, а также о том, что именно входит в подмножество языка Embedded Swift.
- Коллекция примеров проектов Embedded Swift на GitHub демонстрирует, на каких встроенных устройствах сегодня можно использовать Swift, а примеры также могут быть использованы в качестве шаблонов для ваших собственных проектов.
- Руководство Embedded Swift User Manual описывает, как использовать режим компиляции Embedded Swift и как взаимодействовать с компилятором.
- Страница Инструментов содержит руководства по настройке интеграции Swift в ваш редактор для включения таких функций, как индексация, автодополнение, переход к определению и других.
- Форумы Swift — лучшее место для задавания вопросов, предоставления отзывов или совместного использования ваших интересных проектов.
Исходный код этого руководства можно найти на GitHub
The Swift Programming Language, Copyright © 2014-2025 Apple Inc.
Swift and the Swift logo are trademarks of Apple Inc.
Documentation for Swift 6.0.3
https://www.swift.org/getting-started/embedded-swift