raspberrypi / pico-bootrom Goto Github PK
View Code? Open in Web Editor NEWLicense: Other
License: Other
I have issues using Elm Cham's fatfs to mount pico's uf2 disk and figure out that Boot sector doesn't include FAT signature 55-AA at offset 510. Current implementation has FAT signature at MBR which is not correct/enough
https://github.com/raspberrypi/pico-bootrom/blob/master/bootrom/virtual_disk.c#L295
ideally would be defined here
https://github.com/raspberrypi/pico-bootrom/blob/master/bootrom/virtual_disk.c#L63
static const uint8_t boot_sector[] = {
// existing code
[510] = 0x55,
[511] = 0xAA
}
If you think the change make sense I could make an PR for it.
Hello,
The blackmagic debugger now handles multidrop, detects the RP Pico and implement Erase/flash via the ROM functions via the trampoline via the debugger: blackmagic-debug/blackmagic#843
As test, I use the debug build of pico-examples/blink. Flashing with BMP hosted like "blackmagic blink/blink.bin" mostly works. However often, the first call to _connect_internal_flash() fails and PC ends up as 0x100001c4, that is the hardfault handler of blink. Running with the bmp gdb server in firmware always fail, here no usb transactions happen but introducings delay did not help neither.
Any hints welcome!
The bootrom function _reset_to_usb_boot
(code 'U', 'B') fails to reboot to USB if the XOSC is not running.
This seems to be caused by the use of watchdog_reboot(), which switches to this oscillator without checking if it is running: https://github.com/raspberrypi/pico-bootrom/blob/master/usb_device_tiny/runtime.c#L94-L96
(called from https://github.com/raspberrypi/pico-bootrom/blob/master/bootrom/bootrom_main.c#L222)
As a workaround, before calling the bootrom function, the oscillator should be started if it's not running. (It's not necessary to switch to the XOSC oscillator.)
It may also be necessary to ensure other parts of the clock configuration are compatible with the XOSC oscillator. I didn't check that. However, the default configuration after bootup is compatible, it's only missing the XOSC startup.
I tried building the bootrom on Windows and LInux, booth builds faile with the same error (windows example):
[build] c:/progra~2/armgnu~1/112202~1.02/bin/../lib/gcc/arm-none-eabi/11.2.1/../../../../arm-none-eabi/bin/ld.exe: bootrom.elf section `.text' will not fit in region `ROM'
[build] c:/progra~2/armgnu~1/112202~1.02/bin/../lib/gcc/arm-none-eabi/11.2.1/../../../../arm-none-eabi/bin/ld.exe: region `ROM' overflowed by 16384 bytes
[build] collect2.exe: error: ld returned 1 exit status
[build] NMAKE : fatal error U1077: "C:\PROGRA~2\ARMGNU~1\112202~1.02\bin\AR19DD~1.EXE": R³ckgabe-Code "0x1"
[build] Stop.
[build] NMAKE : fatal error U1077: ""C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.27.29110\bin\HostX86\x86\nmake.exe"": R³ckgabe-Code "0x2"
[build] Stop.
[build] NMAKE : fatal error U1077: ""C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.27.29110\bin\HostX86\x86\nmake.exe"": R³ckgabe-Code "0x2"
[build] Stop.
[build] Build finished with exit code 2
steps to reproduce:
git clone https://github.com/raspberrypi/pico-bootrom
cd pico-bootrom
git submodule update --init
mkdir build
cd build
cmake ..
make -j4
Hi,
We are trying to flash the pico with an esp32s3 and a sd card.
The esp32 setup can copy the uf2 to a usb flash drive and the destination file matches the original.
When the pico is plugged in place of the flash drive, it enumerates. I can read a text file from it and copy up to 1036288 bytes worth of the uf2 to it. After this it fails with i/o error (errno=5).
The esp32 usb host stack does not trigger a single error.
Any ideas on what else I can try?
Thank you.
For your curiosity, there is a fine ongoing effort (by someone else) to understand and document bootrom_rt0.S
assembly here: https://news.ycombinator.com/item?id=30970274
Just linking the two posts together.
Enjoy!
See below for the full error message.
/usr/lib/gcc/arm-none-eabi/10.2.0/../../../../arm-none-eabi/bin/ld: bootrom.elf section `.text' will not fit in region `ROM'
/usr/lib/gcc/arm-none-eabi/10.2.0/../../../../arm-none-eabi/bin/ld: region `ROM' overflowed by 16384 bytes
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
I was working with a colleague on a guide to using an ipad text editor with CircuitPython. We ran into trouble when an RP2040 board was plugged in that was never flashed, the ipad's operating system would say that it couldn't successfully power the device. For more info: https://blog.adafruit.com/2022/05/11/new-guide-edit-circuitpython-code-on-ios-with-runestone-adafruitlearningsystem-adafruit-circuitpython-simonbs-makermelissa/
I assume (did not measure) that the device would not exceed 100mA in bootloader mode. If so, the current limit should be lowered. 100mA request may improve compatibility with un-powered hubs or with OTG devices like an ipad.
Note that we haven't been able to successfully uf2-flash a device from an ipad, but not getting the scary power warning would be nice.
When we reboot into RAM we indicate this via
watchdog_hw->scratch[4] = 0xb007c0d3;
watchdog_hw->scratch[5] = pc ^ -0xb007c0d3;
watchdog_hw->scratch[6] = sp;
watchdog_hw->scratch[7] = pc;
however on rebooting into flash we only reset scratch[4]
to 0 (which is also done on the watchdog boot path in the bootrom).
It would be nice to be able to detect a bootrom reset vs another type of watchdog reset explicitly.
is_address_rom
only returns true for addresses between 0 and 8191 inclusive, however we ROM area is 16 KiB. This causes reads to the bootrom area (with READ commands from the PICOBOOT interface) to fail if we try to read anything in the 8191 to 16384 range. Note that it is not possible to read address 8191 since the READ command checks for is_address_rom(address + size)
.
The function should check <= 16384
instead of < 8192
.
A possible workaround is to use EXEC commands to copy the ROM area to RAM and then READ from RAM.
Just FYI if somebody runs into this problem.
I realize that this would mean a ROM change, and I'm not sure how important it is, but...
As I understand it, if you load a UF2 file that contains only RAM content, the bootloader will assume that it is a run-from-ram binary and start it at the lowest address that has been loaded:
pico-bootrom/bootrom/virtual_disk.c
Line 161 in d37cc82
if (!task->result && _uf2_info.valid_block_count == _uf2_info.num_blocks) {
safe_reboot(_uf2_info.ram ? _uf2_info.lowest_addr : 0, SRAM_END, 1000); //300); // reboot in 300 ms
}
This is ok, but is incompatible with "standard" cortex binaries that have the "initial stack pointer" in the vector table at their lowest location.
I think it would only require a little bit of code for either the WD reset code, or the bootrom that sets it up, to notice that the first lword in the binary looks more like a Initial SP value than code, and take appropriate action to support bother traditional cortex binaries as well as the Pico-SDK style RAM binaries.
With the RP2040 in bootloader mode, one gets:
$ sg_inq --only /dev/sdb
standard INQUIRY:
PQual=0 PDT=0 RMB=1 LU_CONG=0 hot_pluggable=0 version=0x02 [SCSI-2]
[AERC=0] [TrmTsk=0] NormACA=0 HiSUP=0 Resp_data_format=2
SCCS=0 ACC=0 TPGS=0 3PC=0 Protect=0 [BQue=0]
EncServ=0 MultiP=0 [MChngr=0] [ACKREQQ=0] Addr16=0
[RelAdr=0] WBus16=0 Sync=0 [Linked=0] [TranDis=0] CmdQue=0
length=37 (0x25), but only fetched 36 bytes Peripheral device type: disk
Vendor identification: RPI
Product identification: RP2
Product revision level: 2
Note that the length=37
but it should be 36.
The issue is this line: https://github.com/raspberrypi/pico-bootrom/blob/master/usb_device_tiny/scsi_ir.h#L32
The - 4
should be a - 5
.
Originally discussed here: hathach/tinyusb#1349
Trying to do this:
dd if=/dev/urandom of=random.bin bs=1024 count=100
uf2conv.py -b 0x10020100 -o random.uf2 -c -f RP2040 random.bin
cp random.uf2 /mnt/uf2 && sync
Note that address starts at 0x10020100: after reboot, content between 0x****000
and 0x***100
stays unchanged (0xFFFFFFFF), shown as following:
( see https://gist.github.com/juju2013/6e5d129effd3e7d3b43a6bc8973306ff )
$10020100 ........ $10021000 FFFFFFFF $10021100 ........ $10022000 FFFFFFFF $10022100 ........ $10023000 FFFFFFFF $10023100 ........ $10024000 FFFFFFFF $10024100 ........ $10025000 FFFFFFFF $10025100 ........ $10026000 FFFFFFFF $10026100 ........ $10027000 FFFFFFFF $10027100 ........ $10028000 FFFFFFFF $10028100 ........ $10029000 FFFFFFFF $10029100 ........ $1002A000 FFFFFFFF
If that address starts at a 4K boundary, content flashed as expected.
Documentation says ( 2.8.3.2. UF2 Format Details ):
Note that flash is erased a 4K sector at a time, so writing to only a subset of a 4K flash sector will leave the rest of that flash sector undefined. Beyond that there is no requirement that a binary be contiguous.
The sources are a great resource. Perhaps the project could also publish binaries under "Release". The ELF corresponding to the mask ROM binary would be most useful for various purposes, not least of which is comparing against independent builds from source.
Hi,
I fully understand that this will not happen quickly due to the cost and complexity of revving your mask ROM. But if you do get around to it I would ask that you consider the following:
As early as possible, ideally before pushing anything onto the stack, make a basic memory test (set 1's, verify, set 0's, verify) on the last 1K block of SRAM (enough to cover 2nd stage bootloader and stack below it). If any memory test fails then move to the next 1K block, and so on. Only set the stack pointer after checking that the SRAM is ready to go. It would ensure that first stage stack and the second stage stack are not corrupted.
Thanks for listening,
Jonathan
void __noinline flash_read_data(uint32_t addr, uint8_t *rx, size_t count) {
assert(addr < 0x1000000);
flash_put_cmd_addr(FLASHCMD_READ_DATA, addr);
flash_put_get(NULL, rx, count, 4);
}
Here is the disassembly of what appears in the v1 mask ROM:
flash_read_data:
17e0: b510 push {r4, lr}
17e2: 000c movs r4, r1
17e4: 0001 movs r1, r0
17e6: 2003 movs r0, #3
17e8: f7ff f9da bl 0xba0 ; flash_put_cmd_addr
17ec: 2280 movs r2, #128 ; 0x80
17ee: 2304 movs r3, #4
17f0: 0021 movs r1, r4
17f2: 2000 movs r0, #0
17f4: 0052 lsls r2, r2, #1
17f6: f7ff ffbf bl 0x1778 ; flash_put_get
17fa: bd10 pop {r4, pc}
One will notice that upon entry: r0=addr
, r1=rx
, and r2=count
. r4
is used as a temporary. Argument shuffling is done prior to the call of flash_put_cmd_addr( )
, which proceeds as expected. However, notice what happens to the arguments for flash_put_get( )
. r0=0
(NULL), r1=rx
(previously saved in r4
), r3=4
. But r2=0x80<<1=256
!
The build appears to have optimized flash_read_data( )
to perform only count=256
.
This is not an outright bug. But it certainly makes flash_read_data( )
not work as advertised, should it ever be called from outside the mask ROM (which is exactly what I had wished to do in a custom 2nd stage bootloader).
From section 2.19.4 of datasheet:
Both the output signal level and acceptable input signal level at the pad are determined by the digital IO supply (IOVDD).
IOVDD can be any nominal voltage between 1.8V and 3.3V, but to meet specification when powered at 1.8V, the pad
input thresholds must be adjusted by writing a 1 to the pad VOLTAGE_SELECT registers. By default the pad input thresholds
are valid for an IOVDD voltage between 2.5V and 3.3V. Using a voltage of 1.8V with the default input thresholds is a safe
operating mode, though it will result in input thresholds that don’t meet specification.
Context:
https://forums.raspberrypi.com/viewtopic.php?t=328887
Would be nice to use a GPIO during bootloader to set this. A simple pull-down vs pull-up should not compromise the pin's operation. Not critical but would be nice on next version of RP2040, whenever that may be. Should be possible to ensure backwards compatibility.
Note this may be considered pointless in most applications. This could be fixed few ways if this becomes problematic, however these work arounds could increase cost.
I have been unable to re-create an image that matches the RP2040 mask ROM, at least on the parts that I have. There are non-trivial differences.
Having an .elf file to trace through Boot ROM code execution is rather important in diagnosing RP2040 behavior.
I’m using this to compile (which ostensibly matches what the README says):
gcc version 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] (GNU Tools for Arm Embedded Processors 9-2019-q4-major)
The 8 most significant hex digits of the Bootrom git revision are: 0xd24340e4
The bootrom version byte at 0x13 is 0x01
How any of this relates to the “B1” specified in the README is not clear.
The README also speaks of “built in debug mode”. I’ve tried both:
cmake -DCMAKE_BUILD_TYPE=Debug .
cmake .
without any change in the output file.
I've attached a binary of what the mask ROM is on the parts that I have.
Thanks.
Hi! I am admittedly doing something slightly odd, but that odd thing may have exposed a bug in the firmware loading code.
The build system for Hubris lays out separately compiled tasks in isolated memory containers. This means that its Flash footprint consists of a series of (power-of-two-aligned) chunks, many of which are not full. For instance,
ADDRESS END SIZE FILE
10000100 100001a8 a8 target/demo-pi-pico/dist/kernel
100001a8 10002b20 2978 target/demo-pi-pico/dist/kernel
10002b20 10002db8 298 target/demo-pi-pico/dist/kernel
10003000 10003048 48 target/demo-pi-pico/dist/idle
10003400 10003708 308 target/demo-pi-pico/dist/sys
10003708 10003710 8 target/demo-pi-pico/dist/sys
10003800 10003aec 2ec target/demo-pi-pico/dist/user_leds
10003aec 10003b48 5c target/demo-pi-pico/dist/user_leds
For instance, in the example layout above, there's a gap between the end of the kernel text (at ...2db8, or ...2e00 when rounded up to the next Flash sector) and the beginning of the next program's text at ...3000.
I've altered our build system to produce UF2 and I've tested it in two different modes. In "contiguous" mode, it generates zero-filled records for gaps like the one described above. In "discontiguous" mode, it does not (and the block count and whatnot is reduced accordingly). The datasheet didn't talk me out of doing discontiguous UF2s; indeed, section 2.8.4.2 mentions offhand that
Note that flash is erased a 4K sector at a time, so writing to only a subset of a 4K flash sector will leave the rest of that
flash sector undefined. Beyond that there is no requirement that a binary be contiguous.
I went and studied virtual_disk.c
and associated code, and it looks like it's trying to do the right thing even if blocks are discontiguous, out of order, etc. So, it sure looks like this should work!
However, when loading in discontiguous mode, the Flash is not being written correctly. Specifically, the Flash will be written up to the final sector in a contiguous region, and then the first few sectors of the region after the gap are erased but not written, so they read back as FF FF etc. Example (from a conversation through gdb+openocd):
(gdb) mon mdb 0x10002d00 16
0x10002d00: 05 00 00 00 00 00 00 00 00 07 00 20 00 01 00 00
(gdb) mon mdb 0x10002e00 16 # expected to be FFs, this is the gap
0x10002e00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
(gdb) mon mdb 0x10003000 16 # expected to have a program in it!
0x10003000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
The UF2 record that should have been written there reads:
00005c00 55 46 32 0a 57 51 5d 9e 00 20 00 00 00 30 00 10 |UF2.WQ].. ...0..|
00005c10 00 01 00 00 2e 00 00 00 68 00 00 00 56 ff 8b e4 |........h...V...|
00005c20 0a 48 0b 49 0b 4a 01 e0 08 c9 08 c2 82 42 fb d1 |.H.I.J.......B..|
00005c30 09 48 0a 49 00 22 00 e0 04 c1 81 42 fc d1 bf f3 |.H.I.".....B....|
00005c40 4f 8f bf f3 6f 8f 00 f0 0b f8 fe de 00 07 00 20 |O...o.......... |
00005c50 48 30 00 10 00 07 00 20 00 07 00 20 00 07 00 20 |H0..... ... ... |
00005c60 80 b5 00 af 30 bf fd e7 00 00 00 00 00 00 00 00 |....0...........|
00005c70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00005df0 00 00 00 00 00 00 00 00 00 00 00 00 30 6f b1 0a |............0o..|
The problem extends up until address ...3500 at which point sectors start being written correctly again. (This is a curious point for things to change, as it's not an erase sector boundary.)
So, I am either missing something, or there's a subtle bug here.
I have attached gzip'd UF2 images of the firmware (compiled for Pi Pico) in both contiguous mode (works!) and discontiguous mode (fails as described above). If you try it, the "working" case should blink the LED at about 1 Hz, while the failure case will set the LED and then hard fault when it jumps into an erased flash sector.
Some of the following character constants don't have a right apostrophe, e.g. 'F
instead of 'F'
:
pico-bootrom/bootrom/bootrom_rt0.S
Lines 210 to 219 in ef22cd8
For some reason this nevertheless assembles correctly?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.