armcm_boot: Avoid invoking functions in reset_handler_stage_two()

Avoid calling memset() and memcpy() prior to copying the ram and
clearing the bss.  Also, place both ResetHandler() and
reset_handler_stage_two() in an explicit ".text.armcm_boot" linker
section.  These changes make it easier to support targets that want to
run all code in ram.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2024-01-20 19:30:21 -05:00
parent 43a9685c58
commit 55e46aa625
1 changed files with 28 additions and 4 deletions

View File

@ -22,7 +22,31 @@ extern uint32_t _stack_end;
* Basic interrupt handlers * Basic interrupt handlers
****************************************************************/ ****************************************************************/
static void __noreturn // Inlined version of memset (to avoid function calls during intial boot code)
static void __always_inline
boot_memset(void *s, int c, size_t n)
{
volatile uint32_t *p = s;
while (n) {
*p++ = c;
n -= sizeof(*p);
}
}
// Inlined version of memcpy (to avoid function calls during intial boot code)
static void __always_inline
boot_memcpy(void *dest, const void *src, size_t n)
{
const uint32_t *s = src;
volatile uint32_t *d = dest;
while (n) {
*d++ = *s++;
n -= sizeof(*d);
}
}
// Main initialization code (called from ResetHandler below)
static void __noreturn __section(".text.armcm_boot.stage_two")
reset_handler_stage_two(void) reset_handler_stage_two(void)
{ {
int i; int i;
@ -60,10 +84,10 @@ reset_handler_stage_two(void)
// 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;
__builtin_memcpy(&_data_start, &_data_flash, count); boot_memcpy(&_data_start, &_data_flash, count);
// Clear the bss segment // Clear the bss segment
__builtin_memset(&_bss_start, 0, (&_bss_end - &_bss_start) * 4); boot_memset(&_bss_start, 0, (&_bss_end - &_bss_start) * 4);
barrier(); barrier();
@ -80,7 +104,7 @@ reset_handler_stage_two(void)
// Initial code entry point - invoked by the processor after a reset // Initial code entry point - invoked by the processor after a reset
// Reset interrupts and stack to take control from bootloaders // Reset interrupts and stack to take control from bootloaders
void void __section(".text.armcm_boot.stage_one")
ResetHandler(void) ResetHandler(void)
{ {
__disable_irq(); __disable_irq();