@@ -15,38 +15,23 @@ pub const PAGE_SIZE = 256;
1515pub const SECTOR_SIZE = 4096 ;
1616pub const BLOCK_SIZE = 65536 ;
1717
18- /// Bus reads to a 16MB memory window start at this address
18+ /// Bus reads to a 16MB memory window start at this address.
1919pub const XIP_BASE = 0x10000000 ;
2020
21- /// After the bootrom enters the user application, it contains also a copy of
22- /// the flash XIP setup function .
21+ /// After the bootrom enters the user application, a copy of the flash XIP
22+ /// setup function is found here on RP2350 .
2323pub const BOOTRAM_BASE = 0x400e0000 ;
2424
25- /// Flash code related to the second stage boot loader
26- pub const boot2 = if (! microzig .config .ram_image ) struct {
27- /// Size of the second stage bootloader in words
25+ /// Infrastructure for reentering XIP mode after exiting for programming.
26+ pub const boot2 = if (! microzig .config .ram_image and compatibility .arch == .arm ) struct {
2827 const BOOT2_SIZE_WORDS = 64 ;
2928
30- /// Buffer for the second stage bootloader
31- ///
32- /// The only job of the second stage bootloader is to configure the SSI and
33- /// the external flash for the best possible execute-in-place (XIP)
34- /// performance. Until the SSI is correctly configured for the attached
35- /// flash device, it's not possible to access flash via the XIP address
36- /// window, i.e., we have to copy the bootloader into sram before calling
37- /// `rom.flash_exit_xip`. This is required if we want to erase and/or write
38- /// to flash.
39- ///
40- /// At the end we can then just make a subroutine call to copyout, to
41- /// configure the SSI and flash. The second stage bootloader will return to
42- /// the calling function if a return address is provided in `lr`.
4329 var copyout : [BOOT2_SIZE_WORDS ]u32 = undefined ;
4430 var copyout_valid : bool = false ;
4531
46- /// Copy the 2nd stage bootloader into memory
47- ///
48- /// This is required by `_range_erase` and `_range_program` so we can later
49- /// setup XIP via the second stage bootloader.
32+ /// Copies the XIP setup function into RAM:
33+ /// - On RP2040 this *is* the second stage bootloader
34+ /// - On RP2350 it is found at BOOTRAM_BASE.
5035 pub export fn flash_init () linksection (".ram_text" ) void {
5136 if (copyout_valid ) return ;
5237 const bootloader = @as ([* ]u32 , @ptrFromInt (switch (compatibility .chip ) {
@@ -61,25 +46,23 @@ pub const boot2 = if (!microzig.config.ram_image) struct {
6146 copyout_valid = true ;
6247 }
6348
64- /// Configure the SSI and the external flash for XIP by calling the second
65- /// stage bootloader that was copied out to `copyout`.
49+ /// Configure the SSI and the external flash for XIP using the XIP setup
50+ /// function that was copied out to `copyout`.
6651 pub export fn flash_enable_xip () linksection (".ram_text" ) void {
67- const f : * const fn () callconv (.c ) void = @ptrCast (& copyout );
68- f ();
52+
53+ // Calling boot2 as a function works because it accepts a return vector in
54+ // LR (and doesn't trash r4-r7). Bootrom passes NULL in LR, instructing
55+ // boot2 to enter flash vector table's reset handler.
56+ @as (* const fn () callconv (.c ) void , @ptrFromInt (@intFromPtr (& copyout ) + 1 ))();
6957 }
7058} else struct {
7159 // no op
7260 pub inline fn flash_init () linksection (".ram_text" ) void {}
7361
74- /// Configure the SSI and the external flash for XIP by calling the second
75- /// stage bootloader embedded into RAM .
62+ // Fallback. This is a very slow XIP configuration, but is very widely
63+ // supported .
7664 pub inline fn flash_enable_xip () linksection (".ram_text" ) void {
77- if (compatibility .chip == .RP2040 and @hasDecl (microzig .board , "bootrom" )) {
78- const f : * const fn () callconv (.c ) void = @ptrCast (microzig .board .bootrom .stage2_rom .ptr );
79- f ();
80- } else {
81- rom .flash_enter_cmd_xip ();
82- }
65+ rom .flash_enter_cmd_xip ();
8366 }
8467};
8568
0 commit comments