Embedded and Freestanding Programming
Target bare metal: -target thumb-freestanding-eabi -mcpu cortex_m0plus, no OS, no libc.
Provide your own entry point, vector table, linker script, and panic handler:
MicroZig (Zig Embedded Group): HAL, board support (RP2040/RP2350, STM32, nRF, ESP32-C3, ATSAMD), register generation from SVD files (regz), USB, flashing.
Use ReleaseSmall, FixedBufferAllocator, packed structs for registers, volatile MMIO, and interrupt handlers with callconv(.{ .arm_interrupt = .{} }) or similar.
export fn _start() callconv(.naked) noreturn {
asm volatile ("bl main");
while (true) {}
}
export fn main() noreturn {
const GPIO_OUT: *volatile u32 = @ptrFromInt(0x5000_0504);
while (true) {
GPIO_OUT.* ^= (1 << 13); // toggle an LED
var i: u32 = 0;
while (i < 100_000) : (i += 1) asm volatile ("nop");
}
}
pub fn panic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
_ = msg;
while (true) {}
}// build.zig snippet
exe.setLinkerScript(b.path("linker.ld"));
exe.entry = .{ .symbol_name = "_start" };
const bin = b.addObjCopy(exe.getEmittedBin(), .{ .format = .bin });
b.getInstallStep().dependOn(&b.addInstallBinFile(bin.getOutput(), "firmware.bin").step);