STM32F407启动流程浅析

来源:互联网 发布:win7网络小图标不见了 编辑:程序博客网 时间:2024/06/03 21:34

基础知识:了解三个寄存器 SP *13 LR *14 PC *15

尊重版权—借鉴以下博客:
http://blog.sina.com.cn/s/blog_62714d6a0100mjgx.html
http://blog.chinaunix.net/uid-12461657-id-3068269.html
http://blog.csdn.net/zhou1232006/article/details/6149548

BL NEXT ;跳转到子程序 BL是跳转
………
NEXT ;NEXT处执行
……….
MOV PC,LR ;从子程序返回 LR(R14)保存了返回地址PC(R15)是当前地址
BL __MAIN

SP LR PC:=============================================================================
1、堆栈指针r13(SP):*每一种异常模式都有其自己独立的R13*,它通常指向异常模式所专用的堆栈,也就是说五种异常模式、
非异常模式(用户模式和系统模式),都有各自独立的堆栈,用不同的堆栈指针来索引。这样当ARM进入异常模式的时候,
程序就可以把一般通用寄存器压入堆栈,返回时再出栈,保证了各种模式下程序的状态的完整性。

2、连接寄存器r14(LR):每种模式下r14都有自身版组,它有两个特殊功能。

(1)***保存子程序返回地址***。使用BL或BLX时,跳转指令自动把返回地址放入r14中;子程序通过把r14复制到PC来实现返回,通常用下列指令之一:                    MOV PC, LR    将PC指针保存到LR,                    BX LR         跳转LR中PC位置(函数返回) BX讲解见后面通常子程序这样写,保证了子程序中还可以调用子程序。                     stmfd sp!, {lr}   带更新将sp指针保存到lr寄存器中(压栈)                     ……                     ldmfd sp!, {pc}  (弹出)(2)当异常发生时,异常模式的r14用来保存异常返回地址,将r14如栈可以处理嵌套中断。

3、程序计数器r15(PC):PC是有读写限制的。当没有超过读取限制的时候,读取的值是指令的地址加上8个字节,
由于ARM指令总是以字对齐的,故bit[1:0]总是00。当用str或stm存储PC的时候,偏移量有可能是8或12等其它值。
在V3及以下版本中,写入bit[1:0]的值将被忽略,而在V4及以上版本写入r15的bit[1:0]必须为00,否则后果不可预测。

异常:=============================================================================
异常的发生会导致程序正常运行的被打断,并将控制流转移到相应的异常处理(异常响应),
有些异常(fiq、irq)事件处理后,系统还希望能回到当初异常发生时被打断的源程序
断点处继续完成源程序的执行(异常返回),这就需要一种解决方案,用于记录源程序的断
点位置,以便正确的异常返回。 类似的还有子程序的调用和返回。
在主程序中(通过子程序调用指令)调用子程序时,
也需要记录下主程序中的调用点位置,以便将来的子程序的返回。

在ARM处理器中使用 R14实现对断点和调用点的记录,即使用R14用作返回连接寄存器(LR )。在硬件上和指令执行上,CPU 自动完成相应返回点的记录。在ARM 汇编语言程序设计时,R14和LR通用。ARM处理器相应异常时,会自动完成将当前的PC保存到LR寄存器。ARM处理器执行子程序调用指令(BL )时,会自动完成将当前的PC的值减去4的结果数据保存到LR寄存器。即将调用指令的下紧邻指令的地址保存到LR。ARM处理器针对不同的模式,共有6个链接寄存器资源(LR ),其中用户模式和系统

模式共用一个 LR,每种异常模式都有各自专用的R14 寄存器(LR )。这些链接寄存器分别
为 R14、R14_svc、R14_abt、R14_und、R14_irq、R14_fiq,
程序设计者要清晰处理器的模式与相应寄存器的对应关系,都是使用 R14,但不同模式下的R14
不是同一个物理资源,其内容可能天壤之别。
R14 不用做链接寄存器(LR )时,也可以用做通用数据寄存器。

三级流水线:============================================================================
三级流水线:(可以拆分为五级或更高级,但原理与三级流水线类似)
ARM处理器使用流水线来增加处理器指令流的速度,这样可使几个操作同时进行,并使处理与存储器系统之间的操作更加流畅,
连续,能提供0.9MIPS/MHZ的指令执行速度。
PC 代表程序计数器,流水线使用三个阶段,因此指令分为三个阶段执行:
1.取指(从存储器装载一条指令); PC-8的位置
2.译码(识别将要被执行的指令); PC-4的位置
3.执行(处理 指令并将结果写回寄存器)。 PC 当前位置(假设PC当前指向执行的代码)

R15(PC)总是指向“正在取指”的指令,而不是指向“正在执行”的指令或正在“译码”的指令。一般来说,
人们习惯性约定 将“正在执行的指令作为参考点”,称之为当前第一条指令,因此PC总是指向第三条指令。
当ARM状态时,每条指令为4字节长,所以PC始终指向该指令地址 加8字节的地址,即:PC值=当前程序执行位置+8;
ARM指令是三级流水线,取指,译指,执行时同时执行的,现在PC指向的是正在取指的地址,
那么cpu正在译指的指令地址是PC-4(假设在ARM状态 下,一个指令占4个字节),
cpu正在执行的指令地址是PC-8,也就是说PC所指向的地址和现在所执行的指令地址相差8。
当突然发生中断的时候,保存的是PC的地址
如果返回的时候返回PC,那么中间就有一个指令没有执行,所以用SUB PC LR-IRQ #4

十分感谢—参考博客:

http://blog.csdn.net/tianshi_1988/article/details/51084052
一、STM32启动文件解析
MDK5—startup_stm32f40_41xxx.s启动流程分析

;******************** (C) COPYRIGHT 2013 STMicroelectronics ********************;* File Name          : startup_stm32f40_41xxx.s;* Author             : MCD Application Team;* Version            : V1.3.0;* Date               : 08-November-2013;* Description        : STM32F40xxx/41xxx devices vector table for MDK-ARM toolchain.   STM32F40/41XX器件向量表;*                      This module performs:     stm32启动以后模块执行以下操作;*                      - Set the initial SP      设置初始化的SP指针;*                      - Set the initial PC == Reset_Handler  设置初始PC--->指向Reset_Handler;*                      - Set the vector table entries with the exceptions ISR address   设置具有异常ISR地址的向量表条目;*       - Configure the system clock and the external SRAM mounted on STM324xG-EVAL board to be used as data memory (optional, to be enabled by user)         配置系统时钟和外部SRAM并挂载到STM324xG-EVAL板用作数据存储器(可选,可由用户设置);*                      - Branches to __main in the C library (which eventually  分支跳转到C库中的_main(最终调用main());*                        calls main()).;*                      After Reset the CortexM4 processor is in Thread mode,  复位后CortexM4处理器处于线程模式,;*                      priority is Privileged, and the Stack is set to Main.  优先级是Privileged,并且Stack被设置为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          设置堆栈大小为0X400(1k)   EQU伪指令,作用是左边的符号名代表右边的表达式                AREA    STACK, NOINIT, READWRITE, ALIGN=3    ;定义栈段:名称为STACK,未初始化,可读写,ELF 的栈段按2^3=8对齐 Stack_Mem       SPACE   Stack_Size          分配一片连续的存储区域并初始化为 0,栈空间:0x400个字节 __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          ;堆空间:0x200个字节__heap_limit                               ;堆空间结束地址                 PRESERVE8                   ;PRESERVE8 指令指定当前文件保持堆栈八字节对齐                     THUMB                       ;告诉汇编器下面是32位的Thumb指令,如果需要汇编器将插入位以保证对齐   ; Vector Table Mapped to Address 0 at Reset  ;中断向量表定义;向量表在复位时映射到地址0                                              实际上是在CODE区(假设STM32从FLASH启动,则此中断向量表实际起始地址即为0x8000000,映射到0)                 AREA    RESET, DATA, READONLY ;定义一块数据段<DATA>,只可读<READONLY,默认READWRITE>,段名字是RESET                 EXPORT  __Vectors             ;EXPORT:在程序中声明一个全局的标号__Vectors,该标号可在其他的文件中引用                 EXPORT  __Vectors_End         ;在程序中声明一个全局的标号__Vectors_End                 EXPORT  __Vectors_Size        ;在程序中声明一个全局的标号__Vectors_Size  ;DCD(DCDU)用于分配一片连续的字存储单元并用指定的数据初始化。 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++       假如:        0x8000000地址存放的是栈顶地址__initial_sp,                0x8000004地址存放的是复位中断向量Reset_Handler(STM32使用32位总线,因此存储空间为4字节对齐)。+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++               大BOSS:向量表 这个向量表的编写是有讲究的,跟硬件一一对应不能乱写的,CPU找入口地址就靠它了,bin文件开头就是他们的地址               __Vectors       DCD     __initial_sp               ; Top of Stack        ;该处物理地址值存储---栈顶地址__initial_sp所表示的地址值,即为 __Vetors 标号所表示的值                 DCD     Reset_Handler              ; Reset Handler    上电后根据boot引脚来决定PC位置,比如boot设置为flash启动,则启动后PC跳到0x08000000。    此时CPU会先取2个地址,第一个是栈顶地址,第二个是复位异常地址,故有了上面的写法,这样就跳到reset_handler。                DCD     NMI_Handler                ; NMI Handler                DCD     HardFault_Handler          ; Hard Fault Handler    当发生硬件错误中断时,调转到中断错误处理函数--->stm32f4xx_it.c--->                        void HardFault_Handler(void)   //可以发现这个函数是一个什么也不做的死循环,所以发生硬件                        {                               //错误时代码会跑死                            /* Go to infinite loop when Hard Fault exception occurs */                            while (1)                            {                                //CODE可以添加  如果有必要,可以在这种中断处理函数中添加自己的coding                            }                        }                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, 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     FSMC_IRQHandler                   ; FSMC                                                           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     CRYP_IRQHandler                   ; CRYP crypto                                                     DCD     HASH_RNG_IRQHandler               ; Hash and Rng                DCD     FPU_IRQHandler                    ; FPU__Vectors_End        ;Vectors结束 __Vectors_Size  EQU  __Vectors_End - __Vectors      ;得到向量表的大小,304个字节也就是0x130个字节(以上代码累加)  4*(142-66)                AREA    |.text|, CODE, READONLY     ;定义一个代码段,可读,段名字是.text                                                       ;|.text|  用于表示由 C 编译程序产生的代码段,或用于以某种方式与 C 库关联的代码段 ; Reset handler    (复位中断发生以后执行以下过程)    ;利用PROC、ENDP这一对伪指令标记程序开始、结束,把程序段分为若干个过程,                                                    使程序的结构加清晰 Reset_Handler    PROC                 EXPORT  Reset_Handler             [WEAK]  ;WEAK(弱声明)声明其他的同名标号优先于该标号被引用,                                                  就是说如果外面声明了的话,调用外面的对应函数         IMPORT  SystemInit                ;IMPORT:(导出符号表供外部调用(系统初始化))伪指令用于通知编译器要使用的标号在其他的源文件中定义         IMPORT  __main                    ;导出符号表                     LDR     R0, =SystemInit ---->存储器到寄存器的数据加载 system_stm32f4xx.c 中的void SystemInit(void)                                            设置微控制器系统初始化嵌入式Flash接口,PLL并更新 SystemFrequency变量。                     BLX     R0                ;带链接的跳转,同时切换指令集,跳到SystemInit                      LDR     R0, =__main    ;系统初始化之后跳转到main函数执行                     BX      R0             ;切换指令集,main函数不返回跳到__main,进入C的世界                      ENDP; Dummy Exception Handlers (infinite loops which can be modified)NMI_Handler     PROC                EXPORT  NMI_Handler                [WEAK]  不可屏蔽中断处理函数                 B       .                ENDPHardFault_Handler\             ;\意为换行连接符                PROC                EXPORT  HardFault_Handler          [WEAK]  硬件错误处理函数                 B       .                ENDPMemManage_Handler\                PROC                EXPORT  MemManage_Handler          [WEAK]                B       .                ENDPBusFault_Handler\                PROC                EXPORT  BusFault_Handler           [WEAK]                B       .                ENDPUsageFault_Handler\                PROC                EXPORT  UsageFault_Handler         [WEAK]                B       .                ENDPSVC_Handler     PROC                EXPORT  SVC_Handler                [WEAK]                B       .                ENDPDebugMon_Handler\                PROC                EXPORT  DebugMon_Handler           [WEAK]                B       .                ENDPPendSV_Handler  PROC                EXPORT  PendSV_Handler             [WEAK]                B       .                ENDPSysTick_Handler PROC                EXPORT  SysTick_Handler            [WEAK]                B       .                ENDPDefault_Handler PROC   (默认的处理函数---->导出符号表)  ;输出异常向量表标号,方便外部实现异常的具体功能,  [WEAK]是弱定义的意思,如果外部定义了,优先执行外部定义,否则下面的函数定义(与上面相同,上面为定义,这边为导出)            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  FSMC_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  CRYP_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                                                 FSMC_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                                                           CRYP_IRQHandler                                                   HASH_RNG_IRQHandlerFPU_IRQHandler                B       .                ENDP                ALIGN       ;默认是字对齐方式,也说明了代码是4字节对齐的 ;*******************************************************************************; User Stack and Heap initialization   用户堆栈初始化 ;*******************************************************************************                 IF      :DEF:__MICROLIB     ;判断是否使用DEF:__MICROLIB(micro lib),如果勾选了micro lib                  EXPORT  __initial_sp                 EXPORT  __heap_base                 EXPORT  __heap_limit                 ELSE                              ;如果没有勾选micro lib                  IMPORT  __use_two_region_memory    ;两区堆栈空间,堆和栈有各自的空间地址                  EXPORT  __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

1、 AREA指令:伪指令,用于定义代码段或数据段,后跟属性标号。其中比较重要的一个标号为“READONLY”或者“READWRITE”,
其中“READONLY”表示该段为只读属性,联系到STM32的内部存储介质,可知具有只读属性的段保存于FLASH区,即0x8000000地址后。
而“READONLY”表示该段为“可读写”属性,可知“可读写”段保存于SRAM区,即0x2000000地址后。由此可以从第3、7行代码知道,
堆栈段位于SRAM空间。从第82行可知,中断向量表放置与FLASH区,而这也是整片启动代码中最先被放进FLASH区的数据。
因此可以得到一条重要的信息:0x8000000地址存放的是栈顶地址__initial_sp,0x8000004地址存放的是复位中断向量Reset_Handler
(STM32使用32位总线,因此存储空间为4字节对齐)。
2、 DCD指令:作用是开辟一段空间,其意义等价于C语言中的地址符“&”。因此从第84行开始建立的中断向量表则类似于使用C语言
定义了一个指针数组,其每一个成员都是一个函数指针,分别指向各个中断服务函数。
3、 标号:前文多处使用了“标号”一词。标号主要用于表示一片内存空间的某个位置,等价于C语言中的“地址”概念。
地址仅仅表示存储空间的一个位置,从C语言的角度来看,变量的地址,数组的地址或是函数的入口地址在本质上并无区别。
4、 第202行中的__main标号并不表示C程序中的main函数入口地址,因此第204行也并不是跳转至main函数开始执行C程序。
__main标号表示C/C++标准实时库函数里的一个初始化子程序__main的入口地址。该程序的一个主要作用是初始化堆栈
(对于程序清单一来说则是跳转__user_initial_stackheap标号进行初始化堆栈的),并初始化映像文件,最后跳转C程序中的main函数。
这就解释了为何所有的C程序必须有一个main函数作为程序的起点——因为这是由C/C++标准实时库所规定的——并且不能更改,
因为C/C++标准实时库并不对外界开发源代码。因此,实际上在用户可见的前提下,程序在第204行后就跳转至.c文件中的main函数,
开始执行C程序了。至此可以总结一下STM32的启动文件和启动过程。首先对栈和堆的大小进行定义,并在代码区的起始处建立中断向量表,
其第一个表项是栈顶地址,第二个表项是复位中断服务入口地址。然后在复位中断服务程序中跳转¬¬C/C++标准实时库的__main函数,
完成用户堆栈等的初始化后,跳转.c文件中的main函数开始执行C程序。假设STM32被设置为从内部FLASH启动(这也是最常见的一种情况)
,中断向量表起始地位为0x8000000,则栈顶地址存放于0x8000000处,而复位中断服务入口地址存放于0x8000004处。当STM32遇到复位信号后,
则从0x80000004处取出复位中断服务入口地址,继而执行复位中断服务程序,然后跳转__main函数,最后进入mian函数,来到C的世界。

博客地址:
http://blog.sina.com.cn/s/blog_861912cd0100vqm7.html
操作

所有这些指令均会引发跳转,或跳转到 label,或跳转到包含在 Rm 中的地址处。 此外:
BL 和 BLX 指令可将下一个指令的地址复制到 lr(r14,链接寄存器)中。
BX 和 BLX 指令可将处理器的状态从 ARM 更改为 Thumb,或从 Thumb 更改为 ARM。
BLX label 无论何种情况,始终会更改处理器的状态。
BX Rm 和 BLX Rm 可从 Rm 的位 [0] 推算出目标状态:
如果 Rm 的位 [0] 为 0,则处理器的状态会更改为(或保持在)ARM 状态
如果 Rm 的位 [0] 为 1,则处理器的状态会更改为(或保持在)Thumb 状态。

重要函数分析;
void SystemInit(void)
{
/* FPU settings ————————————————————*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
/* Reset the RCC clock configuration to the default reset state ————*/
/* Set HSION bit */ RCC时钟配置—默认复位状态
RCC->CR |= (uint32_t)0x00000001;

/* Reset CFGR register */ 复位配置寄存器
RCC->CFGR = 0x00000000;

/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;

/* Reset PLLCFGR register */ //复位PLL配置寄存器
RCC->PLLCFGR = 0x24003010;

/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;

/* Disable all interrupts */ 关中断
RCC->CIR = 0x00000000;

if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) || defined (PREMAIN_FSMC_SETUP) /* Keil */

SystemInit_ExtMemCtl();

endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM || defined (PREMAIN_FSMC_SETUP) / / Keil */

/* Configure the System clock source, PLL Multiplier and Divider factors,
AHB/APBx prescalers and Flash settings ———————————-*/
SetSysClock(); //设置系统时钟,设置时钟源,倍频或分频设置,AHB/APB桥及FLASH配置

/* Configure the Vector Table location add offset address -配置向量表位置并添加偏移量———-*/

ifdef VECT_TAB_SRAM

SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */

else

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */

endif

}

1,ldr加载指令
LDR指令的格式为:
LDR{条件} 目的寄存器,<存储器地址>
LDR指令用亍从存储器中将一个32位的字数据传送到目的寄存器中。该指令通常用亍从存储器
中读取32位的字数据到通用寄存器,然后对数据迕行处理。当程序计数器PC作为目的寄存器时,
指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。该指令在程序设
计中比较常用,丏寻址方式灵活多样,请读者认真掌握。
指令示例:
LDR R0,[R1] ;将存储器地址为R1的字数据读入寄存器R0。
LDR R0,[R1,R2] ;将存储器地址为R1+R2的字数据读入寄存器R0。
LDR R0,[R1,#8] ;将存储器地址为R1+8的字数据读入寄存器R0。
LDR R0,[R1,R2]!;将存储器地址为R1+R2的字数据读入寄存器R0,幵将新地址R1+R2写入R1。
LDR R0,[R1,#8]! ;将存储器地址为R1+8的字数据读入寄存器R0,幵将新地址R1+8写入R1。
LDR R0,[R1],R2 ;将存储器地址为R1的字数据读入寄存器R0,幵将新地址R1+R2写入R1。
LDR R0,[R1,R2,LSL#2]! ;将存储器地址为R1+R2×4的字数据读入寄存器R0,并将新地址R1+R2×4写入R1。
LDR R0,[R1],R2,LSL#2 ;将存储器地址为R1的字数据读入寄存器R0,幵将新地址R1+R2×4写入R1。”

ARM是RISC结构,数据从内存到CPU乊间的移劢叧能通过L/S指令来完成,也就是ldr/str指令。
比如想把数据从内存中某处读取到寄存器中,叧能使用ldr
比如:
ldr r0, 0x12345678
就是把0x12345678返个地址中的值存放到r0中。

LDR 的两种用法
1)LDR pc, =MyHandleIRQ 表示将MyHandleIRQ符号放入pc寄存器中
2)LDR PC,MyHandleIRQ 表示将读取存储器中MyHandleIRQ符号所表示的地址中的值,及需要多读一次存储器。

在代码中:
start:
ldr pc,=MyHandleReset @jump to HandleReset
ldr pc,=MyHandleUndef @jump to HandleUndef
ldr pc,=MyHandleSWI @jump to HandleSWI
ldr pc,=MyHandleIabort @jump to HandleIabort
ldr pc,=MyHandleDabort @jump to HandleDabort
nop
ldr pc,=MyHandleIRQ @jump to HandleIRQ <=之前出错的一行
ldr pc,=MyHandleFIQ @jump to HandleFIQ

@MyHandleIRQ: .word OS_CPU_IRQ_ISR
MyHandleIRQ:
sub lr, lr, #4 @ to calculate the return address
stmdb sp!, {r0-r12,lr}
ldr lr, =int_return @ restore the return address
ldr pc, =int_handle @ call for the interrupt handler
在“之前出错的一行”处,如果改成“ldr pc,MyHandleIRQ”当中断来临时,无法进行中断处理。

另一种情况是正确的,注意体会:
start:
ldr pc,=MyHandleReset @jump to HandleReset
ldr pc,=MyHandleUndef @jump to HandleUndef
ldr pc,=MyHandleSWI @jump to HandleSWI
ldr pc,=MyHandleIabort @jump to HandleIabort
ldr pc,=MyHandleDabort @jump to HandleDabort
nop
ldr pc,MyHandleIRQ @jump to HandleIRQ <=之前出错的一行
ldr pc,=MyHandleFIQ @jump to HandleFIQ

MyHandleIRQ: .word OS_CPU_IRQ_ISR
@MyHandleIRQ:
@ sub lr, lr, #4 @ to calculate the return address
@ stmdb sp!, {r0-r12,lr}
@ ldr lr, =int_return @ restore the return address
@ ldr pc, =int_handle @ call for the interrupt handler
因为当中断来临时,还需要去MyHandleIRQ处把OS_CPU_IRQ_ISR取出,即多取一次存储器。

小弟刚入行,知识难免有欠缺,所以博客难免会出现错误,博客也没有什么图片之类的,看起来比较单调,希望看者有心,多多包涵,有问题请不吝指出!

0 0
原创粉丝点击