Skip to content

Commit 92dd75b

Browse files
authored
Merge branch 'main' into RPi-4B-BCM2711
2 parents dc4024f + 8795b3f commit 92dd75b

File tree

22 files changed

+780
-119
lines changed

22 files changed

+780
-119
lines changed

.flake8

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[flake8]
2+
3+
ignore =
4+
# These are needed to make our license headers pass the linting
5+
E265,
6+
E266,
7+
8+
# 10% larger than the standard 80 character limit. Conforms to the black
9+
# standard and Bugbear's B950.
10+
max-line-length = 88

.github/workflows/build-esp.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
branches: ["main"]
88
schedule:
99
# Build on Mondays at 9am PST every week
10-
- cron: '0 17 * * 1'
10+
- cron: '0 17 * * 1'
1111

1212
jobs:
1313
build-esp:

.github/workflows/build-nuttx.yml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
name: Build NuttX Examples
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
pull_request:
7+
branches: ["main"]
8+
schedule:
9+
# Build on Mondays at 9am PST every week
10+
- cron: '0 17 * * 1'
11+
12+
jobs:
13+
build-nuttx:
14+
runs-on: ubuntu-24.04
15+
16+
strategy:
17+
fail-fast: false
18+
matrix:
19+
example: [nuttx-riscv-blink]
20+
swift: [swift-DEVELOPMENT-SNAPSHOT-2024-12-22-a]
21+
22+
steps:
23+
- name: Checkout repo
24+
uses: actions/checkout@v4
25+
26+
- name: Install apt dependencies
27+
run: |
28+
sudo apt-get -qq update && sudo apt-get -qq -y install \
29+
bison flex gettext texinfo libncurses5-dev libncursesw5-dev \
30+
gperf automake libtool pkg-config build-essential gperf genromfs \
31+
libgmp-dev libmpc-dev libmpfr-dev libisl-dev binutils-dev libelf-dev \
32+
libexpat-dev gcc-multilib g++-multilib u-boot-tools util-linux \
33+
kconfig-frontends ninja-build
34+
35+
- name: Install CMake 3.30.2
36+
run: |
37+
ARCH=`uname -m`
38+
curl -sL https://github.com/Kitware/CMake/releases/download/v3.30.2/cmake-3.30.2-linux-$ARCH.tar.gz -O
39+
tar xzf cmake-3.30.2-linux-$ARCH.tar.gz
40+
export PATH="`pwd`/cmake-3.30.2-linux-$ARCH/bin:$PATH"
41+
echo "PATH=$PATH" >> $GITHUB_ENV
42+
cmake --version
43+
44+
- name: Install RISC-V toolchain
45+
run: |
46+
mkdir -p riscv-none-elf-gcc && \
47+
curl -s -L "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz" \
48+
| tar -C riscv-none-elf-gcc --strip-components 1 -xz
49+
export PATH="$PATH:`pwd`/riscv-none-elf-gcc/bin/"
50+
echo "PATH=$PATH" >> $GITHUB_ENV
51+
riscv-none-elf-gcc --version
52+
53+
- name: Install ${{ matrix.swift }}
54+
run: |
55+
wget -q https://download.swift.org/development/ubuntu2404/${{ matrix.swift }}/${{ matrix.swift }}-ubuntu24.04.tar.gz
56+
tar xzf ${{ matrix.swift }}-ubuntu24.04.tar.gz
57+
export PATH="`pwd`/${{ matrix.swift }}-ubuntu24.04/usr/bin/:$PATH"
58+
echo "PATH=$PATH" >> $GITHUB_ENV
59+
swiftc --version
60+
61+
- name: Config ${{ matrix.example }}
62+
working-directory: ${{ matrix.example }}
63+
run: cmake -B build -GNinja -DBOARD_CONFIG=rv-virt:leds_swift -DENABLE_NUTTX_TRACE=ON
64+
65+
- name: Build ${{ matrix.example }}
66+
working-directory: ${{ matrix.example }}
67+
run: cmake --build build

.github/workflows/build-pico-sdk.yml

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ on:
77
branches: ["main"]
88
schedule:
99
# Build on Mondays at 9am PST every week
10-
- cron: '0 17 * * 1'
10+
- cron: '0 17 * * 1'
1111

1212
jobs:
1313
build-pico-sdk:
14-
runs-on: ubuntu-22.04
15-
container: swiftlang/swift:nightly-main-jammy
14+
runs-on: ubuntu-24.04
1615
strategy:
1716
fail-fast: false
1817
matrix:
@@ -21,13 +20,14 @@ jobs:
2120
board: pico
2221
- name: pico-w-blink-sdk
2322
board: pico_w
23+
swift: [swift-DEVELOPMENT-SNAPSHOT-2024-12-04-a]
2424

2525
steps:
2626
- name: Checkout repo
2727
uses: actions/checkout@v4
2828

2929
- name: Install apt dependencies
30-
run: apt-get -qq update && apt-get -qq -y install curl ninja-build python3
30+
run: sudo apt-get -qq update && sudo apt-get -qq -y install curl ninja-build python3
3131

3232
- name: Install CMake 3.30.2
3333
run: |
@@ -38,19 +38,28 @@ jobs:
3838
echo "PATH=$PATH" >> $GITHUB_ENV
3939
cmake --version
4040
41+
- name: Install GNU ARM toolchain
42+
run: |
43+
ARCH=`uname -m`
44+
curl -sL https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-gnu-toolchain-13.3.rel1-$ARCH-arm-none-eabi.tar.xz -O
45+
tar xf arm-gnu-toolchain-13.3.rel1-$ARCH-arm-none-eabi.tar.xz
46+
47+
- name: Install ${{ matrix.swift }}
48+
run: |
49+
wget -q https://download.swift.org/development/ubuntu2404/${{ matrix.swift }}/${{ matrix.swift }}-ubuntu24.04.tar.gz
50+
tar xzf ${{ matrix.swift }}-ubuntu24.04.tar.gz
51+
export PATH="$PATH:`pwd`/${{ matrix.swift }}-ubuntu24.04/usr/bin/"
52+
echo "PATH=$PATH" >> $GITHUB_ENV
53+
which swiftc
54+
swiftc --version
55+
4156
- name: Clone Pico SDK
4257
run: |
4358
git clone https://github.com/raspberrypi/pico-sdk.git
4459
cd pico-sdk
4560
git submodule update --init --recursive
4661
cd ..
4762
48-
- name: Download GNU ARM toolchain
49-
run: |
50-
ARCH=`uname -m`
51-
curl -sL https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-gnu-toolchain-13.3.rel1-$ARCH-arm-none-eabi.tar.xz -O
52-
tar xf arm-gnu-toolchain-13.3.rel1-$ARCH-arm-none-eabi.tar.xz
53-
5463
- name: Set Pico environment variables
5564
run: |
5665
ARCH=`uname -m`

.github/workflows/build-zephyr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
branches: ["main"]
88
schedule:
99
# Build on Mondays at 9am PST every week
10-
- cron: '0 17 * * 1'
10+
- cron: '0 17 * * 1'
1111

1212
jobs:
1313
build-zephyr:

.github/workflows/lint.yml

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,26 @@ on:
77
branches: ["main"]
88

99
jobs:
10-
lint:
11-
name: Lint
10+
validate_format_config:
11+
name: Validate Format Config
1212
runs-on: ubuntu-latest
13-
container: swift:6.0-jammy
14-
1513
steps:
1614
- name: Checkout repo
1715
uses: actions/checkout@v4
1816

1917
- name: Install apt dependencies
20-
run: apt-get -qq update && apt-get -qq -y install curl
18+
run: sudo apt-get -qq update && sudo apt-get -qq -y install curl
2119

2220
- name: Compare against swift-mmio swift-format config
2321
run: |
2422
curl -sL https://raw.githubusercontent.com/apple/swift-mmio/refs/heads/main/.swift-format -o .swift-format-mmio
2523
diff .swift-format .swift-format-mmio
2624
27-
- name: Lint
28-
run: swift-format lint --recursive --strict .
25+
soundness:
26+
name: Soundness
27+
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main
28+
with:
29+
api_breakage_check_enabled: false # this repo doesn't vend any API
30+
license_header_check_enabled: false # feature: https://github.com/swiftlang/github-workflows/issues/78
31+
license_header_check_project_name: "Swift.org" # bug: https://github.com/swiftlang/github-workflows/issues/76
32+
unacceptable_language_check_enabled: false # unfortunately many hardware specs use terms like master/slave in their documentation

README.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,22 @@ Each example in this repository contains build and deployment instructions, howe
3232

3333
| Name | Platform | SDK | Description | Photo |
3434
| ---- | -------- | --- | ----------- | ----- |
35-
| [stm32-blink](./stm32-blink) | STM32F746G-DISCO | None | Blink an LED repeatedly. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/739e98fd-a438-4a64-a7aa-9dddee25034b"> |
36-
| [stm32-lcd-logo](./stm32-lcd-logo) | STM32F746G-DISCO | None | Animate the Swift Logo on the built-in LCD. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/9e117d81-e808-493e-a20c-7284ea630f37"> |
37-
| [stm32-neopixel](./stm32-neopixel) | STM32F746G-DISCO | None | Control NeoPixel LEDs using SPI. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/9c5d8f74-f8aa-4632-831e-212a3e35e75a"> |
38-
| [stm32-uart-echo](./stm32-uart-echo) | STM32F746G-DISCO | None | Echo user input using UART. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/97d3c465-9a07-4b86-9654-0c2aaaa43b3d">|
39-
| [pico-blink](./pico-blink) | Raspberry Pi Pico | None | Blink an LED repeatedly. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/f2c45c18-f9a4-48b4-a941-1298ecc942cb"> |
35+
| [esp32-led-blink-sdk](./esp32-led-blink-sdk) | ESP32-C6-Bug | ESP-IDF SDK | Blink an LED repeatedly with Swift & the ESP-IDF. | <img width="300" src="esp32-led-blink-sdk/assets/images/ledon.jpg"> |
36+
| [esp32-led-strip-sdk](./esp32-led-strip-sdk) | ESP32-C6-DevKitC-1 | ESP-IDF SDK | Control NeoPixel LEDs with Swift & the ESP-IDF. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/15f8a3e0-953e-426d-ad2d-3902baf859be"> |
37+
| [nrfx-blink-sdk](./nrfx-blink-sdk) | nRF52840-DK | Zephyr SDK | Blink an LED repeatedly with Swift & Zephyr. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/ae3ff153-dd33-4460-8a08-4eac442bf7b0"> |
38+
| [nuttx-riscv-blink] | QEMU | NuttX | Blink a virualized led in QEMU using the Apache NuttX RTOS | |
4039
| [pico-blink-sdk](./pico-blink-sdk) | Raspberry Pi Pico, Pico 2 | Pico SDK | Blink an LED repeatedly with Swift & the Pico SDK. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/f2c45c18-f9a4-48b4-a941-1298ecc942cb"> |
40+
| [pico-blink](./pico-blink) | Raspberry Pi Pico | None | Blink an LED repeatedly. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/f2c45c18-f9a4-48b4-a941-1298ecc942cb"> |
4141
| [pico-w-blink-sdk](./pico-w-blink-sdk) | Raspberry Pi Pico W | Pico SDK | Blink an LED to signal 'SOS' in Morse code repeatedly with Swift & the Pico SDK. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/26223064/a4949a2e-1887-4325-8f5f-a681963c93d7"> |
4242
| [pico2-neopixel](./pico2-neopixel) | Raspberry Pi Pico 2 | None | Control Neopixel LEDs using the RP2350 PIO. | <img width="300" src="pico2-neopixel/assets/images/example.jpg"> |
43-
| [nrfx-blink-sdk](./nrfx-blink-sdk) | nRF52840-DK | Zephyr SDK | Blink an LED repeatedly with Swift & Zephyr. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/ae3ff153-dd33-4460-8a08-4eac442bf7b0"> |
44-
| [esp32-led-strip-sdk](./esp32-led-strip-sdk) | ESP32-C6-DevKitC-1 | ESP-IDF SDK | Control NeoPixel LEDs with Swift & the ESP-IDF. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/15f8a3e0-953e-426d-ad2d-3902baf859be"> |
45-
| [esp32-led-blink-sdk](./esp32-led-blink-sdk) | ESP32-C6-Bug | ESP-IDF SDK | Blink an LED repeatedly with Swift & the ESP-IDF. | <img width="300" src="esp32-led-blink-sdk/assets/images/ledon.jpg"> |
4643
| [rpi4b-blink](./rpi4b-blink) | Raspberry Pi 4B | None | Blink the Pi's status green LED repeatedly using Swift MMIO. | <img width="300" src="rpi4b-blink/assets/rpi4.png"> |
4744
| [rpi5-blink](./rpi5-blink) | Raspberry Pi 5 | None | Blink the Pi's status green LED repeatedly with Swift MMIO. | <img width="300" src="rpi5-blink/assets/raspi5.png"> |
45+
| [stm32-blink](./stm32-blink) | STM32F746G-DISCO | None | Blink an LED repeatedly. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/739e98fd-a438-4a64-a7aa-9dddee25034b"> |
46+
| [stm32-lcd-logo](./stm32-lcd-logo) | STM32F746G-DISCO | None | Animate the Swift Logo on the built-in LCD. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/9e117d81-e808-493e-a20c-7284ea630f37"> |
47+
| [stm32-neopixel](./stm32-neopixel) | STM32F746G-DISCO | None | Control NeoPixel LEDs using SPI. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/9c5d8f74-f8aa-4632-831e-212a3e35e75a"> |
48+
| [stm32-uart-echo](./stm32-uart-echo) | STM32F746G-DISCO | None | Echo user input using UART. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/97d3c465-9a07-4b86-9654-0c2aaaa43b3d">|
4849

49-
Note that the SDK integration examples (Pico SDK, Zephyr SDK, etc.) are not recommendations or endorsement, the same is true for build system choice (Make, CMake, SwiftPM, shell scripts). Embedded Swift aims to be versatile and to allow for integration into more existing SDKs and build systems, and the example projects are merely showing the possibilities.
50+
Note that the SDK integration examples (Pico SDK, Zephyr SDK, etc.) are not recommendations or endorsement, the same is true for build system choice (Make, CMake, SwiftPM, shell scripts). Embedded Swift aims to be versatile and allowing integration into existing SDKs and build systems, and the example projects show some of the possibilities.
5051

5152
## Community Examples
5253

@@ -59,6 +60,8 @@ Note that the SDK integration examples (Pico SDK, Zephyr SDK, etc.) are not reco
5960
| ---- | -------- | ----------- |
6061
| [swift-matter-examples](https://github.com/apple/swift-matter-examples) | ESP32 | An Embedded Swift Matter application running on ESP32-C6. |
6162
| [swift-flipperzero-hello](https://github.com/Sameesunkaria/swift-flipperzero-hello) | Flipper Zero | A demonstration of running Swift apps on the Flipper Zero. |
63+
| [EmbeddedSwift nRF52 Examples](https://github.com/nelcea/EmbeddedSwift-nRF52-Examples) | nRF52840 (Development Kit) | A collection of examples using Embedded Swift on top of nRF Connect SDK (Zephyr). |
64+
| [Swatak](https://github.com/nelcea/EmbeddedSwift-nRF52-Swatak) | nRF52840 (Seeed Studio XIAO) | A reaction time game inspired by BATAK© boards, implemented in Embedded Swift using nRF Connect SDK. |
6265
| [swift-picosystem-example](https://github.com/jerrodputman/swift-picosystem-example) | PicoSystem | An Embedded Swift demo running on the Pimoroni PicoSystem |
6366
| [PlaydateKit](https://github.com/finnvoor/PlaydateKit) | Playdate | A full featured framework for building Playdate games using Embedded Swift. |
6467
| [swift-playdate-examples](https://github.com/apple/swift-playdate-examples) | Playdate | An Embedded Swift game running on Playdate by Panic. |

Tools/macho2bin.py

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,45 @@
88
# See https://swift.org/LICENSE.txt for license information
99

1010
#
11-
# macho2bin -- Converts a statically-linked executable Mach-O into a flat "BIN" file suitable for flashing as a single
12-
# contiguous blob onto some embedded devices. Note that this format assumes the embedded device can boot from a state
13-
# where the entire firmware (all segments) are flashed contigously into one smalle address range. This is true for e.g.
14-
# the STM32F746 devices if we place the vector table at 0x00200000, and code and data right after it, as the vector
15-
# table also contains a pointer to the initial PC. This setup might not work for other devices.
11+
# macho2bin -- Converts a statically-linked executable Mach-O into a flat "BIN" file
12+
# suitable for flashing as a single contiguous blob onto some embedded devices. Note
13+
# that this format assumes the embedded device can boot from a state where the entire
14+
# firmware (all segments) are flashed contigously into one smalle address range. This
15+
# is true for e.g. the STM32F746 devices if we place the vector table at 0x00200000,
16+
# and code and data right after it, as the vector table also contains a pointer to the
17+
# initial PC. This setup might not work for other devices.
1618
#
1719
# Usage:
18-
# $ macho2bin.py <input> <output> --base-address <base-address> --segments <segment-list>
20+
# $ macho2bin.py <input> <output> --base-address <base-address> --segments
21+
# <segment-list>
1922
#
2023
# Example:
21-
# $ macho2bin.py ./blink ./blink.bin --base-address 0x00200000 --segments '__TEXT,__DATA,__VECTORS'
24+
# $ macho2bin.py ./blink ./blink.bin --base-address 0x00200000 --segments
25+
# '__TEXT,__DATA,__VECTORS'
2226
#
2327
# Requirements and notes:
24-
# * The output BIN file is a flat contiguous representation of the segments (--segments) based on their VM addresses.
25-
# * The BIN file's first byte corresponds to the specified base address (--base-address).
28+
# * The output BIN file is a flat contiguous representation of the segments
29+
# (--segments) based on their VM addresses.
30+
# * The BIN file's first byte corresponds to the specified base address
31+
# (--base-address).
2632
# * Any gaps between segments are filled with zero bytes.
27-
# * Because of that, you want the input Mach-O to have all segments "close", and not have gaps.
33+
# * Because of that, you want the input Mach-O to have all segments "close", and not
34+
# have gaps.
2835
#
2936

3037
import argparse
3138
import os
39+
3240
from macholib import MachO
3341
from macholib import mach_o
3442

43+
3544
def main():
3645
parser = argparse.ArgumentParser()
37-
parser.add_argument('input')
38-
parser.add_argument('output')
39-
parser.add_argument('--base-address', required=True)
40-
parser.add_argument('--segments', required=True)
46+
parser.add_argument("input")
47+
parser.add_argument("output")
48+
parser.add_argument("--base-address", required=True)
49+
parser.add_argument("--segments", required=True)
4150
args = parser.parse_args()
4251
args.base_address = int(args.base_address, 16)
4352
args.segments = args.segments.split(",")
@@ -49,17 +58,23 @@ def main():
4958
for command in mh.commands:
5059
if isinstance(command[1], mach_o.segment_command):
5160
(_, segment, sections) = command
52-
segname = segment.segname.decode().strip('\0')
53-
if segname not in args.segments: continue
61+
segname = segment.segname.decode().strip("\0")
62+
if segname not in args.segments:
63+
continue
5464

5565
with open(args.input, "rb") as f:
5666
f.seek(mh.offset + segment.fileoff)
5767
data = f.read(segment.filesize)
58-
segments.append({"vmaddr": segment.vmaddr, "data": data, "name": segname})
59-
68+
segments.append(
69+
{"vmaddr": segment.vmaddr, "data": data, "name": segname}
70+
)
71+
6072
segments = sorted(segments, key=lambda x: x["vmaddr"])
6173

62-
assert segments[0]["vmaddr"] == args.base_address, f"first segment's vmaddr 0x{segments[0]['vmaddr']:08x} does not match the passed --base-address 0x{args.base_address:08x}"
74+
assert segments[0]["vmaddr"] == args.base_address, (
75+
f"first segment's vmaddr 0x{segments[0]['vmaddr']:08x} does not match the"
76+
f" passed --base-address 0x{args.base_address:08x}"
77+
)
6378

6479
if os.path.exists(args.output):
6580
os.unlink(args.output)
@@ -69,15 +84,22 @@ def main():
6984
for segment in segments:
7085
gap = segment["vmaddr"] - vmaddr
7186
if gap != 0:
72-
print(f"Writing gap of size {gap} (0x{gap:0x}) at vmaddr 0x{vmaddr:08x}")
73-
f.write(b'\0' * gap)
87+
print(
88+
f"Writing gap of size {gap} (0x{gap:0x}) at vmaddr 0x{vmaddr:08x}"
89+
)
90+
f.write(b"\0" * gap)
7491
assert gap >= 0
7592
vmaddr = segment["vmaddr"]
76-
print(f"Writing segment {segment['name']} size {len(segment['data'])} (0x{len(segment['data']):x}) at vmaddr 0x{vmaddr:08x}")
93+
print(
94+
f"Writing segment {segment['name']} size"
95+
f" {len(segment['data'])} (0x{len(segment['data']):x}) at vmaddr"
96+
f" 0x{vmaddr:08x}"
97+
)
7798
f.write(segment["data"])
7899
vmaddr = segment["vmaddr"] + len(segment["data"])
79100

80101
print(f"Produced {args.output} with {vmaddr - args.base_address} bytes")
81102

82-
if __name__ == '__main__':
103+
104+
if __name__ == "__main__":
83105
main()

0 commit comments

Comments
 (0)