The job of the second stage boot is not what I would have expected (namely to load more stuff into SRAM). Instead, its job is to set up the XIP hardware to run code directly out of flash. So, it is not a "loader" at all, and I need to break my habit of calling it such.
Why couldn't the first stage boot do this? Well, it could (had they programmed it this way). Having the second stage boot on flash allows a different second stage for different flash chips.
The Pico ships with a Winbond W25Q16JV chip. This is a 16 megabit (2 megabyte) flash chip.
I spent some time studying the Pico SDK to learn more about the second stage boot. First of all, it fits into 256 bytes. The source can be found at:
pico-sdk/src/rp2_common/boot_stage2If you look at this directory, you will find source files for several different (5 at this time) second stage boot files:
boot2_usb_blinky.S boot2_generic_03h.S boot2_at25sf128a.S boot2_w25q080.S boot2_is25lp080.S boot2_w25x10cl.SThe first is not really a boot at all, but a demo that runs as second stage boot. The "generic" file is what I at first thought gets compiled for the pico. It is not -- the "at25sf128a" file is what is used (see below). This leaves us with 4 others, corresponding to other flash chips:
w25q16jv -- 16 Mbit - the chip we have on the Pico at25sf128a -- 128 Mbit SPI flash (16 Mbyte) Renesas electronis w25q080 -- 8 Mbit (1 Mbyte) flash - Winbond is25lp080 -- 8 Mbit (1 Mbyte) flash - ISSI w25x10cl -- 1 Mbit nor flash -- WinbondExcept for the 128 Mbit chip, these are all odd small chips that we don't expect to see.
The 03h (aka 0x03) command is apparently the flash read command.
Two things ought to be noted. One is that this "compiles" something called "compile_time_choice.S". In our case this ends up being exactly "boot2_at25sf128a.S" via a complex tangle of conditional code. The "chooser" just includes one of the other files, as governed by compile time switches.
The second thing is the output, namely "bs2_default_padded_checksummed.S". This is a binary blob repackaged by the python script "pad_checksum" in an interesting way. The padding is done with zero bytes and room is left for a 4 byte checksum, which is appended. The original binary is 240 bytes, so this works out just fine.
The build products all end up in
/u1/Projects/rp2040/pico-examples/build/pico-sdk/src/rp2_common/boot_stage2
Of particular interest there is bs2_default.dis. Of course you should avail yourself of the original source code, but the buck stops here. The build process is complex and you may miss certain things, all of which will be found here.
Indeed, examining this corrected me with regard to the boot2_*.S assembly file in use. It is actually the at25sf128a.S file and not the generic_03h file like I first thought!!
cd /u1/Projects/rp2040/pico-examples/build make -f pico-sdk/src/rp2_common/boot_stage2/CMakeFiles/bs2_default.dir/build.make pico-sdk/src/rp2_common/boot_stage2/CMakeFiles/bs2_default.dir/build cd /u1/Projects/rp2040/pico-examples/build/pico-sdk/src/rp2_common/boot_stage2 /usr/bin/arm-none-eabi-gcc -DPICO_BOARD=\"pico\" -DPICO_BUILD=1 -DPICO_NO_HARDWARE=0 -DPICO_ON_DEVICE=1 -I/u1/Projects/rp2040/pico-sdk/src/rp2_common/boot_stage2/asminclude -I/u1/Projects/rp2040/pico-sdk/src/rp2040/hardware_regs/include -I/u1/Projects/rp2040/pico-sdk/src/rp2_common/hardware_base/include -I/u1/Projects/rp2040/pico-sdk/src/common/pico_base/include -I/u1/Projects/rp2040/pico-examples/build/generated/pico_base -I/u1/Projects/rp2040/pico-sdk/src/boards/include -I/u1/Projects/rp2040/pico-sdk/src/rp2_common/pico_platform/include -I/u1/Projects/rp2040/pico-sdk/src/rp2_common/boot_stage2/include -mcpu=cortex-m0plus -mthumb -O3 -DNDEBUG -o CMakeFiles/bs2_default.dir/compile_time_choice.S.obj -c /u1/Projects/rp2040/pico-sdk/src/rp2_common/boot_stage2/compile_time_choice.S /usr/bin/cmake -E cmake_link_script CMakeFiles/bs2_default.dir/link.txt --verbose=xxx /usr/bin/arm-none-eabi-gcc -mcpu=cortex-m0plus -mthumb -O3 -DNDEBUG -Wl,--build-id=none --specs=nosys.specs -nostartfiles -Wl,--script=/u1/Projects/rp2040/pico-sdk/src/rp2_common/boot_stage2/boot_stage2.ld -Wl,-Map=bs2_default.elf.map CMakeFiles/bs2_default.dir/compile_time_choice.S.obj -o bs2_default.elf /usr/bin/arm-none-eabi-objdump -h /u1/Projects/rp2040/pico-examples/build/pico-sdk/src/rp2_common/boot_stage2/bs2_default.elf > bs2_default.dis /usr/bin/arm-none-eabi-objdump -d /u1/Projects/rp2040/pico-examples/build/pico-sdk/src/rp2_common/boot_stage2/bs2_default.elf >> bs2_default.dis make -f pico-sdk/src/rp2_common/boot_stage2/CMakeFiles/bs2_default_padded_checksummed_asm.dir/build.make pico-sdk/src/rp2_common/boot_stage2/CMakeFiles/bs2_default_padded_checksummed_asm.dir/build cd /u1/Projects/rp2040/pico-examples/build/pico-sdk/src/rp2_common/boot_stage2 /usr/bin/arm-none-eabi-objcopy -Obinary /u1/Projects/rp2040/pico-examples/build/pico-sdk/src/rp2_common/boot_stage2/bs2_default.elf /u1/Projects/rp2040/pico-examples/build/pico-sdk/src/rp2_common/boot_stage2/bs2_default.bin /usr/bin/python3.11 /u1/Projects/rp2040/pico-sdk/src/rp2_common/boot_stage2/pad_checksum -s 0xffffffff /u1/Projects/rp2040/pico-examples/build/pico-sdk/src/rp2_common/boot_stage2/bs2_default.bin /u1/Projects/rp2040/pico-examples/build/pico-sdk/src/rp2_common/boot_stage2/bs2_default_padded_checksummed.S
Tom's electronics pages / tom@mmto.org