Skip to content

Commit 5b1700d

Browse files
authored
aarch64 ble/observer font (#6)
1 parent 43dd2e2 commit 5b1700d

18 files changed

+1047
-258
lines changed

.github/workflows/main.yml

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ jobs:
3131
cp -a $REPO-armv6.img boot/
3232
./zig/zig build -Darmv7
3333
cp -a $REPO-armv7.img boot/
34+
./zig/zig build -Darmv8
35+
cp -a $REPO-armv8.img boot/
3436
- name: release draft
3537
env:
3638
GITHUB_USER: $GITHUB_ACTOR

README.md

+9-14
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,20 @@
1-
zig logo is displayed
2-
3-
The frame buffer cursor moves around the screen in response to the tv remote controller buttons. This requires the Consumer Electronics Control (CEC) feature on the tv.
4-
5-
Successfully tested on rpi3b, rpi3b+
6-
7-
Not yet working on armv6 raspberry pi models
1+
Privacy
2+
-------
83

9-
Not yet tested on rpi4b
4+
Bluetooth signals are collected and displayed on the screen
105

11-
Building
6+
Function
127
--------
138

14-
Requires the following patch to lib/zig/std/fmt.zig:
9+
zig logo is displayed
1510

16-
replace
11+
The frame buffer cursor moves around the screen in response to the tv remote controller buttons. This requires the Consumer Electronics Control (CEC) feature on the tv.
1712

18-
const digit = a % base;
13+
Presently only working on rpi3b+ due to some code generation issues
1914

20-
with
15+
Not yet working on armv6 raspberry pi models
2116

22-
const digit = a - base * (a / base);
17+
Not yet tested on rpi4b
2318

2419
Testing
2520
-------

assets/BCM4345C0.hcd

55.2 KB
Binary file not shown.

assets/small_font.bmp

32.1 KB
Binary file not shown.
File renamed without changes.
File renamed without changes.

boot/config.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ kernel=zig-bare-metal-raspberry-pi-armv6.img
1414
[rpi2]
1515
kernel=zig-bare-metal-raspberry-pi-armv7.img
1616
[rpi3]
17-
kernel=zig-bare-metal-raspberry-pi-armv7.img
17+
kernel=zig-bare-metal-raspberry-pi-armv8.img
1818
[rpi4]
19-
kernel=zig-bare-metal-raspberry-pi-armv7.img
19+
kernel=zig-bare-metal-raspberry-pi-armv8.img

build.zig

+30-14
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ const builtin = @import("builtin");
55
pub fn build(b: *Builder) !void {
66
const mode = b.standardReleaseOptions();
77
const want_armv6 = b.option(bool, "armv6", "Build armv6") orelse false;
8-
const want_armv7 = b.option(bool, "armv7", "Build armv7 (default)") orelse false;
9-
const want_qemu = b.option(bool, "qemu", "Build qemu variant of armv7") orelse false;
8+
const want_armv7 = b.option(bool, "armv7", "Build armv7") orelse false;
9+
const want_armv8 = b.option(bool, "armv8", "Build armv8 (default)") orelse false;
10+
const want_qemu = b.option(bool, "qemu", "Build qemu variant") orelse false;
1011
const want_nodisplay = b.option(bool, "nodisplay", "No display for qemu") orelse false;
1112

1213
const exec_name = "zig-bare-metal-raspberry-pi";
@@ -21,21 +22,25 @@ pub fn build(b: *Builder) !void {
2122
arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v6 };
2223
subarch = 6;
2324
kernel_name = exec_name ++ "-armv6.img";
24-
} else {
25+
} else if (want_armv7) {
2526
arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v7 };
2627
subarch = 7;
28+
kernel_name = exec_name ++ "-armv7.img";
29+
} else {
30+
arch = builtin.Arch{ .aarch64 = builtin.Arch.Arm64.v8 };
31+
subarch = 8;
2732
if (want_qemu) {
28-
kernel_name = exec_name ++ "-armv7-qemu.img";
33+
kernel_name = exec_name ++ "-armv8-qemu.img";
2934
} else {
30-
kernel_name = exec_name ++ "-armv7.img";
35+
kernel_name = exec_name ++ "-armv8.img";
3136
}
3237
}
3338
const os = builtin.Os.freestanding;
3439
const environ = builtin.Abi.eabihf;
3540
exe.setTarget(arch, os, environ);
3641
exe.addBuildOption(u32, "subarch", subarch);
3742
exe.addBuildOption(bool, "is_qemu", want_qemu);
38-
exe.setLinkerScriptPath(if (want_qemu) "src/linker-qemu.ld" else "src/linker.ld");
43+
exe.setLinkerScriptPath(if (want_qemu and subarch < 8) "src/linker-qemu.ld" else "src/linker.ld");
3944

4045
const run_objcopy = b.addSystemCommand([_][]const u8{
4146
"llvm-objcopy-6.0", exe.getOutputPath(),
@@ -47,14 +52,25 @@ pub fn build(b: *Builder) !void {
4752
b.default_step.dependOn(&run_objcopy.step);
4853

4954
var run_qemu_args = std.ArrayList([]const u8).init(b.allocator);
50-
try run_qemu_args.appendSlice([_][]const u8{
51-
"qemu-system-arm",
52-
"-kernel", exe.getOutputPath(),
53-
"-m", "256",
54-
"-M", "raspi2",
55-
"-serial", "stdio",
56-
"-display", if (want_nodisplay) "none" else "gtk",
57-
});
55+
if (!want_qemu) {
56+
try run_qemu_args.appendSlice([_][]const u8{
57+
"echo", "-Dqemu is required to run qemu",
58+
});
59+
} else if (subarch == 6) {
60+
try run_qemu_args.appendSlice([_][]const u8{
61+
"echo", "-Darmv6 will not run on qemu",
62+
});
63+
} else {
64+
try run_qemu_args.appendSlice([_][]const u8{
65+
if (subarch == 8) "qemu-system-aarch64" else "qemu-system-arm",
66+
"-kernel", exe.getOutputPath(),
67+
"-m", "256",
68+
"-M", if (subarch == 7) "raspi2" else "raspi3",
69+
"-serial", if (subarch == 8) "none" else "stdio",
70+
"-serial", if (subarch == 8) "stdio" else "none",
71+
"-display", if (want_nodisplay) "none" else "gtk",
72+
});
73+
}
5874
const run_qemu = b.addSystemCommand(run_qemu_args.toSliceConst());
5975
run_qemu.step.dependOn(&exe.step);
6076

release-message.md

+1
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@
1616
* apply power to the pi
1717
* you should see the zig logo displayed along with a changing banner of colored lines
1818
* if your tv has CEC (Consumer Electronics Control) then the frame buffer cursor will move in response to tv remote controller buttons
19+
* nearby ble (bluetooth low energy) devices should be listed on the screen

src/arm_assembly_code.zig

+136-41
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
pub const PERIPHERAL_BASE = if (build_options.subarch >= 7) 0x3F000000 else 0x20000000;
23

34
var already_panicking: bool = false;
@@ -28,8 +29,12 @@ pub fn io(comptime StructType: type, offset: u32) *volatile StructType {
2829

2930
pub fn hang(comptime format: []const u8, args: ...) noreturn {
3031
log(format, args);
32+
var time = milliseconds.read();
33+
while (!serial.isOutputQueueEmpty()) {
34+
serial.loadOutputFifo();
35+
}
3136
while (true) {
32-
if (build_options.subarch >= 7) {
37+
if (build_options.subarch >= 7) {
3338
v7.wfe();
3439
}
3540
}
@@ -47,25 +52,25 @@ pub const v7 = struct {
4752
}
4853
};
4954

50-
pub fn sp() u32 {
55+
pub fn sp() usize {
5156
var word = asm("mov %[word], sp"
5257
: [word] "=r" (-> usize));
5358
return word;
5459
}
5560

56-
pub fn cpsr() u32 {
61+
pub fn cpsr() usize {
5762
var word = asm("mrs %[word], cpsr"
5863
: [word] "=r" (-> usize));
5964
return word;
6065
}
6166

62-
pub fn spsr() u32 {
67+
pub fn spsr() usize {
6368
var word = asm("mrs %[word], spsr"
6469
: [word] "=r" (-> usize));
6570
return word;
6671
}
6772

68-
pub fn sctlr() u32 {
73+
pub fn sctlr() usize {
6974
var word = asm("mrc p15, 0, %[word], c1, c0, 0"
7075
: [word] "=r" (-> usize));
7176
return word;
@@ -89,38 +94,72 @@ pub fn dsbSt() void {
8994
}
9095

9196
pub fn setVectorBaseAddressRegister(address: u32) void {
92-
asm volatile("mcr p15, 0, %[address], cr12, cr0, 0"
93-
:
94-
: [address] "{r0}" (address)
95-
);
97+
if (build_options.subarch >= 8) {
98+
asm volatile("mcr p15, 0, %[address], cr12, cr0, 0"
99+
:
100+
: [address] "{x0}" (address)
101+
);
102+
} else {
103+
asm volatile("mcr p15, 0, %[address], cr12, cr0, 0"
104+
:
105+
: [address] "{r0}" (address)
106+
);
107+
}
96108
}
97109

98110
pub fn setCntfrq(word: u32) void {
99-
asm volatile("mcr p15, 0, %[word], c14, c0, 0"
100-
:
101-
: [word] "{r0}" (word)
102-
);
111+
if (build_options.subarch >= 8) {
112+
asm volatile("msr cntfrq_el0, %[word]"
113+
:
114+
: [word] "{x0}" (word)
115+
);
116+
} else {
117+
asm volatile("mcr p15, 0, %[word], c14, c0, 0"
118+
:
119+
: [word] "{r0}" (word)
120+
);
121+
}
103122
}
104123

105124
pub fn cntfrq() u32 {
106-
var word = asm("mrc p15, 0, %[word], c14, c0, 0"
107-
: [word] "=r" (-> usize));
108-
return word;
125+
var word: usize = undefined;
126+
if (build_options.subarch >= 8) {
127+
word = asm volatile("mrs %[word], cntfrq_el0"
128+
: [word] "=r" (-> usize)
129+
);
130+
} else {
131+
word = asm("mrc p15, 0, %[word], c14, c0, 0"
132+
: [word] "=r" (-> usize)
133+
);
134+
}
135+
return @truncate(u32, word);
109136
}
110137

111138
pub fn cntpct32() u32 {
112-
return asm("mrrc p15, 0, %[cntpct_low], r1, c14"
113-
: [cntpct_low] "=r" (-> usize)
114-
:
115-
: "r1"
116-
);
139+
var word: usize = undefined;
140+
if (build_options.subarch >= 8) {
141+
word = asm volatile("mrs %[word], cntpct_el0"
142+
: [word] "=r" (-> usize)
143+
);
144+
} else {
145+
word = asm("mrrc p15, 0, %[cntpct_low], r1, c14"
146+
: [cntpct_low] "=r" (-> usize)
147+
:
148+
: "r1"
149+
);
150+
}
151+
return @truncate(u32, word);
117152
}
118153

119154
// Loop count times in a way that the compiler won't optimize away.
120155
pub fn delay(count: usize) void {
121156
var i: usize = 0;
122157
while (i < count) : (i += 1) {
123-
asm volatile("mov r0, r0");
158+
if (build_options.subarch >= 8) {
159+
asm volatile("mov x0, x0");
160+
} else {
161+
asm volatile("mov r0, r0");
162+
}
124163
}
125164
}
126165

@@ -166,14 +205,15 @@ pub fn setBssToZero() void {
166205
@memset((*volatile [1]u8)(&__bss_start), 0, @ptrToInt(&__bss_end) - @ptrToInt(&__bss_start));
167206
}
168207

208+
169209
comptime {
170210
asm(
171211
\\.section .text.boot // .text.boot to keep this in the first portion of the binary
172212
\\.globl _start
173213
\\_start:
174214
);
175215

176-
if (build_options.subarch >= 7) {
216+
if (build_options.subarch == 7) {
177217
asm(
178218
\\ mrc p15, 0, r0, c0, c0, 5
179219
\\ and r0,#3
@@ -188,24 +228,79 @@ comptime {
188228
);
189229
}
190230

191-
asm(
192-
\\ cps #0x1f // enter system mode
193-
\\ mov sp,#0x08000000
194-
\\ bl kernelMain
195-
\\
196-
\\.section .text.exception_vector_table
197-
\\.balign 0x80
198-
\\exception_vector_table:
199-
\\ b exceptionEntry0x00
200-
\\ b exceptionEntry0x01
201-
\\ b exceptionEntry0x02
202-
\\ b exceptionEntry0x03
203-
\\ b exceptionEntry0x04
204-
\\ b exceptionEntry0x05
205-
\\ b exceptionEntry0x06
206-
\\ b exceptionEntry0x07
207-
);
231+
if (build_options.subarch <= 7) {
232+
asm(
233+
\\ cps #0x1f // enter system mode
234+
\\ mov sp,#0x08000000
235+
\\ bl kernelMain
236+
\\
237+
\\.section .text.exception_vector_table
238+
\\.balign 0x80
239+
\\exception_vector_table:
240+
\\ b exceptionEntry0x00
241+
\\ b exceptionEntry0x01
242+
\\ b exceptionEntry0x02
243+
\\ b exceptionEntry0x03
244+
\\ b exceptionEntry0x04
245+
\\ b exceptionEntry0x05
246+
\\ b exceptionEntry0x06
247+
\\ b exceptionEntry0x07
248+
);
249+
} else {
250+
asm(
251+
\\ mrs x0,mpidr_el1
252+
\\ mov x1,#0xC1000000
253+
\\ bic x0,x0,x1
254+
\\ cbz x0,master
255+
\\hang:
256+
\\ wfe
257+
\\ b hang
258+
\\master:
259+
\\ mov sp,#0x08000000
260+
\\ mov x0,#0x1000 //exception_vector_table
261+
\\ msr vbar_el3,x0
262+
\\ msr vbar_el2,x0
263+
\\ msr vbar_el1,x0
264+
\\ bl kernelMain
265+
\\.balign 0x800
266+
\\.section .text.exception_vector_table
267+
\\exception_vector_table:
268+
\\.balign 0x80
269+
\\ b exceptionEntry0x00
270+
\\.balign 0x80
271+
\\ b exceptionEntry0x01
272+
\\.balign 0x80
273+
\\ b exceptionEntry0x02
274+
\\.balign 0x80
275+
\\ b exceptionEntry0x03
276+
\\.balign 0x80
277+
\\ b exceptionEntry0x04
278+
\\.balign 0x80
279+
\\ b exceptionEntry0x05
280+
\\.balign 0x80
281+
\\ b exceptionEntry0x06
282+
\\.balign 0x80
283+
\\ b exceptionEntry0x07
284+
\\.balign 0x80
285+
\\ b exceptionEntry0x08
286+
\\.balign 0x80
287+
\\ b exceptionEntry0x09
288+
\\.balign 0x80
289+
\\ b exceptionEntry0x0A
290+
\\.balign 0x80
291+
\\ b exceptionEntry0x0B
292+
\\.balign 0x80
293+
\\ b exceptionEntry0x0C
294+
\\.balign 0x80
295+
\\ b exceptionEntry0x0D
296+
\\.balign 0x80
297+
\\ b exceptionEntry0x0E
298+
\\.balign 0x80
299+
\\ b exceptionEntry0x0F
300+
);
301+
}
208302
}
209303

210304
const build_options = @import("build_options");
211-
const log = @import("serial.zig").log;
305+
const log = serial.log;
306+
const serial = @import("serial.zig");

0 commit comments

Comments
 (0)