Skip to content
This repository has been archived by the owner on Jan 24, 2022. It is now read-only.

VTOR and initial stack for debuggers #283

Closed
debuti opened this issue Jul 31, 2020 · 5 comments
Closed

VTOR and initial stack for debuggers #283

debuti opened this issue Jul 31, 2020 · 5 comments

Comments

@debuti
Copy link

debuti commented Jul 31, 2020

In crt0.s you'll usually find statements like the next one at the very beginning of the code:
ldr SP, =_stack_start

To set the initial stack pointer to the correct value. You'll find it along with code to set VTOR, and other tasks considered as protective programming. This allows to mimic the HW reset behavior to start off in the same environment when the software is launched from a debugger (ie. lauterbach)

Can this be implemented in fn Reset() -> !?

One can argue that this can be implemented inside the preinit function, but in the stack pointer case it wont work as the stack has already been used by that moment and on function epilogue it will be incremented causing an incorrect mem access. Setting it using the debugger is also possible, but is not very clean to have this values (IVT location or stack start) in the debugger context.

@debuti debuti changed the title VTOR and initial stack on debuggers VTOR and initial stack for debuggers Jul 31, 2020
@adamgreig
Copy link
Member

See also #55 where this was discussed previously. I think there have been similar discussions on the chat before too but not sure if they made it into issues. Do you have a specific debugger where this is a problem? I don't understand why using a debugger should require changing VTOR. It seems like a correct debugger should ensure SP is initialised if it's jumping code execution to the reset vector manually; otherwise it could use the AIRCR register to trigger a local reset.

Previously it's been mentioned in the context of bootloaders which might fail to change VTOR (and SP, I suppose) before jumping into the application, but really that seems like a defect in the bootloader. User applications can change VTOR in pre_init but you're right that it's too late to update SP there.

On Cortex-M0 there's no support for VTOR and instead remapping the vector table is done in some chip-specific fashion, for example by remapping SRAM to address 0 and writing a vector table to the start of the SRAM. We can't implement that in cortex-m-rt because it's entirely application and MCU specific, and requires corresponding updates to the user's memory.x etc. It could be supported by a BSP or HAL perhaps.

In the context of bootloaders I was fairly sure we shouldn't try and fix them in cortex-m-rt, since it's very platform specific and we can't make all the right guesses, but I hadn't considered debuggers too. I'd be interested in hearing about why a debugger needs the user code to set up SP/VTOR for sure.

@debuti
Copy link
Author

debuti commented Jul 31, 2020

Makes sense, but i think that at least the stack pointer -afaik common to all cortex m processors- can be set at reset, leaving the rest for the preinit, where it can be easily adjusted with some unsafe blocks.

Or what about inlining the preinit?

In our environment we are using an nxp s32g debugged with a trace32 + lauterbach for cortex-m cable. For sure the code will work perfectly once flashed, but when loaded (through data.load.elf) directly to RAM, it takes the VTOR and MSP it has by that moment, producing funny results when any interrupt/exception arrives.

@adamgreig
Copy link
Member

Do you modify memory.x to change the flash origin to point to SRAM, then rebuild, to generate an image to run from RAM? Once you've used data.load.elf to load the image into SRAM, do you call something else to jump execution?

I think there could be compelling arguments for this, perhaps it helps our memory safety case if we do always set the stack pointer in our Reset vector to whatever was configured in our linker script rather than only relying on hardware to do it for us, but I worry there are situations where having this crate set the SP at reset causes more problems. I'm not sure if there's any good way to make this user configurable either (short of adding a default Cargo feature which is a bit heavy-handed).

@therealprof
Copy link
Contributor

From this weeks discussion: We have a feeling this is quite vendor specific and there's very little we can do universally about it. Changing the SP would require a #[naked] function which requires assembly which is not possible.

Since we don't have any other report about requiring to reset the stack pointer we feel inclined to close this as a "won't fix".

@adamgreig
Copy link
Member

To add a little more context:

  • Adding a universal write to SP in Reset is undesirable for a few reasons
    • It affects all users; every Rust program on a Cortex-M would start off by performing a redundant write to SP after the hardware does it
    • It requires either a new reset vector written in assembly, or modifying our current entry point to be #[naked]
    • It shouldn't be required for a standard system. This seems like something the debug probe needs to do -- what other required startup behaviour is it not correctly emulating? We can't go around resetting all the CSRs too, just in case they were not initialised; it seems to me like when running from SRAM the device should be reset after loading the new program and before starting execution.

Adding some way to let the user perform this sort of initialisation behaviour is tricky too, because their function would also need to be #[naked] or written in assembly.

It might yet be possible to provide a good way to allow the user to customise the reset vector entirely; in the worst case the user can provide their own link.x pointing to their own reset vector. If you could find a way to do that inside cortex-m-rt I'd love to see it as a PR, as it would enable pretty much any required boot customisation. Otherwise (and short of finding further examples of behaviour that require SP be set at start), we'd rather not add that here.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants