About
This is a non-exhaustive, curated list of changes meant to help users quickly see what has improved since they last checked.
You can subscribe to this page via RSS.
Changes
June 22, 2025
Regz Wizard
Regz is the program responsible for generating code to access MMIO within MicroZig. We’ve started building a GUI for it called Regz Wizard. It’s built on top of DVUI, and right now it displays the generated code for an ATDF or SVD file.
In the future it will aid in patching files. Keeping track of changes to an original register schema is important for when that schema is updated, and reproducing changes on similar hardware. Some projects exist just to provide consistent data structure between MCUs. This consistency makes it easier to write HALs that are portable across multiple MCUs.
June 19, 2025
June 18, 2025
Linker Script Generation
Every firmware needs a linker script that places stuff where it belongs in memory. When porting microzig to a new target you must face the challenge of dealing with a linker script. But fear not as microzig has your back (in most cases). Let’s checkout the linker_script
field in Target
.
linker_script: LinkerScript = .{},
pub const LinkerScript = struct {
/// Will anything be auto-generated for this linker script?
generate: GenerateOptions = .{ .memory_regions_and_sections = .{} },
/// Linker script path. Will be appended after what is auto-generated if it's not null.
file: ?LazyPath = null,
pub const GenerateOptions = union(enum) {
/// Only generates a comment with target info.
none,
/// Only generates memory regions.
memory_regions,
/// Generates memory regions and default sections based on the provided options.
memory_regions_and_sections: struct {
/// Where should rodata go?
rodata_location: enum {
/// Place rodata in the first region tagged as flash.
flash,
/// Place rodata in the first region tagged as ram.
ram,
} = .flash,
},
};
};
For an example let’s look at the target definition of rp2040. In this case we need a linker script that should also place the bootrom at the beginning of flash. Fortunately, we can still mostly auto-generate one and just patch it up a bit.
// port/raspberrypi/rp2xxx/build.zig
const chip_rp2040: microzig.Target = .{
// ...
.chip = .{
// ...
.memory_regions = &.{
.{ .tag = .flash, .offset = 0x10000000, .length = 2048 * 1024, .access = .rx },
.{ .tag = .ram, .offset = 0x20000000, .length = 256 * 1024, .access = .rwx },
},
},
.linker_script = .{
// The `generate` field defaults to `.memory_regions_and_sections`.
// This will be appended at the end of the auto-generated linker
// script.
.file = b.path("ld/rp2040/sections.ld"),
},
};
/* port/raspberrypi/rp2xxx/ld/rp2040/sections.ld */
SECTIONS
{
.boot2 : {
__boot2_start__ = .;
KEEP (*(.boot2))
__boot2_end__ = .;
} > flash0
ASSERT(__boot2_end__ - __boot2_start__ == 256,
"ERROR: Pico second stage bootloader must be 256 bytes in size")
}
INSERT BEFORE .flash_start;
This is the generated linker script:
/*
* Target CPU: cortex_m0plus
* Target Chip: RP2040
*/
/*
* This section was auto-generated by microzig.
*/
MEMORY
{
flash0 (rx!w) : ORIGIN = 0x10000000, LENGTH = 0x00200000
ram0 (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040000
}
SECTIONS
{
.flash_start :
{
KEEP(*(microzig_flash_start))
} > flash0
.text :
{
*(.text*)
*(.srodata*)
*(.rodata*)
} > flash0
.ARM.extab : {
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > flash0
.ARM.exidx : {
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > flash0
.data :
{
microzig_data_start = .;
*(.sdata*)
*(.data*)
KEEP(*(.ram_text))
microzig_data_end = .;
} > ram0 AT> flash0
.bss (NOLOAD) :
{
microzig_bss_start = .;
*(.sbss*)
*(.bss*)
microzig_bss_end = .;
} > ram0
.flash_end :
{
microzig_flash_end = .;
} > flash0
microzig_data_load_start = LOADADDR(.data);
}
/*
* End of auto-generated section.
*/
SECTIONS
{
.boot2 : {
__boot2_start__ = .;
KEEP (*(.boot2))
__boot2_end__ = .;
} > flash0
ASSERT(__boot2_end__ - __boot2_start__ == 256,
"ERROR: Pico second stage bootloader must be 256 bytes in size")
}
INSERT BEFORE .flash_start;
FYI
- If the ram memory region used by the linker script generator is executable, a
.ram_text
section will be included for code that should be placed in ram. This applies to the rp2040 target where the section tagged as ram is executable.