-
Notifications
You must be signed in to change notification settings - Fork 905
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Why does second stage bootloader not set VTOR and SP? #6
Comments
I'm not sure that is an assumption they should make (unless flash is at 0x00000000), Still if they don't reference the stack pointer you could replace it with something like 0x47184b00, // ldr r3, [pc, #0]; bx r3 to jump to the reset vector, and actually put a stack pointer in there (though all your bootstrap code need to be in the first 256 bytes of flash somewhere) |
Seems like the second stage bootloader already breaks this assumption, so I guess the other issue is the alignment requirement of VTOR, and not wanting to hoist the reset handler over the vector table to fill the alignment hole? |
P.S. yay, rust i'm guessing - i wanted to give it a try myself, but i had zero time, and my Rust is not very idiomatic yet! |
Purely a size consideration, in case we needed to squeeze more in there at a later time (as you can see it is already quite tight), and want to keep the interface stable. No strong objections to that mechanism but it looks like it would add a few bytes. Then again I guess now would be the time to change it, if ever. |
(I'm guessing one of the unstated priors here is that you would rather not ship your own second stages with those SDKs) |
So I understand, you're suggesting a patch like this? (edit: and also setting VTOR as well as vectoring through the table)
|
oh i had entirely misread the original topic - ignore everything i said! |
Thought about this a bit longer, and it makes sense to put vector table at the start in flash images, but we also have a NO_FLASH build flag, where binaries are built to be loaded into RAM. The issue is that when loaded over UF2->USB, the bootrom enters these images in the same way that boot2 currently enters flash crt0. This means we'll have vector table first on flash builds (which by default we then copy out and relocate into RAM anyway), and second on RAM-only builds. I can't see this causing any particular trouble other than making people's eyes bulge, so I'll raise a PR to make these changes. |
Thanks! https://GitHub.com/thejpster/pico-blink-rs contains my terrible hacks. |
And to be clear, yes I would prefer not to ship either ASM or blobs with a Rust application. ASM is preferable, but it involves pulling in big dependencies to kick off gcc / as automatically. |
Shipping ASM shims is much easier if you take the approach that I've used in the cortex-m crate, it works without any external dependencies: https://github.com/rust-embedded/cortex-m/blob/master/asm/lib.rs |
Ok, so the ideal situation from a dependency point of view is to reimplement boot2 in rust, if you are able? In other words, you would be free to change the handover between that second stage and the reset handler of the rust program? I think it still makes sense to make this change to the boot2 files shipped with the SDK. |
I think the change would help with supporting other OSes too. We'll look at doing boot2 in Rust. It'll be an interesting challenge! |
Note the other thing we have in the first 256 bytes is the root of our machine walkable "binary info" tree (used by picotool) Our hope is to have other languages include other information that might be useful to users (you can run this against a BIN/UF2/ELF file or against a device to see what is on it!) The information is designed to be compact, but if nothing else included the end address of the binary is good because it allows you to do e.g.
or
|
Off the top of my head, 256 bytes minus 20 bytes leaves room for 57 interrupt vectors, which is more than enough I think. Configuring an SDK to put a special section after the vector table is usually much easier than trying to put it in front of the vector table. |
I'm not that sure moving the vectors to 0x10000100 is that advantageous. If we're going to copy the vectors to RAM anyway, they can be anywhere in flash really. They could even be first thing in .data, so they'll be initialized by the .data copy. |
I'm not aware of the build system or language context here. It makes sense to me that existing projects might assume their image starts with a vector table, as they may expect the hardware to be doing the vectoring. It seems a bit cleaner for boot2 (whose contents ought to be language-agnostic, and whose size is fixed) to be the only thing bumped on the front of that. |
Yes FYI the original reason for this was that we support the very non standard idea of RAM UF2s, and the bootrom has no idea what the entry point is in the binary, so we go with the lowest address. Also RAM binaries means that you can't just expect to always download code in debugger, then reboot, you should also support "file" and "run". Anyway I think we support all that with the new layout (which I agree is more sensible) without needing to change the bootrom :-) |
Yeah definitely worth considering the RAM binary use case. (RP2040 with no flash, running something on the device without disturbing the flash) use cases, since you do need code at the beginning for that (although clearly you could just trade out the boot stage 2 for a 256 byte indirect thru boot vector at 0x100) |
Agreed; more of an FYI than a concern over space |
Traditionally the main app will relocate VTOR if necessary, which is why it doesn't make sense to do it in boot stage2. You can have a look at SystemInit function in system_XXX.c files in CMSIS libraries. This concept makes sense, you can have multiple implementations of system_XXXX.c, one which will copy VTOR to RAM and relocate address there, another while will use FLASH for this purpose. I don't think that that it's necessary to do it in boot_stage2. On the other hand, I think that you could use C directly writing boot_stage2 code. It's more readable for most people and the size of the output is pretty much the same, or very close (it fits 252bytes). I've verified this by rewriting this in C. I'm porting this ASM to C and the results look ok. I think I should get my pico tomorrow and will check if everything works. If it's ok then I will post a like to my repo. |
Yeah, the question here is not about installing the VTOR, but whether to allow the real binary to have its vector table at the beginning of the binary (which we currently don't as we jump there). The change would just be to pull initial PC,SP from 0x100-0x108 instead of jumping to 0x100 |
Oh damn, yeah missed the point :D I've looked at the linker file again, I get what you mean. That looks really weird indeed... What was the initial idea behind placing reset section in front of vector? |
Keeping the handover between boot2 and crt0 absolutely minimal in case there was any critical hardware setup we needed to use that space for. We've released now, things seem to be basically working, so it makes sense to spend those bytes to bring our binary layout in line with other codebases' assumptions
Please do share -- right now I'm keen on just getting the binary layout change merged before people go too much further with bare metal language bringup stuff, but it would be interesting to look at rewriting in C in the future (and might let us have a single, more configurable boot2) |
I added a comment to the PR, but I don't think we should actually install the VTOR. we should just redirect thru the first 8 bytes, and leave it to the language runtime to decide how they setup vector table. Thoughts? |
I think the issue with not installing VTOR is that a lot of existing runtime will just turn on IRQs without modifying VTOR (as VTOR is not modifiable on some systems anyway), under the assumption that VTOR points at the vector table that you came into the image through, which is true on almost every system apart from ours. If we didn't install VTOR, this would send all such code through the bootrom vector table. This doesn't affect our runtime anyway because we relocate VTOR before enabling IRQs, so it wouldn't affect our code, and would give other crt0s an experience that's more consistent with other Cortex-M platforms. |
Yes, you are right, my brain was out to lunch |
The answer to the question in this thread's title is now "it does" :) |
Having to make 0x100 in flash a function as opposed to a vector table complicates the use of other programming languages and SDKs, which assume flash starts with a vector table.
Is there a reason why the second stage bootloader doesn't set VTOR to 0x1000_0100, SP to [0x1000_0100] and then jump to [0x1000_0104]?
The text was updated successfully, but these errors were encountered: