armcm_boot: Improve ARM Cortex-M control transfer from bootloaders (#4024)

Signed-off-by: Matt Baker <baker.matt.j@gmail.com>
This commit is contained in:
Matt Baker 2021-03-09 06:32:20 -08:00 committed by GitHub
parent b0f94e50ee
commit 3f07b16b35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 40 additions and 9 deletions

View File

@ -18,21 +18,40 @@ extern uint32_t _data_start, _data_end, _data_flash;
extern uint32_t _bss_start, _bss_end, _stack_start; extern uint32_t _bss_start, _bss_end, _stack_start;
extern uint32_t _stack_end; extern uint32_t _stack_end;
/**************************************************************** /****************************************************************
* Basic interrupt handlers * Basic interrupt handlers
****************************************************************/ ****************************************************************/
// Initial code entry point - invoked by the processor after a reset static void __noreturn
void reset_handler_stage_two(void)
ResetHandler(void)
{ {
// Disable SysTick irq (for some bootloaders that don't) int i;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk;
// Explicitly load the stack pointer (for some bootloaders that don't) // Clear all enabled user interrupts and user pending interrupts
asm volatile("mov sp, %0" : : "r"(&_stack_end)); for (i = 0; i < ARRAY_SIZE(NVIC->ICER); i++) {
barrier(); NVIC->ICER[i] = 0xFFFFFFFF;
__DSB();
NVIC->ICPR[i] = 0xFFFFFFFF;
}
// Reset all user interrupt priorities
for (i = 0; i < ARRAY_SIZE(NVIC->IP); i++)
NVIC->IP[i] = 0;
// Disable SysTick interrupt
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk;
__DSB();
// Clear pending pendsv and systick interrupts
SCB->ICSR = SCB_ICSR_PENDSVCLR_Msk | SCB_ICSR_PENDSTCLR_Msk;
// Reset all system interrupt priorities
for (i = 0; i < ARRAY_SIZE(SCB->SHP); i++)
SCB->SHP[i] = 0;
__DSB();
__ISB();
__enable_irq();
// Copy global variables from flash to ram // Copy global variables from flash to ram
uint32_t count = (&_data_end - &_data_start) * 4; uint32_t count = (&_data_end - &_data_start) * 4;
@ -53,6 +72,18 @@ ResetHandler(void)
for (;;) for (;;)
; ;
} }
// Initial code entry point - invoked by the processor after a reset
// Reset interrupts and stack to take control from bootloaders
void
ResetHandler(void)
{
__disable_irq();
// Explicitly load the stack pointer, jump to stage two
asm volatile("mov sp, %0\n bx %1"
: : "r"(&_stack_end), "r"(reset_handler_stage_two));
}
DECL_ARMCM_IRQ(ResetHandler, -15); DECL_ARMCM_IRQ(ResetHandler, -15);
// Code called for any undefined interrupts // Code called for any undefined interrupts