-
Notifications
You must be signed in to change notification settings - Fork 64
Modernize rpi-5 build #128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@iCMDdev can you verify that this example still works with the build changes? |
Hi, sure! I'll test later today, or in the worst case, tomorrow, and let you know. |
Sorry for the delay. I tried to test it since yesterday but something didn't work out (likely on my end). I'll test again tomorrow and let you know how it goes. |
Unfortunately I think something isn't right on the Pi 5 (LED doesn't blink); I'll try to compare the resulted binaries. Currently the old build fails for me, so I'll have to retry with an older Swift dev build. Looking at the output of |
Thanks so much for taking a look; would you be interesting in trying to fix/land this change? we're trying to move all the SwiftPM sample to avoid manually linking |
Yes, surely! I was actually looking into it right now. Looking at the old ( cmd@ ~/Downloads/rpi-5-blink-binary % objdump -D kernel8.elf
kernel8.elf: file format elf64-littleaarch64
Disassembly of section .text:
0000000000080000 <_start>:
80000: d53800a1 mrs x1, MPIDR_EL1
80004: 92400421 and x1, x1, #0x3
80008: b4000061 cbz x1, 0x80014 <_start+0x14>
8000c: d503205f wfe
80010: 17ffffff b 0x8000c <_start+0xc>
80014: 58000161 ldr x1, 0x80040 <_start+0x40>
80018: 9100003f mov sp, x1
8001c: 58000161 ldr x1, 0x80048 <_start+0x48>
80020: 18000182 ldr w2, 0x80050 <_start+0x50>
80024: 34000082 cbz w2, 0x80034 <_start+0x34>
80028: f800843f str xzr, [x1], #0x8
8002c: 51000442 sub w2, w2, #0x1
80030: 35ffffa2 cbnz w2, 0x80024 <_start+0x24>
80034: 940003ee bl 0x80fec <main>
80038: 17fffff5 b 0x8000c <_start+0xc>
8003c: 00000000 udf #0x0
... (there's more) And here is the current, new build result: cmd@ ~/Downloads/rpi-5-blink % objdump -D Application
Application: file format elf64-littleaarch64
Disassembly of section .swift_modhash:
0000000000080000 <$d>:
80000: b8 37 7d b5 .word 0xb57d37b8
80004: 35 04 4e b2 .word 0xb24e0435
80008: 8d 6c 19 ca .word 0xca196c8d
8000c: cf a6 20 4d .word 0x4d20a6cf
... (more .words)
Disassembly of section .text:
00000000000800a0 <main>:
800a0: d28f8088 mov x8, #0x7c04 // =31748
800a4: f2afaa28 movk x8, #0x7d51, lsl #16
800a8: f2c00208 movk x8, #0x10, lsl #32
800ac: b9400509 ldr w9, [x8, #0x4]
800b0: 12167929 and w9, w9, #0xfffffdff
800b4: b9000509 str w9, [x8, #0x4]
800b8: b9400109 ldr w9, [x8]
800bc: 32170129 orr w9, w9, #0x200
800c0: b9000109 str w9, [x8]
800c4: b9400109 ldr w9, [x8]
800c8: 12167929 and w9, w9, #0xfffffdff
800cc: b9000109 str w9, [x8]
800d0: 17fffffa b 0x800b8 <main+0x18> So yes, as I suspected, the entrypoint is likely the issue. This is likely caused by the linking step, and I'll look into it. It's a bit strange, since the same linker script is used and this shouldn't have happened. Also: In the new build, there's no If you have any ideas why this could happen, I'm open to hearing them! |
Updates the rpi-5-blink example to link using SwiftPM and use a toolset.json.
@iCMDdev I think I fixed those issues!
|
Great! I'll test again shortly. |
I think we're definitely on the right track and these changes are good, but from my testing it stil doesn't blink. Here's what I've noticed:
% objdump -D Application
Disassembly of section .text:
0000000000080000 <_start>:
80000: d53800a1 mrs x1, MPIDR_EL1
80004: 92400421 and x1, x1, #0x3
80008: b4000061 cbz x1, 0x80014 <_start+0x14>
8000c: d503205f wfe
80010: 17ffffff b 0x8000c <_start+0xc>
80014: 58000161 ldr x1, 0x80040 <_start+0x40>
80018: 9100003f mov sp, x1
8001c: 58000161 ldr x1, 0x80048 <_start+0x48>
80020: 18000182 ldr w2, 0x80050 <_start+0x50>
80024: 34000082 cbz w2, 0x80034 <_start+0x34>
80028: f800843f str xzr, [x1], #0x8
8002c: 51000442 sub w2, w2, #0x1
80030: 35ffffa2 cbnz w2, 0x80024 <_start+0x24>
80034: 94000008 bl 0x80054 <main>
80038: 17fffff5 b 0x8000c <_start+0xc>
8003c: 00000000 udf #0x0
0000000000080040 <$d>:
80040: 00 00 08 00 .word 0x00080000
80044: 00 00 00 00 .word 0x00000000
80048: 90 00 08 00 .word 0x00080090
8004c: 00 00 00 00 .word 0x00000000
80050: 00 00 00 00 .word 0x00000000
0000000000080054 <main>:
80054: d28f8088 mov x8, #0x7c04 // =31748
80058: f2afaa28 movk x8, #0x7d51, lsl #16
8005c: f2c00208 movk x8, #0x10, lsl #32
80060: b9400509 ldr w9, [x8, #0x4]
80064: 12167929 and w9, w9, #0xfffffdff
80068: b9000509 str w9, [x8, #0x4]
8006c: b9400109 ldr w9, [x8]
80070: 32170129 orr w9, w9, #0x200
80074: b9000109 str w9, [x8]
80078: b9400109 ldr w9, [x8]
8007c: 12167929 and w9, w9, #0xfffffdff
80080: b9000109 str w9, [x8]
80084: 17fffffa b 0x8006c <main+0x18> (That's all of it. No mentions of
|
@iCMDdev can you try the old version but in a I do really appreciate the time and help here! |
Sure! |
It looks like indeed, the old build doesn't work either when compiled in release mode (with While the old build |
I think I figured out something by looking at the assembly. I was previously using the following as a simple workaround for a for _ in 1..<100000 {} But that gets optimized in the production assembly: main:
// set x8 to the MMIO address = 0x00000010_7d51_7c04
mov x8, #0x7c04
movk x8, #0x7d51, lsl #16
movk x8, #0x10, lsl #32
// x8 is now set to GPIO base address + 4 = GIODATA
// x8 + 4 = GPIOIODIR (GPIO direction register)
ldr w9, [x8, #0x4] // load current value of GIOIODIR
and w9, w9, #0xfffffdff // clear bit 9, which is for GPIO9 (value 0 = output)
str w9, [x8, #0x4] // store result back to GIOIODIR
// x8 + 0 = GPIOIODATA (GPIO data register)
// set GPIO9 (onboard green ACT LED) high
ldr w9, [x8] // load current value of GIODATA
<main+0x18>:
orr w9, w9, #0x200 // set bit 9, which is for GPIO9 (value 1 = high)
str w9, [x8] // store result back to GIODATA
// NOTICE: There's no delay here!!
// x8 + 0 = GPIOIODATA (GPIO data register)
// set GPIO9 (onboard green ACT LED) low
ldr w9, [x8] // load current value of GIODATA
and w9, w9, #0xfffffdff // clear bit 9, which is for GPIO9 (value 0 = low)
str w9, [x8] // store result back to GIODATA
b 0x8006c <main+0x18> // loop back; set GPIO9 high again And, to be honest, I forgot to rewrite it in a more graceful manner. So, @rauhul, do you have any tips on how to write such a TL;DR I suppose the code is actually running but it blinks really fast, without a delay; unfortunately I can't find my SWD debugger to attach to my Pi and confirm it that way (edit: reading this, I guess I could just turn the LED off without turning it back on and confirm it like that, but I'll try the hack mentioned below). |
I've seen that the STM32 example defines a for _ in 0..<10_000 * milliseconds {
nop()
} So I assume that would work. |
@iCMDdev our hack solution in the other examples is to use inline asm from a c header to expose |
Yeah, just noticed that (also sent my comment above right before seeing this). I'll try to test that. |
@rauhul Great news: I confirmed it works!!! I made the follwing changes (for the Pi 5 example, Pi 4 should be similar): // Support.h
#pragma once
static inline __attribute((always_inline)) void nop() {
asm volatile("nop");
} // Application.swift
import MMIO
import Support // for nop()
@Register(bitWidth: 32)
struct GIOIODIR {
@ReadWrite(bits: 9..<10, as: Bool.self)
var direction: DIRECTION
}
@Register(bitWidth: 32)
struct GIODATA {
@ReadWrite(bits: 9..<10, as: Bool.self)
var value: VALUE
}
@RegisterBlock
struct GPIO {
@RegisterBlock(offset: 0x00008)
var gioiodir: Register<GIOIODIR>
@RegisterBlock(offset: 0x00004)
var giodata: Register<GIODATA>
}
let gpio = GPIO(unsafeAddress: 0x10_7d51_7c00)
func setLedOutput() {
gpio.gioiodir.modify {
$0.direction = false // 0 is output, 1 is input
}
}
func ledOn() {
gpio.giodata.modify {
$0.value = true // pin on
}
}
func ledOff() {
gpio.giodata.modify {
$0.value = false // pin off
}
}
@main
struct Application {
static func main() {
setLedOutput()
while true {
ledOn()
for _ in 1..<100000 { nop() } // added nop and increased delay
ledOff()
for _ in 1..<100000 { nop() } // added nop and increased delay
}
}
} |
Updates the rpi-5-blink example to link using SwiftPM and use a toolset.json.