嵌入式学习 - ARM体系结构
嵌入式学习 - STM32存储器映射
嵌入式学习 - STM32F4启动分析
1、启动流程
1.1、 STM32F4启动流程
Cortex-M4
的程序映像通常是从地址0x00000000
开始的,系统复位
(设备上电)后,处理器首先
读取中断向量表
中的前两个字(8个字节),第一个字存入MSP(主线程堆栈指针)
, 第二个字为复位向量地址
,它表示程序执行的起始地址(复位处理)。
STM32F4启动流程
STM32F4启动举例
开发板复位后,访问存储器地址x00000000
,该地址中存储的是闪存、系统存储器或静态存储器(Flash、system memory or SRAM)
等存储空间的首地址(外设存储重映射),它由启动模式(BOOT pins)
决定。当访问
0x00000004
地址时,访问复位向量地址
,读取复位向量
,并执行Reset_Handler复位中断程序
。
注:
复位向量的奇偶
决定是否是Thumb工作状态(LSB=1时)
下运行。STM32F4存储器地址
0x00000004~0x0000 003C
为系统高优先级不可屏蔽中断
向量表;地址0x0000 0040~0x0000 0184
为各种高优先级外设存储器(外部)中断
向量表;具体可参考STM32F4xx中文参考手册.中断和事件
。
1.2、STM32F4启动模式
根据启动模式的不同,
用户闪存
、系统存储器
和SRAM
都可以映射到0x0的低端地址;我们可以通过BOOT pins(Boot0、Boot1)
来选择启动方式。
核心板原理图
从主闪存存储器(Flash memory)启动
:启动地址0x08000000
是STM32内置的Flash, 一般我们使用JTAG或者SWD模式下载程序时,就是下载到这个里面,重启后也直接从这启动程序。基本上都是采用这种模式。
从系统存储器(System memory)启动
:启动地址0x1FFF0000
从系统存储器启动,这种模式启动的程序功能是由厂家设置的。一般来说,这种启动方式用的比较少。系统存储器是芯片内部一块特定的区域,STM32在出厂时,由ST在这个区域内部预置了一段BootLoader, 也就是我们常说的ISP程序,这是一块ROM, 出厂后无法修改。一般来说,我们选用这种启动模式时,是为了从串口下载程序,因为在厂家提供的BootLoader中,提供了串口下载程序的固件,可以通过这个BootLoader将程序下载到系统的Flash中。但是这个下载方式需要以下步骤:
1、
将BOOT0设置为1,BOOT1设置为0,然后按下复位键,这样才能从系统存储器启动BootLoader.
2、
在BootLoader的帮助下,通过串口下载程序到Flash中.
3、
程序下载完成后,需要将BOOT0设置为GND,按下复位,这样,STM32才可以从Flash中启动。可以看到,利用串口下载程序还是比较的麻烦,需要跳帽跳来跳去的,非常的不注重用户体验.
从内置静态存储器(SRAM)启动
:启动地址0x20000000
内置SRAM, 既然是SRAM, 自然也就没有程序存储的能力了,这个模式一般用于程序调试。假如我只修改了代码中一个小小的地方,然后就需要重新檫除整个Flash,比较的费时,可以考虑从这个模式启动代码(也就是STM32的内存中),用于快速的程序调试,等程序调试完成后,在将程序下载到SRAM中。
2、启动文件分析
启动文件由汇编编写,是系统上电复位后第一个执行的程序。主要做了以下工作:
|初始化堆栈指针SP;
|初始化程序计数器指针PC;
|初始化中断向量表;
|调用Systemlnit()函数配置系统时钟;
|调用C库函数"__main”,初始化用户堆栈 (最终用来调用main函数);
;******************** (C) COPYRIGHT 2017 STMicroelectronics ********************
;* File Name : startup_stm32f407xx.s
;* Author : MCD Application Team
;* Description : STM32F407xx 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 设置堆、栈的大小,设置中断向量表的入口地址
;* - 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 >>>
;*******************************************************************************
;
;* Redistribution and use in source and binary forms, with or without modification,
;* are permitted provided that the following conditions are met:
;* 1. Redistributions of source code must retain the above copyright notice,
;* this list of conditions and the following disclaimer.
;* 2. Redistributions in binary form must reproduce the above copyright notice,
;* this list of conditions and the following disclaimer in the documentation
;* and/or other materials provided with the distribution.
;* 3. Neither the name of STMicroelectronics nor the names of its contributors
;* may be used to endorse or promote products derived from this software
;* without specific prior written permission.
;*
;* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
;* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
;* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
;* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
;* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
;* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
;* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
;* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
;* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
;* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
;*******************************************************************************
;*******************************************************************************
; 创建并初始化堆、栈空间
;*******************************************************************************
; 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 0x400 ;定义栈空间大小为1kb。EQU:宏定义的伪指令,相当于c中的define。
; ALIGN:对指令或者数据存放的地址进行对齐,后面会跟一个立即数。缺省表示4字节对齐。
AREA STACK, NOINIT, READWRITE, ALIGN=3 ;AREA:汇编生成一个新代码段或数据段,空间命名为栈STACK,不初始化,可读可写,2^3 = 8字节为单位开辟空间
Stack_Mem SPACE Stack_Size ; SPACE:分配一段大小为1kb的内存空间,作为栈(Stack)空间(地址分配是低地址->高地址),栈:用于局部变量、函数调用和函数形参的开销。
__initial_sp ;初始化堆栈指针sp,它指向栈的结束地址,即栈的顶地址,当栈被使用的时候,是由高地址->低地址生长的。
; <h> Heap Configuration
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Heap_Size EQU 0x200; 定义堆空间大小为0.5kb = 512k
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base ; 堆空间起始地址
Heap_Mem SPACE Heap_Size
__heap_limit ; 堆空间终止地址, 堆的内存使用分配由低地址—>高地址生长,和栈被使用时相反。
PRESERVE8 ;指定当前文件的堆、栈按8字节对齐
THUMB ;表示下面的指令为Thumb指令。Thumb是arm以前的16bit指令集,现在Cortex-M系列使用的是32位的Thumb-2指令集,它兼容16位的Thumb指令集。
;*******************************************************************************
; Vector Table Mapped to Address 0 at Reset 向量表的映射,从0地址开始
; 向量表:一个32位的整型数组,一个元素对应一个异常(ESR 中断服务程序),数组元素存的就是ESR的起始地址。具体请参考中文开发手册的中断和事件章节。
; 当内核响应了一个发生的异常后,对应的异常服务例程(ESR)就会执行。
; EXPORT:声明一个符号具有全局属性,可被外部的文件使用。如果是IAR编译器,则使用的是GLOBAL这个指令。
; DCD:分配一个或多个以字节为单位的内存,以4字节对齐,并要求初始化这些内存。在向量表中,DCD分配一堆内存,并用ESR的起始地址初始化。
;*******************************************************************************
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY ;生成一个数据段RESET
EXPORT __Vectors ; 向量表起始地址
EXPORT __Vectors_End ;向量表结束地址
EXPORT __Vectors_Size ;向量表大小
__Vectors DCD __initial_sp ; Top of Stack 栈顶指针 0x0
DCD Reset_Handler ; Reset Handler 复位向量指针 0x04
DCD NMI_Handler ; NMI Handler 不可屏蔽中断 0x08再上个地址的基础上新增4个字节,下面的依此类推
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 0 表示保留
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, ADC2 and ADC3s
DCD CAN1_TX_IRQHandler ; CAN1 TX
DCD CAN1_RX0_IRQHandler ; CAN1 RX0
DCD CAN1_RX1_IRQHandler ; CAN1 RX1
DCD CAN1_SCE_IRQHandler ; CAN1 SCE
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 USART3_IRQHandler ; USART3
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 TIM8_BRK_TIM12_IRQHandler ; TIM8 Break and TIM12
DCD TIM8_UP_TIM13_IRQHandler ; TIM8 Update and TIM13
DCD TIM8_TRG_COM_TIM14_IRQHandler ; TIM8 Trigger and Commutation and TIM14
DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare
DCD DMA1_Stream7_IRQHandler ; DMA1 Stream7
DCD FMC_IRQHandler ; FMC
DCD SDIO_IRQHandler ; SDIO
DCD TIM5_IRQHandler ; TIM5
DCD SPI3_IRQHandler ; SPI3
DCD UART4_IRQHandler ; UART4
DCD UART5_IRQHandler ; UART5
DCD TIM6_DAC_IRQHandler ; TIM6 and DAC1&2 underrun errors
DCD TIM7_IRQHandler ; TIM7
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 ETH_IRQHandler ; Ethernet
DCD ETH_WKUP_IRQHandler ; Ethernet Wakeup through EXTI line
DCD CAN2_TX_IRQHandler ; CAN2 TX
DCD CAN2_RX0_IRQHandler ; CAN2 RX0
DCD CAN2_RX1_IRQHandler ; CAN2 RX1
DCD CAN2_SCE_IRQHandler ; CAN2 SCE
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 OTG_HS_EP1_OUT_IRQHandler ; USB OTG HS End Point 1 Out
DCD OTG_HS_EP1_IN_IRQHandler ; USB OTG HS End Point 1 In
DCD OTG_HS_WKUP_IRQHandler ; USB OTG HS Wakeup through EXTI
DCD OTG_HS_IRQHandler ; USB OTG HS
DCD DCMI_IRQHandler ; DCMI
DCD 0 ; Reserved
DCD HASH_RNG_IRQHandler ; Hash and Rng
DCD FPU_IRQHandler ; FPU
__Vectors_End ;向量表结束
__Vectors_Size EQU __Vectors_End - __Vectors ;向量表大小 = 结束地址 - 起始地址
AREA |.text|, CODE, READONLY ; 汇编生成一个只读的.text代码文件
;*******************************************************************************
; Reset handler 复位程序(系统上电后第一个执行的程序,调用SystemInit()函数初始化系统时钟,然后调用C库函数__mian,初始化用户堆栈,最终调用main函数前往C的世界。)
;*******************************************************************************
Reset_Handler PROC ;定义了一个复位子程序:Reset_Handler。PROC 是子程序定义伪指令。这里就相当于C语言里定义了一个函数,函数名为Reset_Handler。
EXPORT Reset_Handler [WEAK] ;EXPORT 表示 Reset_Handler 这个子程序可供其他模块调用。相当于C语言的函数声明。关键字[WEAK] 表示弱定义, 如果编译器发现在别处定义了同名的函数,则在链接时用别处的地址进行链接,如果其它地方没有定义,编译器也不报错,以此处地址进行链接。
; SystemInit 和__main 这两个标号在其他文件,在链接的时候需要到其他文件去寻找。 相当于C语言中,从其它文件引入函数声明。以便下面对外部函数进行调用。
; SystemInit 若由我们自己实现,则我们要编写一个具有该名称的函数,用来初始化 STM32 芯片的时钟,一般包括初始化AHB、APB等各总线的时钟, 需要经过一系列的配置STM32才能达到稳定运行的状态。当然这个函数在固件库里面官方有提供。
;__main 其实不是我们定义的(不要与C语言中的main函数混淆),这是一个C库函数,当编译器编译时,只要遇到这个标号就会定义这个函数, 该函数的主要功能是:负责初始化栈、堆,配置系统环境,并在函数的最后调用用户编写的 main 函数,从此去往 C 的世界。
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit ;把 SystemInit 的地址加载到寄存器 R0。
BLX R0 ;程序跳转到 R0 中的地址执行程序,即执行SystemInit函数的内容。
LDR R0, =__main ;把__main 的地址加载到寄存器 R0。
BX R0 ;程序跳转到 R0 中的地址执行程序,即执行__main函数,执行完毕之后就去到我们熟知的 C 世界,进入main函数。
ENDP ;子程序结束。
; LDR、BLX、BX是CM4内核指令,可在《CM3权威指南CnR2》第四章:指令集 中查询到。
; LDR:从存取器中加载字到一个寄存器中
; BL: 跳转到由寄存器给出的地址,并把跳转前的下条质量地址保存到LR
; BLX:跳转到由寄存器给出的地址,并根据寄存器的LSE确定处理器的状态,还要把跳转前的下条指令地址保存到LR
; BX:跳转到由寄存器给出的地址,不用返回
;*******************************************************************************
; Dummy Exception Handlers (infinite loops which can be modified) 中断服务程序
; 若不在外部的C文件里面重新实现中断服务程序,当我们在使用某个外设并开启了某个中断,但是又忘记编写配套的中断服务程序或者函数名写错,那当中断来临的时,程序就会跳转到启动文件这些预先写好的空的中断服务程序中,并且在这个空函数中无限循环(B .),直到内存泄漏程序崩溃。
;*******************************************************************************
;----------------- 系统中断异常 ------------------
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 CAN1_TX_IRQHandler [WEAK]
EXPORT CAN1_RX0_IRQHandler [WEAK]
EXPORT CAN1_RX1_IRQHandler [WEAK]
EXPORT CAN1_SCE_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 USART3_IRQHandler [WEAK]
EXPORT EXTI15_10_IRQHandler [WEAK]
EXPORT RTC_Alarm_IRQHandler [WEAK]
EXPORT OTG_FS_WKUP_IRQHandler [WEAK]
EXPORT TIM8_BRK_TIM12_IRQHandler [WEAK]
EXPORT TIM8_UP_TIM13_IRQHandler [WEAK]
EXPORT TIM8_TRG_COM_TIM14_IRQHandler [WEAK]
EXPORT TIM8_CC_IRQHandler [WEAK]
EXPORT DMA1_Stream7_IRQHandler [WEAK]
EXPORT FMC_IRQHandler [WEAK]
EXPORT SDIO_IRQHandler [WEAK]
EXPORT TIM5_IRQHandler [WEAK]
EXPORT SPI3_IRQHandler [WEAK]
EXPORT UART4_IRQHandler [WEAK]
EXPORT UART5_IRQHandler [WEAK]
EXPORT TIM6_DAC_IRQHandler [WEAK]
EXPORT TIM7_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 ETH_IRQHandler [WEAK]
EXPORT ETH_WKUP_IRQHandler [WEAK]
EXPORT CAN2_TX_IRQHandler [WEAK]
EXPORT CAN2_RX0_IRQHandler [WEAK]
EXPORT CAN2_RX1_IRQHandler [WEAK]
EXPORT CAN2_SCE_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 OTG_HS_EP1_OUT_IRQHandler [WEAK]
EXPORT OTG_HS_EP1_IN_IRQHandler [WEAK]
EXPORT OTG_HS_WKUP_IRQHandler [WEAK]
EXPORT OTG_HS_IRQHandler [WEAK]
EXPORT DCMI_IRQHandler [WEAK]
EXPORT HASH_RNG_IRQHandler [WEAK]
EXPORT FPU_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
CAN1_TX_IRQHandler
CAN1_RX0_IRQHandler
CAN1_RX1_IRQHandler
CAN1_SCE_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
USART3_IRQHandler
EXTI15_10_IRQHandler
RTC_Alarm_IRQHandler
OTG_FS_WKUP_IRQHandler
TIM8_BRK_TIM12_IRQHandler
TIM8_UP_TIM13_IRQHandler
TIM8_TRG_COM_TIM14_IRQHandler
TIM8_CC_IRQHandler
DMA1_Stream7_IRQHandler
FMC_IRQHandler
SDIO_IRQHandler
TIM5_IRQHandler
SPI3_IRQHandler
UART4_IRQHandler
UART5_IRQHandler
TIM6_DAC_IRQHandler
TIM7_IRQHandler
DMA2_Stream0_IRQHandler
DMA2_Stream1_IRQHandler
DMA2_Stream2_IRQHandler
DMA2_Stream3_IRQHandler
DMA2_Stream4_IRQHandler
ETH_IRQHandler
ETH_WKUP_IRQHandler
CAN2_TX_IRQHandler
CAN2_RX0_IRQHandler
CAN2_RX1_IRQHandler
CAN2_SCE_IRQHandler
OTG_FS_IRQHandler
DMA2_Stream5_IRQHandler
DMA2_Stream6_IRQHandler
DMA2_Stream7_IRQHandler
USART6_IRQHandler
I2C3_EV_IRQHandler
I2C3_ER_IRQHandler
OTG_HS_EP1_OUT_IRQHandler
OTG_HS_EP1_IN_IRQHandler
OTG_HS_WKUP_IRQHandler
OTG_HS_IRQHandler
DCMI_IRQHandler
HASH_RNG_IRQHandler
FPU_IRQHandler
B .
ENDP
ALIGN
;*******************************************************************************
; User Stack and Heap initialization 用户堆栈初始化
;*******************************************************************************
IF :DEF:__MICROLIB ;这个宏在KEIL->Options for Target 'xx'->Use MicroLIB这里开启
;用户栈和堆初始化,由C库函数_main来完成
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
;ALIGN:对指令或者数据存放的地址进行对齐,后面会跟一个立即数。缺省表示4字节对齐。
;IF,ELSE,ENDIF:汇编的条件分支语句,跟C语言的if ,else类似
;END:文件结束
;************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE*****
C程序的内存分配
用户堆、栈空间的初始化 Use MicroLIB
启动文件中使用到的arm汇编指令
CM4内核的指令
查找汇编指令:MDK->Help->uVision Help中搜索到,以EQU为例
文章提问
STM32的flash起始地址为0x08000000. CPU怎么从0x00000000处运行的?
当 STM32F4启动模式将BOOT0设置为1,BOOT1设置为x(任意值1或0),此时0x00000000地址处重映射地址0x08000000,即0x00000000的地址存的时0x08000000的地址,然后按下复位键,从片上用户闪存(Flash)启动。
为什么堆栈要分配到SRAM中?在FLASH中可以吗?
1、Flash存储器适用于速度要求高、容量要求大、掉电时要求数据不易丢失的场合,一般用于应用程序的存储。
2、SRAM存储器相当于计算机的内存,读写速度比Flash快N倍,掉电后数据易丢失,一般用于存储程序运行过程中产生的临时数据。
RO Size=Code + ROData(程序占用FLASH空间的大小)
RW Size=RW Data + ZI Data(运行时程序占用RAM空间的大小)
ROM Size=Code + RO Data + RWData(烧写时序占用FLASH空间的大小)
写在最后
STM32F4启动分析
Cortex-M/R 内核启动过程 / 程序启动流程(基于ARMCC、Keil)
Cortex-M/R 内核启动过程 / 程序启动流程(基于IAR)
启动文件详解 — [野火]STM32库开发实战指南
C语言内存管理