×
单片机 > 单片机程序设计 > 详情

STM32F103X启动代码详细分析

发布时间:2020-09-02 发布时间:
|

1.      在分析启动代码之前,先把STM32的存储结构说一下:



上面这张图来自CORTEX M3权威指南


STM32F103RTB6 有20k的SRAM,起始地址为0x20000000,128k的闪存flash,起始地址为0x08000000(处于code区域).


        从主闪存存储器启动时,主闪存存储器被映射到启动空间(0x00000000),但仍然能够在它原有的地址(0x08000000)访问它,即闪存存储器的内容可以在两个地址区域访问,0x00000000或0x0800 0000。


         通过boot0和boot1的配置可以选着三种启动方式:



当我们下载程序时,选着的是系统存储器启动,当我们一上电开始跑程序的时候,应选择闪存flash启动.


1.      再明确一下一些代码对齐的规则:


1.1   字对齐: 4字节对齐,ARM指令时32位一跳的; 半字对齐: 2字节对齐.thumb指令是16位一跳的。而CORTEX-M3  是thumb-2指令集,16位32位都有


1.2   注意align的不同:


AREA    STACK, NOINIT, READWRITE, ALIGN=3


此处的align表示接下来的堆栈段是2^3=8字节对齐的


而单纯.align或ALIGN表示字对齐(32位)


3.我想我们还要明确比较重要的一点,既然我们的程序是从flash闪存上开始执行的,在STM32中文手册上由这么一句话:,CPU从地址0x0000 0000获取堆栈顶的地址,并从启动存储器的0x00000004指示的地址开始执行代码。而0x00000004开始的地址放的是什么呢?我可以告诉你从该处开始放的是cortex-m3规定的异常向量表。而且我们还可以确定,0x0000 0004出放的必然是复位异常向量。


4.下面好好来分析启动代码,我从keil得到的文件是STM32F10X.s,跟着我的注释走吧


//栈大小


Stack_Size      EQU    0x00000200                


//定义堆栈段,8字节对齐,注意,是可读写!!而我们的闪存flash是要擦除后才能写的,这就有问题了,说明我们的堆栈段不可能是安排在Flash闪存上的,那安排在哪呢?当然是内部20k的SRAM上啦!


                AREA    STACK, NOINIT, READWRITE, ALIGN=3


//stack_Mem为堆栈的底部,SPACE表示存储Stack_size个 分配单元


Stack_Mem       SPACE  Stack_Size


//__initial_sp很显然表示的是栈顶地址


__initial_sp


//下面是在SRAM上分配堆空间,大小为0


Heap_Size       EQU    0x00000000


 


                AREA    HEAP, NOINIT, READWRITE, ALIGN=3


//__heap_base和Heap_Mem为堆起始地址


__heap_base


Heap_Mem        SPACE  Heap_Size


//__heap_limit为堆结束的地址


__heap_limit


//8字节对齐,在keil中必须要这一条


                PRESERVE8


//使用的是thumb指令集,但是cortex-m3是thumb-2版本,16位和32位的指令都有


       THUMB


//只读代码段


                AREA    RESET, DATA, READONLY


//导出__Vectors中断向量表起始地址,相当于在此声明__Vectors为一个全局变量,别的文件时可以访问到的   


                            EXPORT __Vectors


//前面说过0x0地址必须放堆栈顶地址


__Vectors       DCD    __initial_sp              ; Top ofStack


//接下来是一些异常向量表,当发生该异常时,PC将会跳到这里执行


                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 detect


                DCD    TAMPER_IRQHandler         ; Tamper


                DCD     RTC_IRQHandler            ; RTC


                DCD     FLASH_IRQHandler          ; Flash


                DCD     RCC_IRQHandler            ; RCC


                DCD     EXTI0_IRQHandler          ; EXTI Line 0


                DCD     EXTI1_IRQHandler          ; EXTI Line 1


                DCD     EXTI2_IRQHandler          ; EXTI Line 2


                DCD     EXTI3_IRQHandler          ; EXTI Line 3


                DCD     EXTI4_IRQHandler          ; EXTI Line 4


                DCD     DMAChannel1_IRQHandler    ; DMA Channel 1


                DCD     DMAChannel2_IRQHandler    ; DMA Channel 2


                DCD     DMAChannel3_IRQHandler    ; DMA Channel 3


                DCD     DMAChannel4_IRQHandler    ; DMA Channel 4


                DCD     DMAChannel5_IRQHandler    ; DMA Channel 5


                DCD     DMAChannel6_IRQHandler    ; DMA Channel 6


                DCD     DMAChannel7_IRQHandler    ; DMA Channel 7


                DCD     ADC_IRQHandler            ; ADC


                DCD     USB_HP_CAN_TX_IRQHandler  ; USB High Priority or CAN TX


                DCD     USB_LP_CAN_RX0_IRQHandler ; USB Low  Priority or CAN RX0


                DCD     CAN_RX1_IRQHandler        ; CAN RX1


                DCD     CAN_SCE_IRQHandler        ; CAN SCE


                DCD     EXTI9_5_IRQHandler        ; EXTI Line 9..5


                DCD     TIM1_BRK_IRQHandler       ; TIM1 Break


                DCD     TIM1_UP_IRQHandler        ; TIM1 Update


                DCD     TIM1_TRG_COM_IRQHandler   ; TIM1 Trigger and Commutation


                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      ; EXTI Line 15..10


                DCD     RTCAlarm_IRQHandler       ; RTC Alarm through EXTI Line


                DCD     USBWakeUp_IRQHandler      ; USB Wakeup from suspend


//声明代码段|.text|是约定的代码段名称


AREA    |.text|, CODE,READONLY


//中断异常向量的函数指针


Reset_Handler   PROC


//到处该符号,[WEAK]表示如果外部有同名符号,外部该同名符号是优先使用的


                EXPORT  Reset_Handler             [WEAK]


//__main标号起始不是我们c语言中的main函数,而是C/C++标准实时库函数里的一个初始化子程序__main的入口地址,该程序的一个主要作用是初始化堆栈(对于我们的程序来说是跳转到后面的_user_initial_stackheap标号出进行初始化堆栈),并初始化映象文件,最后跳转到C程序的main函数。我们就理解为__main最后就跳到了main吧


                IMPORT  __main


                LDR     R0, =__main


                BX      R0


                ENDP


//下面就是其他向量的函数地址了,这里只是简单的死循环,不做任何处理,然而很有意思的是,他们都EXPORT…[WEAK]了,所以,当我们要设置该异常的中断向量函数时,以我们设置的同名标号为准,这就是我们经常在keil中写的各个外部中断的handler了,然而,当没有设置这个异常的中断函数就引发了该中断,程序就会死在中断函数入口了。


; Dummy Exception Handlers (infinite loopswhich 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  TAMPER_IRQHandler         [WEAK]


                EXPORT  RTC_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  DMAChannel1_IRQHandler    [WEAK]


                EXPORT  DMAChannel2_IRQHandler    [WEAK]


                EXPORT  DMAChannel3_IRQHandler    [WEAK]


                EXPORT  DMAChannel4_IRQHandler    [WEAK]


                EXPORT  DMAChannel5_IRQHandler    [WEAK]


                EXPORT  DMAChannel6_IRQHandler    [WEAK]


                EXPORT  DMAChannel7_IRQHandler    [WEAK]


                EXPORT  ADC_IRQHandler            [WEAK]


                EXPORT  USB_HP_CAN_TX_IRQHandler  [WEAK]


                EXPORT  USB_LP_CAN_RX0_IRQHandler [WEAK]


                EXPORT  CAN_RX1_IRQHandler        [WEAK]


                EXPORT  CAN_SCE_IRQHandler        [WEAK]


                EXPORT  EXTI9_5_IRQHandler        [WEAK]


                EXPORT  TIM1_BRK_IRQHandler       [WEAK]


                EXPORT  TIM1_UP_IRQHandler        [WEAK]


                EXPORT  TIM1_TRG_COM_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  RTCAlarm_IRQHandler       [WEAK]


                EXPORT  USBWakeUp_IRQHandler      [WEAK]


 


WWDG_IRQHandler


PVD_IRQHandler


TAMPER_IRQHandler


RTC_IRQHandler


FLASH_IRQHandler


RCC_IRQHandler


EXTI0_IRQHandler


EXTI1_IRQHandler


EXTI2_IRQHandler


EXTI3_IRQHandler


EXTI4_IRQHandler


DMAChannel1_IRQHandler


DMAChannel2_IRQHandler


DMAChannel3_IRQHandler


DMAChannel4_IRQHandler


DMAChannel5_IRQHandler


DMAChannel6_IRQHandler


DMAChannel7_IRQHandler


ADC_IRQHandler


USB_HP_CAN_TX_IRQHandler


USB_LP_CAN_RX0_IRQHandler


CAN_RX1_IRQHandler


CAN_SCE_IRQHandler


EXTI9_5_IRQHandler


TIM1_BRK_IRQHandler


TIM1_UP_IRQHandler


TIM1_TRG_COM_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


RTCAlarm_IRQHandler


USBWakeUp_IRQHandler


 


                B       .


 


                ENDP


// 字对齐(32位)


ALIGN


; User Initial Stack & Heap


//这里我们没有定义__MICROLIB,走下面分支


                IF      :DEF:__MICROLIB


                //导出栈顶,堆头和堆尾地址


                EXPORT  __initial_sp


                EXPORT  __heap_base


                EXPORT  __heap_limit


               


                ELSE


               


               


IMPORT __use_two_region_memory


//一个小函数,我们前面提到在__main中会调用他来初始化堆栈


                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


                                     //调回__mian中调用__user_initial_stackheap的地方去


                BX      LR


 


               ALIGN


 


                ENDIF


//汇编结束


END




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
AVR单片机语音识别电路模块设计