mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-10-06 09:02:52 +08:00
fix(bootloader): select the MSP before jumping to the application
NuttX 12.12.0 added arm_initialize_stack(), which moves thread mode onto the process stack pointer whenever CONFIG_ARCH_INTERRUPTSTACK > 7. Every bootloader config qualifies, so the bootloader now reaches arch_do_jump() with CONTROL.SPSEL set, where previously it ran on the main stack. arch_do_jump() writes the MSP and branches, but never selects it. The application therefore starts on the bootloader's PSP while its own startup code initialises a stack pointer the CPU is not using. Boards booted far enough to reach NSH and start MAVLink, then hard faulted once the stale bootloader stack was overwritten, surfacing as an assertion in Idle_Task with no useful backtrace. Clear CONTROL.SPSEL so control passes on the stack the application expects. The i.MX RT bootloader performs the same jump and its configs also exceed the interrupt stack threshold, so fix both. Verified on CubePilot CubeOrange and Pixhawk 6C; the prebuilt bootloaders for both are regenerated, as the shipped binaries have the defect. Assisted-by: Claude:claude-opus-5 Signed-off-by: Julian Oes <julian@oes.ch>
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -684,10 +684,21 @@ arch_do_jump(const uint32_t *app_base)
|
||||
uint32_t stacktop = app_base[APP_VECTOR_OFFSET_WORDS];
|
||||
uint32_t entrypoint = app_base[APP_VECTOR_OFFSET_WORDS + 1];
|
||||
|
||||
uint32_t scratch;
|
||||
|
||||
/* NuttX 12.12 runs thread mode on the PSP (arm_initialize_stack(), enabled
|
||||
* whenever CONFIG_ARCH_INTERRUPTSTACK > 7). The application expects to start
|
||||
* on the MSP, so select it again before handing over -- otherwise the app
|
||||
* keeps running on the bootloader's stack and faults once it is clobbered.
|
||||
*/
|
||||
asm volatile(
|
||||
"msr msp, %0 \n"
|
||||
"bx %1 \n"
|
||||
: : "r"(stacktop), "r"(entrypoint) :);
|
||||
"mrs %0, control \n"
|
||||
"bic %0, %0, #2 \n"
|
||||
"msr control, %0 \n"
|
||||
"isb sy \n"
|
||||
"msr msp, %1 \n"
|
||||
"bx %2 \n"
|
||||
: "=&r"(scratch) : "r"(stacktop), "r"(entrypoint) :);
|
||||
|
||||
// just to keep noreturn happy
|
||||
for (;;) ;
|
||||
|
||||
@@ -636,10 +636,21 @@ arch_do_jump(const uint32_t *app_base)
|
||||
uint32_t stacktop = app_base[0];
|
||||
uint32_t entrypoint = app_base[1];
|
||||
|
||||
uint32_t scratch;
|
||||
|
||||
/* NuttX 12.12 runs thread mode on the PSP (arm_initialize_stack(), enabled
|
||||
* whenever CONFIG_ARCH_INTERRUPTSTACK > 7). The application expects to start
|
||||
* on the MSP, so select it again before handing over -- otherwise the app
|
||||
* keeps running on the bootloader's stack and faults once it is clobbered.
|
||||
*/
|
||||
asm volatile(
|
||||
"msr msp, %0 \n"
|
||||
"bx %1 \n"
|
||||
: : "r"(stacktop), "r"(entrypoint) :);
|
||||
"mrs %0, control \n"
|
||||
"bic %0, %0, #2 \n"
|
||||
"msr control, %0 \n"
|
||||
"isb sy \n"
|
||||
"msr msp, %1 \n"
|
||||
"bx %2 \n"
|
||||
: "=&r"(scratch) : "r"(stacktop), "r"(entrypoint) :);
|
||||
|
||||
// just to keep noreturn happy
|
||||
for (;;) ;
|
||||
|
||||
Reference in New Issue
Block a user