Skip to content

Commit eede411

Browse files
GrazfatherUthedris
authored andcommitted
Add rp2040 ram image (flashless) target board (ZigEmbeddedGroup#535)
1 parent 3a7b670 commit eede411

File tree

7 files changed

+143
-45
lines changed

7 files changed

+143
-45
lines changed

build-internals/build.zig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ pub const Target = struct {
5757
/// (optional) Provide a custom linker script for the hardware or define a custom generation.
5858
linker_script: ?LazyPath = null,
5959

60+
/// (Optional) Explicitly set the entry point
61+
entry: ?Build.Step.Compile.Entry = null,
62+
6063
/// (optional) Post processing step that will patch up and modify the elf file if necessary.
6164
patch_elf: ?*const fn (*Build.Dependency, LazyPath) LazyPath = null,
6265

@@ -71,6 +74,7 @@ pub const Target = struct {
7174
hal: ?HardwareAbstractionLayer = null,
7275
board: ?Board = null,
7376
linker_script: ?LazyPath = null,
77+
entry: ?Build.Step.Compile.Entry = null,
7478
patch_elf: ?*const fn (*Build.Dependency, LazyPath) LazyPath = null,
7579
};
7680

@@ -88,6 +92,7 @@ pub const Target = struct {
8892
.hal = options.hal orelse from.hal,
8993
.board = options.board orelse from.board,
9094
.linker_script = options.linker_script orelse from.linker_script,
95+
.entry = options.entry orelse from.entry,
9196
.patch_elf = options.patch_elf orelse from.patch_elf,
9297
};
9398
return ret;

build.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,9 @@ pub fn MicroBuild(port_select: PortSelect) type {
332332
/// If set, overrides the `linker_script` property of the target.
333333
linker_script: ?LazyPath = null,
334334

335+
/// If set, overrides the default `entry` property of the arget.
336+
entry: ?Build.Step.Compile.Entry = null,
337+
335338
/// Strips stack trace info from final executable.
336339
strip: bool = false,
337340

@@ -538,6 +541,7 @@ pub fn MicroBuild(port_select: PortSelect) type {
538541
fw.artifact.link_gc_sections = options.strip_unused_symbols;
539542
fw.artifact.link_function_sections = options.strip_unused_symbols;
540543
fw.artifact.link_data_sections = options.strip_unused_symbols;
544+
fw.artifact.entry = options.entry orelse target.entry orelse .default;
541545

542546
fw.artifact.root_module.addImport("microzig", core_mod);
543547
fw.artifact.root_module.addImport("app", app_mod);

core/src/cpus/cortex_m.zig

Lines changed: 69 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -587,49 +587,68 @@ pub const startup_logic = struct {
587587
extern var microzig_bss_end: u8;
588588
extern const microzig_data_load_start: u8;
589589

590+
pub fn ram_image_entrypoint() linksection(".entry") callconv(.naked) void {
591+
asm volatile (
592+
\\
593+
// Set VTOR to point to ram table
594+
\\mov r0, %[_vector_table]
595+
\\mov r1, %[_VTOR_ADDRESS]
596+
\\str r0, [r1]
597+
// Set up stack and jump to _start
598+
\\ldm r0!, {r1, r2}
599+
\\msr msp, r1
600+
\\bx r2
601+
:
602+
: [_vector_table] "r" (&startup_logic._vector_table),
603+
[_VTOR_ADDRESS] "r" (&peripherals.scb.VTOR),
604+
: "memory", "r0", "r1", "r2"
605+
);
606+
}
607+
590608
pub fn _start() callconv(.c) noreturn {
609+
if (comptime !is_ramimage()) {
610+
// fill .bss with zeroes
611+
{
612+
const bss_start: [*]u8 = @ptrCast(&microzig_bss_start);
613+
const bss_end: [*]u8 = @ptrCast(&microzig_bss_end);
614+
const bss_len = @intFromPtr(bss_end) - @intFromPtr(bss_start);
615+
616+
@memset(bss_start[0..bss_len], 0);
617+
}
591618

592-
// fill .bss with zeroes
593-
{
594-
const bss_start: [*]u8 = @ptrCast(&microzig_bss_start);
595-
const bss_end: [*]u8 = @ptrCast(&microzig_bss_end);
596-
const bss_len = @intFromPtr(bss_end) - @intFromPtr(bss_start);
619+
// load .data from flash
620+
{
621+
const data_start: [*]u8 = @ptrCast(&microzig_data_start);
622+
const data_end: [*]u8 = @ptrCast(&microzig_data_end);
623+
const data_len = @intFromPtr(data_end) - @intFromPtr(data_start);
624+
const data_src: [*]const u8 = @ptrCast(&microzig_data_load_start);
597625

598-
@memset(bss_start[0..bss_len], 0);
599-
}
626+
@memcpy(data_start[0..data_len], data_src[0..data_len]);
627+
}
600628

601-
// load .data from flash
602-
{
603-
const data_start: [*]u8 = @ptrCast(&microzig_data_start);
604-
const data_end: [*]u8 = @ptrCast(&microzig_data_end);
605-
const data_len = @intFromPtr(data_end) - @intFromPtr(data_start);
606-
const data_src: [*]const u8 = @ptrCast(&microzig_data_load_start);
629+
// Move vector table to RAM if requested
630+
if (interrupt.has_ram_vectors()) {
631+
// Copy vector table to RAM and set VTOR to point to it
607632

608-
@memcpy(data_start[0..data_len], data_src[0..data_len]);
609-
}
633+
if (comptime interrupt.has_ram_vectors_section()) {
634+
@export(&ram_vectors, .{
635+
.name = "_ram_vectors",
636+
.section = "ram_vectors",
637+
.linkage = .strong,
638+
});
639+
} else {
640+
@export(&ram_vectors, .{
641+
.name = "_ram_vectors",
642+
.linkage = .strong,
643+
});
644+
}
610645

611-
// Move vector table to RAM if requested
612-
if (interrupt.has_ram_vectors()) {
613-
// Copy vector table to RAM and set VTOR to point to it
614-
615-
if (interrupt.has_ram_vectors_section()) {
616-
@export(&ram_vectors, .{
617-
.name = "_ram_vectors",
618-
.section = "ram_vectors",
619-
.linkage = .strong,
620-
});
621-
} else {
622-
@export(&ram_vectors, .{
623-
.name = "_ram_vectors",
624-
.linkage = .strong,
625-
});
626-
}
627-
628-
const flash_vector: [*]const usize = @ptrCast(&_vector_table);
646+
const flash_vector: [*]const usize = @ptrCast(&_vector_table);
629647

630-
@memcpy(ram_vectors[0..vector_count], flash_vector[0..vector_count]);
648+
@memcpy(ram_vectors[0..vector_count], flash_vector[0..vector_count]);
631649

632-
peripherals.scb.VTOR = @intFromPtr(&ram_vectors);
650+
peripherals.scb.VTOR = @intFromPtr(&ram_vectors);
651+
}
633652
}
634653

635654
microzig_main();
@@ -655,14 +674,28 @@ pub const startup_logic = struct {
655674
};
656675
};
657676

677+
fn is_ramimage() bool {
678+
// HACK
679+
// TODO: Use microzig_options?
680+
if (microzig.config.board_name) |board_name|
681+
return std.mem.containsAtLeast(u8, board_name, 1, "ram image");
682+
return false;
683+
}
684+
658685
pub fn export_startup_logic() void {
686+
if (is_ramimage())
687+
@export(&startup_logic.ram_image_entrypoint, .{
688+
.name = "_entry_point",
689+
.linkage = .strong,
690+
});
691+
659692
@export(&startup_logic._start, .{
660693
.name = "_start",
661694
});
662695

663696
@export(&startup_logic._vector_table, .{
664697
.name = "_vector_table",
665-
.section = "microzig_flash_start",
698+
.section = ".isr_vector",
666699
.linkage = .strong,
667700
});
668701
}

examples/raspberrypi/rp2xxx/build.zig

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub fn build(b: *std.Build) void {
1212
const mz_dep = b.dependency("microzig", .{});
1313
const mb = MicroBuild.init(b, mz_dep) orelse return;
1414

15-
const rp2040_only_examples: []const Example = &.{
15+
const specific_examples: []const Example = &.{
1616
// RaspberryPi Boards:
1717
.{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_flash-program", .file = "src/rp2040_only/flash_program.zig" },
1818
.{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_flash-id", .file = "src/rp2040_only/flash_id.zig" },
@@ -23,18 +23,15 @@ pub fn build(b: *std.Build) void {
2323
.{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_hd44780", .file = "src/rp2040_only/hd44780.zig" },
2424
.{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_pcf8574", .file = "src/rp2040_only/pcf8574.zig" },
2525
.{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_i2c_slave", .file = "src/rp2040_only/i2c_slave.zig" },
26+
.{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico_flashless, .name = "pico_flashless_blinky", .file = "src/blinky.zig" },
2627

2728
// WaveShare Boards:
28-
.{ .target = mb.ports.rp2xxx.boards.waveshare.rp2040_matrix, .name = "rp2040-matrix_tiles", .file = "src/rp2040_only/tiles.zig" },
29+
.{ .target = mb.ports.rp2xxx.boards.waveshare.rp2040_matrix, .name = "rp2040_matrix_tiles", .file = "src/rp2040_only/tiles.zig" },
2930
// .{ .target = "board:waveshare/rp2040_eth", .name = "rp2040-eth" },
3031
// .{ .target = "board:waveshare/rp2040_plus_4m", .name = "rp2040-plus-4m" },
3132
// .{ .target = "board:waveshare/rp2040_plus_16m", .name = "rp2040-plus-16m" },
3233
};
3334

34-
const rp2350_only_examples: []const Example = &.{
35-
// TODO: No RP2350 feature specific examples to show off yet
36-
};
37-
3835
const chip_agnostic_examples: []const ChipAgnosticExample = &.{
3936
.{ .name = "adc", .file = "src/adc.zig" },
4037
.{ .name = "i2c-bus-scan", .file = "src/i2c_bus_scan.zig" },
@@ -60,8 +57,7 @@ pub fn build(b: *std.Build) void {
6057
};
6158

6259
var available_examples = std.ArrayList(Example).init(b.allocator);
63-
available_examples.appendSlice(rp2040_only_examples) catch @panic("out of memory");
64-
available_examples.appendSlice(rp2350_only_examples) catch @panic("out of memory");
60+
available_examples.appendSlice(specific_examples) catch @panic("out of memory");
6561
for (chip_agnostic_examples) |example| {
6662
available_examples.append(.{
6763
.target = mb.ports.rp2xxx.boards.raspberrypi.pico,

port/raspberrypi/rp2xxx/build.zig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ boards: struct {
1515
},
1616
raspberrypi: struct {
1717
pico: *const microzig.Target,
18+
pico_flashless: *const microzig.Target,
1819
pico2_arm: *const microzig.Target,
1920
pico2_riscv: *const microzig.Target,
2021
},
@@ -163,6 +164,15 @@ pub fn init(dep: *std.Build.Dependency) Self {
163164
.imports = rp2040_bootrom_imports,
164165
},
165166
}),
167+
.pico_flashless = chip_rp2040.derive(.{
168+
.entry = .{ .symbol_name = "_entry_point" },
169+
.linker_script = b.path("rp2040_ram_image.ld"),
170+
.board = .{
171+
.name = "RaspberryPi Pico (ram image)",
172+
.url = "https://www.raspberrypi.com/products/raspberry-pi-pico/",
173+
.root_source_file = b.path("src/boards/raspberry_pi_pico2.zig"),
174+
},
175+
}),
166176
.pico2_arm = chip_rp2350_arm.derive(.{
167177
.board = .{
168178
.name = "RaspberryPi Pico 2",

port/raspberrypi/rp2xxx/rp2040.ld

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ SECTIONS
2626

2727
.text :
2828
{
29-
KEEP(*(microzig_flash_start))
29+
KEEP(*(.isr_vector))
3030
*(.text*)
3131
*(.rodata*)
3232
} > flash0
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Target CPU: ARM Cortex-M0+
3+
* Target Chip: RP2040
4+
*/
5+
6+
MEMORY
7+
{
8+
entry (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00000100
9+
ram0 (rwx) : ORIGIN = 0x20000100, LENGTH = 0x0003ff00
10+
}
11+
12+
SECTIONS
13+
{
14+
.entry :
15+
{
16+
KEEP(*(.entry))
17+
} > entry
18+
19+
.text :
20+
{
21+
KEEP(*(.isr_vector))
22+
*(.text*)
23+
*(.rodata*)
24+
} > ram0
25+
26+
.ARM.extab : {
27+
*(.ARM.extab* .gnu.linkonce.armextab.*)
28+
} > ram0
29+
30+
.ARM.exidx : {
31+
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
32+
} > ram0
33+
34+
.data :
35+
{
36+
*(.data*)
37+
} > ram0
38+
39+
.bss :
40+
{
41+
*(.bss*)
42+
} > ram0
43+
44+
/* Unused, but set as extern in startup_logic */
45+
microzig_data_start = .;
46+
microzig_data_end = .;
47+
microzig_bss_start = .;
48+
microzig_bss_end = .;
49+
microzig_data_load_start = .;
50+
}

0 commit comments

Comments
 (0)