STM32 启动代码

Author By YuCloud

边看启动文件边学汇编

汇编

see ARM: Assembler User Guide

see: https://blog.csdn.net/zlmm741/article/details/105189487

指令 作用
EQU 取符号名(类似C #define),同义词 *
AREA 指示编译器汇编一个新段(代码段或数据段)
SPACE 分配内存空间并填零。[标号] SPACE [表达式], 同义词 %
PRESERVE8 按8字节对齐
EXPORT 声明全局,可被外部文件使用,同义词 GLOBAL
DCD 以字为单位分配内存,要求4字节对齐且初始化该内存
PROC 定义子程序,与ENDP成对使用,表示子程序结束 同义词 FUNCTION
WEAK 编译器特性。弱定义,优先使用外部文件定义的标号。
IMPORT 声明标号来自外部文件,类似于C extern
B 跳转到一个标号
ALIGN 编译器指令,对指令或数据存放地址进行对齐(一般跟一个立即数,缺省为4字节)
END EOF,文件结束
IF,ELSE,ENDIF 条件分支

STM32 启动文件详解

注意,汇编里的注释符是;,但这里为了视觉效果,用了斜杆

Stack_Size EQU 0x00000400 		// 定义一个符号,0x400为1KB	

// 汇编一个新段,名为STACK 不初始化(即不填零) 可读可写 2^3=8字节对齐
AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size // 栈本体,这里指令是分配栈大小
__initial_sp // 标名, 表示该地址(这里是末尾,即栈顶地址)

也就是 通知编译器链接 -> 分配一片栈空间 -> 记录栈顶地址

栈的作用是用于局部变量,函数调用,函数形参等的开销,栈的大小不能超过内部SRAM的大小。如果编写的程序比较大,定义的局部变量很多,那么就需要修改栈的大小。如果某一天,你写的程序出现了莫名奇怪的错误,并进入了硬 fault 的时候,这时你就要考虑下是不是栈不够大,溢出了。

指令详解

SPACE 指令用于留出一段填零的内存空间

初始化是指

Indicates that the data section is uninitialized, or initialized to zero.

指令文档链接:EQUSPACEAREA

EQU 是伪指令,不生成二进制代码

另外,Label 就是一个标号,加不加只是为了规范,不影响二进制结果。其实上面代码等价于

AREA STACK, NOINIT, READWRITE, ALIGN=3
SPACE 0x00000400 // 栈本体,这里指令是分配栈大小
<编译器拿到__initial_sp所在行编译时的地址> //标名, 表示该地址(这里是末尾,即栈顶地址)

对了,官方文档说 Use the ALIGN directive to align any code following a SPACE or FILL directive.

ALIGN 指令对齐 SPACE FILL 指令之后的任何代码,而AREA 里有 ALIGN 参数

个人猜测: AREASPACE 配合,才能生成一个段

反汇编一个程序,段是这样的(黑色箭头是 段名,方框是 整个段的内容)

Heap_Size EQU 0x00000200 		//Heap_Size=512B
// 新段,名为HEAP,可读可写,不初始化,8B对齐
AREA HEAP, NOINIT, READWRITE, ALIGN=3 __heap_base // 堆的起始地址
Heap_Mem SPACE Heap_Size // 堆本体
__heap_limit // 堆的结束地址

堆用于 malloc/calloc 等用于动态分配内存的函数

通知编译器链接->记录堆头地址->分配一片堆空间->记录堆尾地址

静态变量和局部变量都是在SRAM中分配

过渡

PRESERVE8 	// 指定当前文件的栈按 8B 对齐
THUMB // 表示后面的指令兼容 Thumb 指令集(ARM以前的16位指令集)

向量表

AREA RESET, DATA, READONLY // 汇编新段,名为RESET的数据段,只读
EXPORT __Vectors //向量表起始
EXPORT __Vectors_End //向量表末尾
EXPORT __Vectors_Size //向量表大小,可由__Vectors_End-__Vectors计算 __Vectors
DCD __initial_sp
DCD Reset_Handler
DCD NMI_Handler
// ... 省略一些代
DCD DMA2D_IRQHandler
__Vectors_End __Vectors_Size EQU __Vectors_End - __Vectors

EXPORT/GLOBAL 声明全局,可被外部文件使用

向量表作用:

当内核响应了一个发生的异常后,对应的异常服务例程(ESR)就会执行。为了决定 ESR的入口地址, 内核使用了―向量表查表机制‖。这里使用一张向量表。向量表其实是一个WORD(32 位整数)数组,每个下标对应一种异常,该下标元素的值则是该 ESR 的入口地址。向量表在地址空间中的位置是可以设置的,通过 NVIC 中的一个重定位寄存器来指出向量表的地址。

在复位后,该寄存器的值为 0。因此,在地址 0 (即 FLASH 地址 0) 处必须包含一张向量表,用于初始时的异常分配。要注意的是这里有个另类: 0 号类型并不是什么入口地址,而是给出了复位后 MSP 的初值。

向量表从 FLASH 的 0 地址开始放置,以 4 个字节为一个单位,地址 0 存放的是栈顶地址, 0X04 存放的是复位程序的地址,以此类推。从代码上看,向量表中存放的都是中断服务函数的函数名,可我们知道 C 语言中的函数名就是一个地址。

DCD:分配一个或者多个以字为单位的内存,以四字节对齐,并要求初始化这些内存。在向量表中, DCD 分配了一堆内存,并且以 ESR 的入口地址初始化它们。

用人话说: 内核在异常时会访问这个表地址,并根据异常类型查表,按表跳转到异常处理函数执行。

各种中断处理程序 xxx_Handler

先指示编译器汇编一个新的代码段,名为 |.text|,只读

                AREA    |.text|, CODE, READONLY
复位程序,也就是默认上电复位后执行的程序
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP

弱符号导出本程序Reset_Handler,导入 SystemInit__main 两个符号,并LDR数据到R0寄存器,跳转执行(BLX/BX)

注:R0~R3 寄存器通常用于函数入参出参或子程序调用,详细请自行搜索 ARM 寄存器作用

PORC 标记了程序的开始,ENDP 标记了程序的末尾。与R13(SP)寄存器相关。

R13(即SP栈指针寄存器): 当程序的运行进入异常模式时,可以将需要保护的寄存器放入R13所指向的堆栈,而当程序从异常模式返回时,则从对应的堆栈中恢复,采用这种方式可以保证异常发生后程序的正常执行。

B 跳转的都是相对地址(相对于 PC寄存器),偏移值是由编译器计算的

B {条件} 目标地址 条件可选,立即跳转执行。(不返回程序),B . 是死循环while(1);的用法

BL 目标地址 无条件跳转到目标地址处执行,并保存PC值到 R14(LR) 寄存器

BLX 目标地址 无条件跳转到目标地址处执行,并切换工作状态为 Thumb ,同时保存PC值到 R14(LR) 寄存器

子程序返回:通过将 R14 寄存器值复制到 PC 来实现。

前文说到, Label 代表的就是其所在地址

其他异常处理程序
定义异常处理子程序
; Dummy Exception Handlers (infinite loops which can be modified)

NMI_Handler     PROC
EXPORT NMI_Handler [WEAK]
B .
ENDP
HardFault_Handler\
PROC
EXPORT HardFault_Handler [WEAK]
B .
ENDP
//...省略一些
SysTick_Handler PROC
EXPORT SysTick_Handler [WEAK]
B .
ENDP

这里虽然有 B . (跳转到当前地址执行,这里会不断跳转执行 B .,也就是死循环),

但是有外部 xxx_Handler时,应该是会返回异常之前的处理函数的,所以在有处理函数的情况下,不会死循环,而是执行完异常处理函数后再跳回异常之前的函数。

弱导出 异常处理函数 的符号表
Default_Handler PROC

                EXPORT  WWDG_IRQHandler                   [WEAK]
EXPORT PVD_IRQHandler [WEAK] // 省略一些
EXPORT FPU_IRQHandler [WEAK]
EXPORT SPI4_IRQHandler [WEAK]

这里 [WEAK] 表示优先使用外部符号,如果没有才使用内部的(即刚才上面定义的子程序)

中断处理函数的符号表

这里是标号,也就是表明程序地址在这里

这样就排列出了中断处理函数表,顺序必须和前面的符号表对应,

应该就是为了让编译器对着符号名链接子程序?

WWDG_IRQHandler
PVD_IRQHandler
TAMP_STAMP_IRQHandler
RTC_WKUP_IRQHandler
FLASH_IRQHandler
//...省略一些
FPU_IRQHandler
SPI4_IRQHandler
// 死循环(点表示当前地址,B表示立即跳转)应该是防止程序跑飞,,所以一切执行完成后就在这里死循环
B . // 程序的结束符
ENDP
// 对齐(默认4B对齐
ALIGN
堆栈初始化
  • if

    • 如果使用了微库(MicroLib),就直接导出堆栈地址符号
  • else

    • 导入外部程序__use_two_region_memory并马上执行调用

    • 并导出子程序符号__user_initial_stackheap给外部程序调用

;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************
IF :DEF:__MICROLIB EXPORT __initial_sp
EXPORT __heap_base
EXPORT __heap_limit ELSE IMPORT __use_two_region_memory //
EXPORT __user_initial_stackheap //导出了

__user_initial_stackheap 的程序定义: 保存堆栈地址和大小到寄存器

// 下面是 __user_initial_stackheap 的程序定义,用于导出给外部程序调用的
__user_initial_stackheap LDR R0, = Heap_Mem
LDR R1, =(Stack_Mem + Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR ALIGN ENDIF END ;************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE*****

启动文件代码(startup_stm32f401xx.s)

点击展开完整代码 [startup_stm32f401xx.s]
;******************** (C) COPYRIGHT 2014 STMicroelectronics ********************
;* File Name : startup_stm32f401xx.s
;* Author : MCD Application Team
;* @version : V1.4.0
;* @date : 04-August-2014
;* Description : STM32F401xx devices vector table for MDK-ARM toolchain.
;* This module performs:
;* - Set the initial SP
;* - Set the initial PC == Reset_Handler
;* - Set the vector table entries with the exceptions ISR address
;* - Configure the system clock
;* - Branches to __main in the C library (which eventually
;* calls main()).
;* After Reset the CortexM4 processor is in Thread mode,
;* priority is Privileged, and the Stack is set to Main.
;* <<< Use Configuration Wizard in Context Menu >>>
;*******************************************************************************
;
; Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
; You may not use this file except in compliance with the License.
; You may obtain a copy of the License at:
;
; http://www.st.com/software_license_agreement_liberty_v2
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
;******************************************************************************* ; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <h> Stack Configuration
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h> Stack_Size EQU 0x00000400 AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp ; <h> Heap Configuration
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h> Heap_Size EQU 0x00000200 AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit PRESERVE8
THUMB ; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size __Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler ; External Interrupts
DCD WWDG_IRQHandler ; Window WatchDog
DCD PVD_IRQHandler ; PVD through EXTI Line detection
DCD TAMP_STAMP_IRQHandler ; Tamper and TimeStamps through the EXTI line
DCD RTC_WKUP_IRQHandler ; RTC Wakeup through the EXTI line
DCD FLASH_IRQHandler ; FLASH
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line0
DCD EXTI1_IRQHandler ; EXTI Line1
DCD EXTI2_IRQHandler ; EXTI Line2
DCD EXTI3_IRQHandler ; EXTI Line3
DCD EXTI4_IRQHandler ; EXTI Line4
DCD DMA1_Stream0_IRQHandler ; DMA1 Stream 0
DCD DMA1_Stream1_IRQHandler ; DMA1 Stream 1
DCD DMA1_Stream2_IRQHandler ; DMA1 Stream 2
DCD DMA1_Stream3_IRQHandler ; DMA1 Stream 3
DCD DMA1_Stream4_IRQHandler ; DMA1 Stream 4
DCD DMA1_Stream5_IRQHandler ; DMA1 Stream 5
DCD DMA1_Stream6_IRQHandler ; DMA1 Stream 6
DCD ADC_IRQHandler ; ADC1
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD EXTI9_5_IRQHandler ; External Line[9:5]s
DCD TIM1_BRK_TIM9_IRQHandler ; TIM1 Break and TIM9
DCD TIM1_UP_TIM10_IRQHandler ; TIM1 Update and TIM10
DCD TIM1_TRG_COM_TIM11_IRQHandler ; TIM1 Trigger and Commutation and TIM11
DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
DCD TIM2_IRQHandler ; TIM2
DCD TIM3_IRQHandler ; TIM3
DCD TIM4_IRQHandler ; TIM4
DCD I2C1_EV_IRQHandler ; I2C1 Event
DCD I2C1_ER_IRQHandler ; I2C1 Error
DCD I2C2_EV_IRQHandler ; I2C2 Event
DCD I2C2_ER_IRQHandler ; I2C2 Error
DCD SPI1_IRQHandler ; SPI1
DCD SPI2_IRQHandler ; SPI2
DCD USART1_IRQHandler ; USART1
DCD USART2_IRQHandler ; USART2
DCD 0 ; Reserved
DCD EXTI15_10_IRQHandler ; External Line[15:10]s
DCD RTC_Alarm_IRQHandler ; RTC Alarm (A and B) through EXTI Line
DCD OTG_FS_WKUP_IRQHandler ; USB OTG FS Wakeup through EXTI line
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD DMA1_Stream7_IRQHandler ; DMA1 Stream7
DCD 0 ; Reserved
DCD SDIO_IRQHandler ; SDIO
DCD TIM5_IRQHandler ; TIM5
DCD SPI3_IRQHandler ; SPI3
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD DMA2_Stream0_IRQHandler ; DMA2 Stream 0
DCD DMA2_Stream1_IRQHandler ; DMA2 Stream 1
DCD DMA2_Stream2_IRQHandler ; DMA2 Stream 2
DCD DMA2_Stream3_IRQHandler ; DMA2 Stream 3
DCD DMA2_Stream4_IRQHandler ; DMA2 Stream 4
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD OTG_FS_IRQHandler ; USB OTG FS
DCD DMA2_Stream5_IRQHandler ; DMA2 Stream 5
DCD DMA2_Stream6_IRQHandler ; DMA2 Stream 6
DCD DMA2_Stream7_IRQHandler ; DMA2 Stream 7
DCD USART6_IRQHandler ; USART6
DCD I2C3_EV_IRQHandler ; I2C3 event
DCD I2C3_ER_IRQHandler ; I2C3 error
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD FPU_IRQHandler ; FPU
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SPI4_IRQHandler ; SPI4 __Vectors_End __Vectors_Size EQU __Vectors_End - __Vectors AREA |.text|, CODE, READONLY ; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP ; Dummy Exception Handlers (infinite loops which can be modified) NMI_Handler PROC
EXPORT NMI_Handler [WEAK]
B .
ENDP
HardFault_Handler\
PROC
EXPORT HardFault_Handler [WEAK]
B .
ENDP
MemManage_Handler\
PROC
EXPORT MemManage_Handler [WEAK]
B .
ENDP
BusFault_Handler\
PROC
EXPORT BusFault_Handler [WEAK]
B .
ENDP
UsageFault_Handler\
PROC
EXPORT UsageFault_Handler [WEAK]
B .
ENDP
SVC_Handler PROC
EXPORT SVC_Handler [WEAK]
B .
ENDP
DebugMon_Handler\
PROC
EXPORT DebugMon_Handler [WEAK]
B .
ENDP
PendSV_Handler PROC
EXPORT PendSV_Handler [WEAK]
B .
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler [WEAK]
B .
ENDP Default_Handler PROC EXPORT WWDG_IRQHandler [WEAK]
EXPORT PVD_IRQHandler [WEAK]
EXPORT TAMP_STAMP_IRQHandler [WEAK]
EXPORT RTC_WKUP_IRQHandler [WEAK]
EXPORT FLASH_IRQHandler [WEAK]
EXPORT RCC_IRQHandler [WEAK]
EXPORT EXTI0_IRQHandler [WEAK]
EXPORT EXTI1_IRQHandler [WEAK]
EXPORT EXTI2_IRQHandler [WEAK]
EXPORT EXTI3_IRQHandler [WEAK]
EXPORT EXTI4_IRQHandler [WEAK]
EXPORT DMA1_Stream0_IRQHandler [WEAK]
EXPORT DMA1_Stream1_IRQHandler [WEAK]
EXPORT DMA1_Stream2_IRQHandler [WEAK]
EXPORT DMA1_Stream3_IRQHandler [WEAK]
EXPORT DMA1_Stream4_IRQHandler [WEAK]
EXPORT DMA1_Stream5_IRQHandler [WEAK]
EXPORT DMA1_Stream6_IRQHandler [WEAK]
EXPORT ADC_IRQHandler [WEAK]
EXPORT EXTI9_5_IRQHandler [WEAK]
EXPORT TIM1_BRK_TIM9_IRQHandler [WEAK]
EXPORT TIM1_UP_TIM10_IRQHandler [WEAK]
EXPORT TIM1_TRG_COM_TIM11_IRQHandler [WEAK]
EXPORT TIM1_CC_IRQHandler [WEAK]
EXPORT TIM2_IRQHandler [WEAK]
EXPORT TIM3_IRQHandler [WEAK]
EXPORT TIM4_IRQHandler [WEAK]
EXPORT I2C1_EV_IRQHandler [WEAK]
EXPORT I2C1_ER_IRQHandler [WEAK]
EXPORT I2C2_EV_IRQHandler [WEAK]
EXPORT I2C2_ER_IRQHandler [WEAK]
EXPORT SPI1_IRQHandler [WEAK]
EXPORT SPI2_IRQHandler [WEAK]
EXPORT USART1_IRQHandler [WEAK]
EXPORT USART2_IRQHandler [WEAK]
EXPORT EXTI15_10_IRQHandler [WEAK]
EXPORT RTC_Alarm_IRQHandler [WEAK]
EXPORT OTG_FS_WKUP_IRQHandler [WEAK]
EXPORT DMA1_Stream7_IRQHandler [WEAK]
EXPORT SDIO_IRQHandler [WEAK]
EXPORT TIM5_IRQHandler [WEAK]
EXPORT SPI3_IRQHandler [WEAK]
EXPORT DMA2_Stream0_IRQHandler [WEAK]
EXPORT DMA2_Stream1_IRQHandler [WEAK]
EXPORT DMA2_Stream2_IRQHandler [WEAK]
EXPORT DMA2_Stream3_IRQHandler [WEAK]
EXPORT DMA2_Stream4_IRQHandler [WEAK]
EXPORT OTG_FS_IRQHandler [WEAK]
EXPORT DMA2_Stream5_IRQHandler [WEAK]
EXPORT DMA2_Stream6_IRQHandler [WEAK]
EXPORT DMA2_Stream7_IRQHandler [WEAK]
EXPORT USART6_IRQHandler [WEAK]
EXPORT I2C3_EV_IRQHandler [WEAK]
EXPORT I2C3_ER_IRQHandler [WEAK]
EXPORT FPU_IRQHandler [WEAK]
EXPORT SPI4_IRQHandler [WEAK] WWDG_IRQHandler
PVD_IRQHandler
TAMP_STAMP_IRQHandler
RTC_WKUP_IRQHandler
FLASH_IRQHandler
RCC_IRQHandler
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
DMA1_Stream0_IRQHandler
DMA1_Stream1_IRQHandler
DMA1_Stream2_IRQHandler
DMA1_Stream3_IRQHandler
DMA1_Stream4_IRQHandler
DMA1_Stream5_IRQHandler
DMA1_Stream6_IRQHandler
ADC_IRQHandler
EXTI9_5_IRQHandler
TIM1_BRK_TIM9_IRQHandler
TIM1_UP_TIM10_IRQHandler
TIM1_TRG_COM_TIM11_IRQHandler
TIM1_CC_IRQHandler
TIM2_IRQHandler
TIM3_IRQHandler
TIM4_IRQHandler
I2C1_EV_IRQHandler
I2C1_ER_IRQHandler
I2C2_EV_IRQHandler
I2C2_ER_IRQHandler
SPI1_IRQHandler
SPI2_IRQHandler
USART1_IRQHandler
USART2_IRQHandler
EXTI15_10_IRQHandler
RTC_Alarm_IRQHandler
OTG_FS_WKUP_IRQHandler
DMA1_Stream7_IRQHandler
SDIO_IRQHandler
TIM5_IRQHandler
SPI3_IRQHandler
DMA2_Stream0_IRQHandler
DMA2_Stream1_IRQHandler
DMA2_Stream2_IRQHandler
DMA2_Stream3_IRQHandler
DMA2_Stream4_IRQHandler
ETH_IRQHandler
OTG_FS_IRQHandler
DMA2_Stream5_IRQHandler
DMA2_Stream6_IRQHandler
DMA2_Stream7_IRQHandler
USART6_IRQHandler
I2C3_EV_IRQHandler
I2C3_ER_IRQHandler
FPU_IRQHandler
SPI4_IRQHandler B . ENDP ALIGN ;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************
IF :DEF:__MICROLIB EXPORT __initial_sp
EXPORT __heap_base
EXPORT __heap_limit ELSE IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap __user_initial_stackheap LDR R0, = Heap_Mem
LDR R1, =(Stack_Mem + Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR ALIGN ENDIF END ;************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE*****

STM32 启动文件流程总结

  1. 分配堆栈
  2. 向量表
  3. 中断/异常处理函数
    1. 复位程序(上电复位默认执行的函数)

      1. SystemInit()
      2. __main()
    2. 其他异常处理程序
  4. 导出堆栈信息等给外部使用

STM32启动代码分析及其汇编学习-ARM的更多相关文章

  1. STM32启动代码分析 IAR 比较好

    stm32启动代码分析 (2012-06-12 09:43:31) 转载▼     最近开始使用ST的stm32w108芯片(也是一款zigbee芯片).开始看他的启动代码看的晕晕呼呼呼的. 还好在c ...

  2. STM32启动代码分析

    STM32启动文件简单分析(STM32F10x.s适用范围)定时器, 型号, 名字在<<STM32不完全手册里面>>,我们所有的例程都采用了一个叫STM32F10x.s的启动文 ...

  3. Linux内核启动代码分析二之开发板相关驱动程序加载分析

    Linux内核启动代码分析二之开发板相关驱动程序加载分析 1 从linux开始启动的函数start_kernel开始分析,该函数位于linux-2.6.22/init/main.c  start_ke ...

  4. STM32启动代码详细分析

    最近需要学习iap的功能,因此离不开stm32的启动代码的分析,以前看了很多遍,都看不懂,读书百遍,其义自见,因此我有看了一遍,下面的文章,挺好的,因此转载: 在上电复位后,我们都知道会先运行启动代码 ...

  5. ARM Linux启动代码分析

    前言 在学习.分析之前首先要弄明白一个问题:为什么要分析启动代码? 因为启动代码绝大部分都是用汇编语言写的,对于没学过或者不熟悉汇编语言的同学确实有一定难度,但是如果你想真正深入地学习Linux,那么 ...

  6. iar stm32 启动代码片段分析

    今天查看了 iar 上面的启动文件,好奇堆栈指针到底是什么时候赋值的,所以就仔细的阅读了代码和相关手册,找到了答案. 首先,芯片启动后,会从ROM的首地址处进行执行,那么我们从 linker 里面找找 ...

  7. STM32 启动代码 bootloader

    什么是启动代码?     启动代码是系统上电或者复位后运行的第一段代码,是进入C 语言的main 函数之前需要执行的那段汇编代码.STM32的启动代码在startup_stm32f10x_hd.s 启 ...

  8. Cortex-M0(NXP LPC11C14)启动代码分析

    作者:刘老师,华清远见嵌入式学院讲师. 启动代码的一般作用 1.堆和栈的初始化: 2.向量表定义: 3.地址重映射及中断向量表的转移: 4.初始化有特殊要求的断口: 5.处理器模式: 6.进入C应用程 ...

  9. S3C6410的启动代码分析&nbsp;一

    本文开始第一篇,启动代码的编写,注意,仅仅是启动代码,并不是bootloader,因为只有boot,没有loader. 第一要明确:CPU上电之后,会从某个固定地址执行指令.ARM结构的CPU从地址0 ...

随机推荐

  1. keycloak~自定义rest接口

    rest资源 对于我们集成keycloak来说,你可能会遇到它没有实现的功能,这时需要对kc进行扩展,资源的扩展是其中一个方面,它需要实现RealmResourceProvider和RealmReso ...

  2. CentOS7-磁盘扩容(LVM-非空目录拓展卷空间大小)

    查看存储情况 $ df -kh 查看磁盘情况 $ fdisk -l 创建分区(注:可操作存储上限2TB) $ fdisk /dev/sdb 根据提示,依次输入"n","p ...

  3. Prometheus(一):Web服务环境监控

    写在前面 现每个后端的同学的日常都在跟服务(接口)打交道,维护老的比较大单体应用.按业务拆得相对比较细的新服务.无论企业内部用的,面向用户的前端的服务.流量大的有流量小的,有重要的有不那么重要的. 但 ...

  4. python编程训练

    1. 反转字符串: 1 #encoding=utf-8 2 #import string 3 from collections import deque 4 5 def reverse1(string ...

  5. runtime使用总结

    runtime这个东西,项目是很少用到的,但面试又避不可少,了解其内部的机制对底层的理解还是很有必要的. 1.动态添加属性 拓展类别属性的简单实现 a.定义字面量指针 static char dyna ...

  6. Blazor 数据绑定开发指南

    翻译自 Waqas Anwar 2021年3月21日的文章 <A Developer's Guide to Blazor Data Binding> [1] 现如今,大多数 Web 应用程 ...

  7. Linux下面向TCP连接的C++ Socket编程实例

    Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.即Socket提供了操作上述特殊文件的接口,使用这些接口可以实现网络编程. Socket通信流程图 TCP(Transmis ...

  8. VRRP概述作用及配置

    文章目录 VRRP的概述 VRRP的作用 虚拟路由器 Master报文的发送 VRRP状态机 VRRP华为命令配置 VRRP的概述1.利用VRRP,一组路由器(同一个LAN中的接口),协同工作,但是只 ...

  9. C语言typedef的用法详解

    C语言允许为一个数据类型起一个新的别名,就像给人起"绰号"一样. 起别名的目的不是为了提高程序运行效率,而是为了编码方便.例如有一个结构体的名字是 stu,要想定义一个结构体变量就 ...

  10. SpringMVC架构(一)

    SpringMVC架构 1.1Spring web mvc介绍 Spring web mvc和Struts2都属于表现层的框架,它是Spring框架的一部分,我们可以从Spring的整体结构中看得出来 ...