Skip to content

modm 的启动流程

· 5 min

under construction!#

Reset_Handler.sx#

.globl Reset_Handler
.text
.syntax unified
.align 4
.type Reset_Handler, %function
.func Reset_Handler
Reset_Handler:
// Some bootloaders do not reset the stack pointer back to the VTOR entry
ldr r0,=__main_stack_top
mov sp,r0
// Enable FPU early so the compiler may use FPU registers for copying
// SCB->CPACR = ((3UL << 10*2) | (3UL << 11*2));
ldr r0,=0xe000ed88
ldr r1,=0x00f00000
str r1, [r0, #0]
bl __modm_initialize_platform
bl modm_initialize_platform
b __modm_startup
.endfunc

以上就是启动文件 reset_handler.sx.

ldr r0,=__main_stack_top
mov sp,r0
ldr r0,=0xe000ed88
ldr r1,=0x00f00000
str r1, [r0, #0]
bl __modm_initialize_platform
bl modm_initialize_platform
b __modm_startup
.endfunc

linkerscript.ld#

一个典型的 STM32 链接脚本大致可以分为以下几个部分:

下面是一个简单示例:

ENTRY(Reset_Handler)
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
}
_stack_top = ORIGIN(RAM) + LENGTH(RAM);
_heap_start = _ebss;
_heap_end = _stack_top;
SECTIONS
{
.text :
{
KEEP(*(.isr_vector))
*(.text*)
*(.rodata*)
_etext = .;
} > FLASH
.data :
{
_sdata = .;
*(.data*)
_edata = .;
} > RAM AT > FLASH
.bss :
{
_sbss = .;
*(.bss*)
*(COMMON)
_ebss = .;
} > RAM
}

实际的 linkerscript.ld 太长了, 就不放了, 但有几个注意的点:

startup#

根据官网的介绍, 启动流程如下:

After reset, the ARM Cortex-M hardware jumps to the Reset_Handler(), which is implemented as follows:

  1. The main stack pointer (MSP) is initialized by software.
  2. Call __modm_initialize_platform() to initialize the device hardware.
  3. Call modm_initialize_platform() to initialize the custom device hardware.
  4. Copy data to internal RAM.
  5. Zero sections in internal RAM.
  6. Initialize ARM Cortex-M core: enable FPU, caches and relocate vector table.
  7. Execute shared hardware initialization functions.
  8. Copy data to external RAM.
  9. Zero sections in external RAM.
  10. Initialize heap via __modm_initialize_memory() (implemented by the modm:platform:heap module).
  11. Call static constructors.
  12. Call main() application entry point.
  13. If main() returns, assert on main.exit (only in debug profile).
  14. Reboot if assertion returns.

其中对应的启动部分的代码就是:

// ----------------------------------------------------------------------------
// Called by Reset_Handler in reset_handler.s
void __modm_startup(void)
{
// Copy and zero all internal memory
table_copy(__table_copy_intern_start, __table_copy_intern_end);
table_zero(__table_zero_intern_start, __table_zero_intern_end);
// Set the vector table location
SCB->VTOR = (uint32_t)__vector_table_ram_start;
// Enable trapping of divide by zero for UDIV/SDIV instructions.
SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;
// Call all hardware initialize hooks
table_call(__hardware_init_start, __hardware_init_end);
// Copy and zero all external memory
table_copy(__table_copy_extern_start, __table_copy_extern_end);
table_zero(__table_zero_extern_start, __table_zero_extern_end);
// Initialize heap as implemented by the heap option
__modm_initialize_memory();
// Call all constructors of static objects
table_call(__init_array_start, __init_array_end);
// Call the application's entry point
main();
// If main exits, assert here in debug mode
(void) modm_assert_continue_fail_debug(0,
"main.exit", "The main() function returned!");
// Otherwise reboot
NVIC_SystemReset();
}