Skip to content

Commit f8f64ae

Browse files
committed
Updated RPi 4 example
1 parent 7a9af2f commit f8f64ae

File tree

7 files changed

+228
-0
lines changed

7 files changed

+228
-0
lines changed

rpi4b-blink/Package.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// swift-tools-version: 6.1
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "RPI4B-Blink",
8+
platforms: [
9+
.macOS(.v14),
10+
],
11+
products: [
12+
.library(
13+
name: "MainApp",
14+
type: .static,
15+
targets: ["MainApp"]),
16+
],
17+
dependencies: [
18+
.package(
19+
url: "https://github.com/apple/swift-mmio.git",
20+
branch: "swift-embedded-examples"),
21+
],
22+
targets: [
23+
.target(
24+
name: "MainApp",
25+
dependencies: [
26+
.product(name: "MMIO", package: "swift-mmio")
27+
],
28+
swiftSettings: [
29+
.enableExperimentalFeature("Embedded"),
30+
.unsafeFlags(["-Xfrontend", "-function-sections"])
31+
]
32+
),
33+
.target(name: "Support")
34+
35+
]
36+
)

rpi4b-blink/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# rpi4b-blink
2+
3+
`[TBA: image here]`
4+
5+
## Requirements
6+
7+
- A Raspberry Pi 4B board
8+
- An SD Card, with a Raspberry Pi OS installed (this way, we don't need to create the configuration files from scratch). You may backup `kernel8.img` and `config.txt` if you need the Linux install later, since we will change these files.
9+
10+
## How to build and run this example:
11+
12+
- Make sure you have a recent nightly Swift toolchain that has Embedded Swift support.
13+
- Build the program, then copy the kernel image to the SD card.
14+
``` console
15+
$ cd rpi4b-blink
16+
$ export TOOLCHAINS='<toolchain-identifier>' # Your Swift nightly toolchain identifier
17+
$ chmod u+x ./build.sh # make build script executable
18+
$ ./build.sh
19+
$ cp kernel8.img /Volumes/bootfs
20+
```
21+
- If your original OS is not 64-bit, make sure to set `arm_64bit=1` in `config.txt`.
22+
- Place the SD card in your Raspberry Pi 4B, and connect it to power.
23+
- After the boot sequence, the green (ACT) led will start blinking in a regular pattern.
24+
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift project authors.
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
import MMIO
13+
14+
@Register(bitWidth: 32)
15+
struct GPSET1 {
16+
@ReadWrite(bits: 10..<11, as: Bool.self)
17+
var set: SET
18+
}
19+
20+
@Register(bitWidth: 32)
21+
struct GPCLR1 {
22+
@ReadWrite(bits: 10..<11, as: Bool.self)
23+
var clear: CLEAR
24+
}
25+
26+
@Register(bitWidth: 32)
27+
struct GPFSEL4 {
28+
@ReadWrite(bits: 6..<7, as: Bool.self)
29+
var fsel42b1: FSEL42b1
30+
@ReadWrite(bits: 7..<8, as: Bool.self)
31+
var fsel42b2: FSEL42b2
32+
@ReadWrite(bits: 8..<9, as: Bool.self)
33+
var fsel42b3: FSEL42b3
34+
}
35+
36+
@RegisterBlock
37+
struct GPIO {
38+
@RegisterBlock(offset: 0x200020)
39+
var gpset1: Register<GPSET1>
40+
@RegisterBlock(offset: 0x20002c)
41+
var gpclr1: Register<GPCLR1>
42+
@RegisterBlock(offset: 0x200010)
43+
var gpfsel4: Register<GPFSEL4>
44+
}
45+
46+
47+
let gpio = GPIO(unsafeAddress: 0xFE000000)
48+
49+
50+
func setLedOutput() {
51+
gpio.gpfsel4.modify {
52+
// setFunction Select 42 (fsel42) to 001
53+
$0.fsel42b1 = true
54+
$0.fsel42b2 = false
55+
$0.fsel42b3 = false
56+
}
57+
}
58+
59+
func ledOn() {
60+
gpio.gpset1.modify {
61+
$0.set = true
62+
}
63+
}
64+
65+
func ledOff() {
66+
gpio.gpclr1.modify {
67+
$0.clear = true
68+
}
69+
}
70+
71+
72+
@main
73+
struct Main {
74+
75+
static func main() {
76+
setLedOutput()
77+
78+
while true {
79+
ledOn()
80+
for _ in 1..<100000 { } // just a delay
81+
ledOff()
82+
for _ in 1..<100000 { } // just a delay
83+
}
84+
}
85+
}

rpi4b-blink/Sources/Support/boot.S

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift project authors.
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
.section ".text.boot"
13+
14+
.global _start
15+
16+
_start:
17+
// Check processor ID is zero (executing on main core), else hang
18+
mrs x1, mpidr_el1
19+
and x1, x1, #3
20+
cbz x1, 2f
21+
// We're not on the main core, so hang in an infinite wait loop
22+
1: wfe
23+
b 1b
24+
2: // We're on the main core!
25+
26+
// Set stack to start below our code
27+
ldr x1, =_start
28+
mov sp, x1
29+
30+
// Clean the BSS section
31+
ldr x1, =__bss_start // Start address
32+
ldr w2, =__bss_size // Size of the section
33+
3: cbz w2, 4f // Quit loop if zero
34+
str xzr, [x1], #8
35+
sub w2, w2, #1
36+
cbnz w2, 3b // Loop if non-zero
37+
38+
// Jump to Swift!
39+
4: bl main
40+
// Halt if Swift returns
41+
b 1b

rpi4b-blink/Sources/Support/include/boot.h

Whitespace-only changes.

rpi4b-blink/build.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/sh
2+
3+
SWIFT_EXEC=${SWIFT_EXEC:-`xcrun -f swift`}
4+
CLANG=${CLANG:-`xcrun -f clang`}
5+
LLVM_OBJCOPY=/opt/homebrew/opt/llvm@17/bin/llvm-objcopy #${LLVM_OBJCOPY:-`xcrun -f llvm-objcopy`}
6+
7+
echo "🛠️ Building with Swift Package Manager... "
8+
9+
# Build the Swift package and get the path to the build directory
10+
BUILDROOT=$($SWIFT_EXEC build --triple aarch64-none-none-elf -Xcc -D__APPLE__ -Xcc -D__MACH__ -Xswiftc -Xfrontend -Xswiftc -disable-stack-protector --show-bin-path)
11+
$SWIFT_EXEC build --triple aarch64-none-none-elf -Xcc -D__APPLE__ -Xcc -D__MACH__ -Xswiftc -Xfrontend -Xswiftc -disable-stack-protector
12+
13+
echo "🔗 Linking with clang..."
14+
15+
$CLANG --target=aarch64-elf -o kernel8.elf "$BUILDROOT/libMainApp.a" "$BUILDROOT/Support.build/boot.S.o" -fuse-ld=lld -nostdlib -Wl,--unresolved-symbols=ignore-in-object-files -Wl,-T ./link.ld
16+
17+
echo "💾 Converting to binary kernel image with llvm-objcopy..."
18+
19+
$LLVM_OBJCOPY -O binary kernel8.elf kernel8.img
20+
21+
echo ""
22+
echo "🥳 Done! kernel8.img was saved to this directory."
23+

rpi4b-blink/link.ld

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
SECTIONS
2+
{
3+
. = 0x80000; /* Kernel load address for AArch64 */
4+
.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
5+
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
6+
PROVIDE(_data = .);
7+
.data : { *(.data .data.* .gnu.linkonce.d*) }
8+
.bss (NOLOAD) : {
9+
. = ALIGN(16);
10+
__bss_start = .;
11+
*(.bss .bss.*)
12+
*(COMMON)
13+
__bss_end = .;
14+
}
15+
_end = .;
16+
17+
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
18+
}
19+
__bss_size = (__bss_end - __bss_start)>>3;

0 commit comments

Comments
 (0)