【万字长文&全网最全】STM32启动过程详解

STM32启动过程详解

STM32存储架构

首先来一张经典的存储器STM32映射表(STM32F103X):

对于这张图,我们在启动阶段只需要关注两段部分:

  • 位于block 0的Flash段,地址0x08000000-0x0807FFFF,总大小512KB,即对于F103系列,FLASH大小最多512KB。
  • 位于block 1的SRAM段,地址0x20000000-0x2000FFFF,总大小64KB,即对于F103系列,SRAM大小最多为64KB。
  • FLASH是什么?

    ​ FLASH(Flash Memory)即闪存,是一种非易失存储器,说白了,在芯片掉电后其中的内容可以被永久保存,类似电脑的硬盘。我们的代码编译成的可执行文件就放在这里。

    SRAM是什么?

    ​ SRAM(Static Random-Access Memory)即静态随机存取存储器,只要保持通电,这里的数据就可以保存下来,一旦芯片掉电,数据也就不在了,类似电脑的内存。程序运行过程中的自动变量(在函数里声明的变量,保存在栈中,函数调用后被自动释放的变量)、全局变量就保存在这里。

    我们编译好的程序如何正确的存放在FLASH段?程序运行中的变量又如何被暂存至SRAM段呢?这个可以查看Keil中的Options->Target段:

    其中,存储区域(Memory Areas)被分为两部分:

  • 只读存储区(左,Read/Only),保存实际代码,你点击烧写按钮烧录的代码或者通过ISP烧录的代码都会放在这里,Keil自动帮助我们填写好了起始地址和大小,0x8000000是起始地址也就对应存储器映射表中的FLASH区域,大小为0x40000也就是256KB,正好是我选用STM32F103RCT6芯片的FLASH大小。(其实还有别的东西,这个后面再讲)
  • 读写存储区(右,Read/Write),程序运行时的全局变量、自动变量就存放在这里。
  • 启动文件startup_stm32f103xe.s

    接下来我们分析一下启动文件,这个文件是MCU运行起来的核心,里面定义了堆、栈、中断向量表、启动代码。

    汇编文件的结构

    AREA

    汇编文件由多个组成,也可以叫做域(AREA),通过以下方式定义,在其后需要定义一个自定义的任意的段名,后面再更上被编译器解释的参数。

    什么是段呢?其实就是划分一段存储器空间用于存放段内的内容,有过一点编程基础的人都知道,程序中的代码、各种类型的变量都是存放在不同区域的,这里的不同区域就对应汇编中的不同段。我们定义了这些段以及这些段对应的属性,编译器就会帮我们把程序中不同的部分(代码部分、变量部分)链接到不同的内存地址。

    	AREA 段名 属性1,属性2,...
    

    这个段需要被链接到哪个地址就通过后面的属性区分,常见的属性有:

  • CODE:标识这一段为代码段,用于存放只读的指令和代码。在STM32中,属性为CODE的段一般会被放在FLASH中。

  • DATA:标识这一段为数据段,用来存放初始化的全局变量和静态变量,在STM32中,属性为DATA的段一般会被放在SRAM中。【注意这里单指属性只有DATA一个标识的段】

  • NOINIT:标识这一段不初始化,经过我的测试,只有一个NOINIT属性的段被存放在了SRAM中。

  • READONLY:标识这一段为只读,只读的段当然只能存放在FLASH(只读存储区)中了。

  • READWRITE:标识这一段为可读可写,可读写的段当然只能存放在SRAM中了。

  • ALIGN:指定对齐方式,如ALIGN=32^3对齐。

  • 定义段名后,就可以在这个段里添加数据了,指令格式为:

    [标号]	[指令助记符]	[操作数]
    

    标号是给该指令所在的地址取一个名字,可以缺省。

    启动文件分配空间用的指令助记符有:

  • SPACE:申请一块空间,后面的操作数就是所要申请的空间大小
  • DCD:申请一个字(32bit)的空间,后面的操作数就是该块空间的初值
  • AREA后面的指令都会作用在这个段中,直到重新开启下一个段。

    栗子

    我们可以在startup_stm32f103xe.s启动文件中定义一个自己的段,如:

                    AREA    TESTAREA, DATA
    Test_Mem        SPACE   0x100
    Test_Mem_End
    

    这样就定义了一个名为TESTAREA的数据段,并直接在段中申请256字节的空间,用标号Test_Mem代表这块空间的起始地址,后跟了一条只有标号的空指令,用标号Test_Mem_End代表这块空间的结束地址。

    为了不让编译器优化未被使用的段,需要在后面使用一下这个段,我把它的地址附在了中断向量表后:

    ; 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     DMA2_Channel3_IRQHandler   ; DMA2 Channel3
                    DCD     DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5
    				DCD		Test_Mem
    				DCD		Test_Mem_End
    __Vectors_End
    

    通过MAP文件就可以查到这个所段定义的地址了,如何使用MAP文件我们后面再说。

        TESTAREA                                 0x20000014   Section      256  startup_stm32f103xe.o(TESTAREA)
        Test_Mem                                 0x20000014   Data         256  startup_stm32f103xe.o(TESTAREA)
        .bss                                     0x20000114   Section       72  usart.o(.bss)
        Test_Mem_End                             0x20000114   Data           0  startup_stm32f103xe.o(TESTAREA)
    

    从这里可以看到Test_Mem标号的地址是0x20000014,Test_Mem_End标号的地址是0x20000114,说明这个段被存放在了SRAM区,且占用了256字节。

    特别的

    有一个特殊的段名被编译器保留了:即RESET段,程序中必须要存在一个RESET段,指定程序的开端。如果删除这个段或者更名这个段,编译器就会报错:

    Test1\Test1.sct(7): error: L6236E: No section matches selector - no section to be FIRST/LAST.
    Not enough information to list image symbols.
    Not enough information to list load addresses in the image map.
    

    好,基础有了,我们来开始分析真正的启动文件。

    栈区

    在启动文件的最开头,是这样一个段。

    Stack_Size		EQU     0x400
    
                    AREA    STACK, NOINIT, READWRITE, ALIGN=3
    Stack_Mem       SPACE   Stack_Size
    __initial_sp	
    

    这一段定义了STM32中的栈,我们逐行解释一下。

    1. EQU类似C中的#define,这行代码定义了一个变量Stack_Size,它的值是0x400。
    2. AREA表示定义一个区域,名称叫做STACK(栈),不初始化,可读可写,8字节对齐。由于READWRITE属性,这个段肯定会被放置在SRAM中。
    3. 在这个段中申请Stack_Size,即1KB的空间,起始地址用Stack_Mem标号代表。
    4. 用标号__initial_sp标识这段空间的结束地址。

    栈的概念应该都不陌生吧,程序中的自动变量(局部变量)、形参就存放在这里,函数调用结束后自动释放,先进后出。

    堆区

    接下来定义了一个堆区。

    Heap_Size      EQU     0x200
    
                    AREA    HEAP, NOINIT, READWRITE, ALIGN=3
    __heap_base
    Heap_Mem        SPACE   Heap_Size
    __heap_limit
    
    1. 定义了一个变量Heap_Size,它的值是0x200。
    2. 定义一个区域,名称叫做HEAP(堆),不初始化,可读可写,8字节对齐。由于READWRITE属性,这个段肯定会被放置在SRAM中。
    3. 用标号__heap_base标识这段空间的起始地址。
    4. 在这个段中申请Heap_Size,即512字节的空间,起始地址用Heap_Mem标号代表。
    5. 用标号__heap_limit标识这段空间的结束地址。

    RESET区

    接下来定义RESET区,从前面的分析知道,这个区是程序的开端

    ; 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 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     DMA1_Channel1_IRQHandler   ; DMA1 Channel 1
                    DCD     DMA1_Channel2_IRQHandler   ; DMA1 Channel 2
                    DCD     DMA1_Channel3_IRQHandler   ; DMA1 Channel 3
                    DCD     DMA1_Channel4_IRQHandler   ; DMA1 Channel 4
                    DCD     DMA1_Channel5_IRQHandler   ; DMA1 Channel 5
                    DCD     DMA1_Channel6_IRQHandler   ; DMA1 Channel 6
                    DCD     DMA1_Channel7_IRQHandler   ; DMA1 Channel 7
                    DCD     ADC1_2_IRQHandler          ; ADC1 & ADC2
                    DCD     USB_HP_CAN1_TX_IRQHandler  ; USB High Priority or CAN1 TX
                    DCD     USB_LP_CAN1_RX0_IRQHandler ; USB Low  Priority or CAN1 RX0
                    DCD     CAN1_RX1_IRQHandler        ; CAN1 RX1
                    DCD     CAN1_SCE_IRQHandler        ; CAN1 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     RTC_Alarm_IRQHandler        ; RTC Alarm through EXTI Line
                    DCD     USBWakeUp_IRQHandler       ; USB Wakeup from suspend
                    DCD     TIM8_BRK_IRQHandler        ; TIM8 Break
                    DCD     TIM8_UP_IRQHandler         ; TIM8 Update
                    DCD     TIM8_TRG_COM_IRQHandler    ; TIM8 Trigger and Commutation
                    DCD     TIM8_CC_IRQHandler         ; TIM8 Capture Compare
                    DCD     ADC3_IRQHandler            ; ADC3
                    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_IRQHandler            ; TIM6
                    DCD     TIM7_IRQHandler            ; TIM7
                    DCD     DMA2_Channel1_IRQHandler   ; DMA2 Channel1
                    DCD     DMA2_Channel2_IRQHandler   ; DMA2 Channel2
                    DCD     DMA2_Channel3_IRQHandler   ; DMA2 Channel3
                    DCD     DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5
    __Vectors_End
    
    1. 通过指定DATAREADONLY两个属性,这个段肯定会被放置在FLASH中,又因为RESET这个特殊的段名,编译器会把这个段放置在FLASH中最开头的位置,对于当前芯片,地址就是0x08000000

      当这个段只被RESET或者RESET和DATA限定时,它也会被放在FLASH中,但是不是最开头的地方。

      但只需要被RESET和READONLY限定,它就会被正确的放在0x08000000位置。

      这个我还不太明白,不过不影响启动分析,有懂的大佬可以帮忙解答一下。

    2. EXPORT表示声明了三个全局标识(全局变量)__Vectors__Vectors_End__Vectors_Size,可以在其他文件里,如你的main.c中引用这个变量(用前要用extern关键字声明)。

    3. 接下来开始划分空间,使用__Vectors标识代表起始地址,后面跟了一堆DCD表示一个字一个字地申请空间并赋初值。

    4. 第一个字的地址里放了__initial_sp,这个正是前面栈区空间的结束地址。由于STM32的栈是自高地址向低地址(自上向下)生长的,所以这个地址也就是栈顶地址。

    5. 接下来放置了一个标识符Reset_Handler,这个其实是一个函数名,往下翻就能找到它的定义,它存放在了CODE段。

      ; Reset handler
      Reset_Handler   PROC
                      EXPORT  Reset_Handler             [WEAK]
                      IMPORT  __main
                      IMPORT  SystemInit
                      LDR     R0, =SystemInit
                      BLX     R0               
                      LDR     R0, =__main
                      BX      R0
                      ENDP
      
    6. 接下来放置了一个标识符NMI_Handler,这个其实也是一个函数名,往下翻就能找到它的定义,它也存放在了CODE段。

      NMI_Handler     PROC
                      EXPORT  NMI_Handler                [WEAK]
                      B       .
                      ENDP
      
    7. 接下来放置了一个标识符HardFault_Handler,这个其实也是一个函数名,往下翻就能找到它的定义,它也存放在了CODE段。

      HardFault_Handler\
                      PROC
                      EXPORT  HardFault_Handler          [WEAK]
                      B       .
                      ENDP
      
    8. 接下来…

    等等,下面这些都是函数名,而且都可以在文件下面找到它们的定义,这是在干什么?这就需要查阅芯片的参考手册了,在参考手册的2.4小节,是这样说明的:

    在从待机模式退出时,BOOT引脚的值将被被重新锁存;因此,在待机模式下BOOT引脚应保持
    为需要的启动配置。在启动延迟之后,CPU从地址0x0000 0000获取堆栈顶的地址,并从启动
    存储器的0x0000 0004指示的地址开始执行代码

    因为固定的存储器映像,代码区始终从地址0x0000 0000开始(通过ICode和DCode总线访问),
    而数据区(SRAM)始终从地址0x2000 0000开始(通过系统总线访问)。 Cortex-M3的CPU始终从
    ICode总线获取复位向量,即启动仅适合于从代码区开始(典型地从Flash启动)。 STM32F10xxx
    微控制器实现了一个特殊的机制,系统可以不仅仅从Flash存储器或系统存储器启动,还可以从
    内置SRAM启动。
    根据选定的启动模式,主闪存存储器、系统存储器或SRAM可以按照以下方式访问:
    从主闪存存储器启动:主闪存存储器被映射到启动空间(0x0000 0000),但仍然能够在它原
    有的地址(0x0800 0000)访问它,即闪存存储器的内容可以在两个地址区域访问, 0x0000
    0000或0x0800 0000。

    ● 从系统存储器启动:系统存储器被映射到启动空间(0x0000 0000),但仍然能够在它原有的
    地址(互联型产品原有地址为0x1FFF B000,其它产品原有地址为0x1FFF F000)访问它。
    ● 从内置SRAM启动:只能在0x2000 0000开始的地址区访问SRAM

    也就是说,CPU总是在地址0x00000000获取栈顶地址(这个地址将被赋值给主堆栈指针寄存器MSP),而后在地址0x00000004处获取开始执行代码的地址(这个地址将被赋值给程序计数器PC),这个是内核所规定的。而通过不同启动模式的映射,在主闪存存储器启动的模式下,FLASH的地址0x08000000被映射到了0x00000000,这个是芯片厂家,即ST公司所规定的。

    因此,通过对RESET区的定义,地址0x08000000存放了栈区栈顶的地址,供CPU使用,同时地址0x08000004存放了启动函数Reset_Handler的地址,供CPU从这里开始执行

    至此,CPU就可以愉快的拿到这两个最重要的地址,开始程序的执行啦。

    Reset_Handler函数下面定义的那些函数又是作什么的呢?

    其实,对于cortex-m3内核来说,从地址0x00000000开始的这段空间也同时作为了中断向量表(这个表是硬件上的定义,当发生了表中对应的中断事件时,CPU会到对应地址处取地址,执行该地址上的程序),我们可以在参考手册里看到中断向量表的定义:

    看它们的名字,正好与RESET区中的函数名称一致。再看右侧的地址,这里的地址并不是偏移地址,而是内核的取指地址,可以看到,地址为0x00000000的地方没有定义,实际上由上面的分析我们知道,这里放了一个特殊的地址:堆栈指针的地址。而紧跟着的一个中断则是Reset复位中断,地址为0x08000004这也正好与上面从启动存储器的0x0000 0004指示的地址开始执行代码相对应,在CPU复位后,即执行Reset复位中断。按照这个表的要求,我们在RESET区中定义了每个地址所对应的函数地址(中断服务函数)。

    代码区

     AREA    |.text|, CODE, READONLY
                    
    ; Reset handler
    Reset_Handler   PROC
                    EXPORT  Reset_Handler             [WEAK]
                    IMPORT  __main
                    IMPORT  SystemInit
                    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  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  DMA1_Channel1_IRQHandler   [WEAK]
                    EXPORT  DMA1_Channel2_IRQHandler   [WEAK]
                    EXPORT  DMA1_Channel3_IRQHandler   [WEAK]
                    EXPORT  DMA1_Channel4_IRQHandler   [WEAK]
                    EXPORT  DMA1_Channel5_IRQHandler   [WEAK]
                    EXPORT  DMA1_Channel6_IRQHandler   [WEAK]
                    EXPORT  DMA1_Channel7_IRQHandler   [WEAK]
                    EXPORT  ADC1_2_IRQHandler          [WEAK]
                    EXPORT  USB_HP_CAN1_TX_IRQHandler  [WEAK]
                    EXPORT  USB_LP_CAN1_RX0_IRQHandler [WEAK]
                    EXPORT  CAN1_RX1_IRQHandler        [WEAK]
                    EXPORT  CAN1_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  RTC_Alarm_IRQHandler        [WEAK]
                    EXPORT  USBWakeUp_IRQHandler       [WEAK]
                    EXPORT  TIM8_BRK_IRQHandler        [WEAK]
                    EXPORT  TIM8_UP_IRQHandler         [WEAK]
                    EXPORT  TIM8_TRG_COM_IRQHandler    [WEAK]
                    EXPORT  TIM8_CC_IRQHandler         [WEAK]
                    EXPORT  ADC3_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_IRQHandler            [WEAK]
                    EXPORT  TIM7_IRQHandler            [WEAK]
                    EXPORT  DMA2_Channel1_IRQHandler   [WEAK]
                    EXPORT  DMA2_Channel2_IRQHandler   [WEAK]
                    EXPORT  DMA2_Channel3_IRQHandler   [WEAK]
                    EXPORT  DMA2_Channel4_5_IRQHandler [WEAK]
    
    WWDG_IRQHandler
    PVD_IRQHandler
    TAMPER_IRQHandler
    RTC_IRQHandler
    FLASH_IRQHandler
    RCC_IRQHandler
    EXTI0_IRQHandler
    EXTI1_IRQHandler
    EXTI2_IRQHandler
    EXTI3_IRQHandler
    EXTI4_IRQHandler
    DMA1_Channel1_IRQHandler
    DMA1_Channel2_IRQHandler
    DMA1_Channel3_IRQHandler
    DMA1_Channel4_IRQHandler
    DMA1_Channel5_IRQHandler
    DMA1_Channel6_IRQHandler
    DMA1_Channel7_IRQHandler
    ADC1_2_IRQHandler
    USB_HP_CAN1_TX_IRQHandler
    USB_LP_CAN1_RX0_IRQHandler
    CAN1_RX1_IRQHandler
    CAN1_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
    RTC_Alarm_IRQHandler
    USBWakeUp_IRQHandler
    TIM8_BRK_IRQHandler
    TIM8_UP_IRQHandler
    TIM8_TRG_COM_IRQHandler
    TIM8_CC_IRQHandler
    ADC3_IRQHandler
    FSMC_IRQHandler
    SDIO_IRQHandler
    TIM5_IRQHandler
    SPI3_IRQHandler
    UART4_IRQHandler
    UART5_IRQHandler
    TIM6_IRQHandler
    TIM7_IRQHandler
    DMA2_Channel1_IRQHandler
    DMA2_Channel2_IRQHandler
    DMA2_Channel3_IRQHandler
    DMA2_Channel4_5_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
    
    

    后面的这些代码都放在了段区。

    1. 定义一个区域,名称叫做.text,代码段,只读。由于READONLYCODE属性,这个段肯定会被放置在FLASH中。

    2. 后面的内容其实就是定义了那些在中断向量表中出现的函数名,由PROCENDP包围的内容就是函数体,[WEAK]指令表示该函数在这里的定义为弱定义,可以在其他文件中重新定义该函数。另外还定义了一个__user_initial_stackheap函数用于在不使用微库__MICROLIB时负责初始化堆栈。

    3. 特别的,对于Default_Handler函数,定义函数地址后使用EXPORT导出各个中断服务函数的符号,随后跟了一堆只有标号的空指令,使用标号定义如WWDG_IRQHandler等中断服务函数的地址,这使得这些中断服务函数的地址都与Default_Handler地址相同。因此,当程序产生未被外部重新定义的中断的时候,就会进入到Default_Handler这个函数中执行,在这个函数的最后是一条指令B.,它表示无条件跳转到当前指令的位置,即进入死循环

    4. 在汇编文件的最后,定义了堆栈初始化的代码,表示如果定义了微库__MICROLIB,则不调用下面的堆栈初始化函数__user_initial_stackheap,由微库进行初始化。若未定义微库,则使用__user_initial_stackheap函数初始化堆栈。

      微库在这里勾选使用。

    STM32内存管理与.map文件分析

    堆、栈、代码、全局变量、局部变量都是放在哪里的呢?它们之间又怎么组织的呢?如何分析软件的代码占用和运行占用呢?

    我们从.map文件入手分析,.map 文件是编译器生成的一种映射文件,主要用于描述程序的内存布局和符号信息。

    段参考信息(Section Cross References)

    Section Cross References
    
        startup_stm32f103xe.o(RESET) refers to startup_stm32f103xe.o(STACK) for __initial_sp
        startup_stm32f103xe.o(RESET) refers to startup_stm32f103xe.o(.text) for Reset_Handler
        startup_stm32f103xe.o(RESET) refers to stm32f1xx_it.o(i.NMI_Handler) for NMI_Handler
        startup_stm32f103xe.o(RESET) refers to stm32f1xx_it.o(i.HardFault_Handler) for HardFault_Handler
        startup_stm32f103xe.o(RESET) refers to stm32f1xx_it.o(i.MemManage_Handler) for MemManage_Handler
        startup_stm32f103xe.o(RESET) refers to stm32f1xx_it.o(i.BusFault_Handler) for BusFault_Handler
        startup_stm32f103xe.o(RESET) refers to stm32f1xx_it.o(i.UsageFault_Handler) for UsageFault_Handler
        ...
        ...
    

    文件中的第一段Section Cross References提供了程序段之间的引用关系的详细信息,从RESET函数开始,分析各个符合的链接来源,如第一行:__initial_sp 是从同一个对象文件(startup_stm32f103xe.o)的 STACK 区域中解析的。

    段移除信息(Removing Unused input sections from the image.)

    Removing Unused input sections from the image.
    
        Removing main.o(.rev16_text), (4 bytes).
        Removing main.o(.revsh_text), (4 bytes).
        Removing main.o(.rrx_text), (6 bytes).
        Removing gpio.o(.rev16_text), (4 bytes).
        Removing gpio.o(.revsh_text), (4 bytes).
        ...
        ...
    

    第二段显示了编译器优化代码,移除未使用的空间的详细信息,如前三行我们可以看到从main.o文件中移除了两个四字节的空间占用和一个六字节的空间占用。

    内存符号表(Image Symbol Table)

    符号表,这个表里显示了程序中的一些本地符号和全局符号,如段名、变量名等,分为两大部分,Local Symbols,和Global Symbols

    Local Symbols
        Local Symbols
    
        Symbol Name                              Value     Ov Type        Size  Object(Section)
    
        ../Core/Src/gpio.c                       0x00000000   Number         0  gpio.o ABSOLUTE
        ../Core/Src/main.c                       0x00000000   Number         0  main.o ABSOLUTE
        ../Core/Src/stm32f1xx_hal_msp.c          0x00000000   Number         0  stm32f1xx_hal_msp.o ABSOLUTE
        ../Core/Src/stm32f1xx_it.c               0x00000000   Number         0  stm32f1xx_it.o ABSOLUTE
        ../Core/Src/system_stm32f1xx.c           0x00000000   Number         0  system_stm32f1xx.o ABSOLUTE
        ../Core/Src/usart.c                      0x00000000   Number         0  usart.o ABSOLUTE
        ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c 0x00000000   Number         0  stm32f1xx_hal.o ABSOLUTE
        ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c 0x00000000   Number         0  stm32f1xx_hal_cortex.o ABSOLUTE
        ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c 0x00000000   Number         0  stm32f1xx_hal_dma.o ABSOLUTE
        ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c 0x00000000   Number         0  stm32f1xx_hal_exti.o ABSOLUTE
        ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c 0x00000000   Number         0  stm32f1xx_hal_flash.o ABSOLUTE
        ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c 0x00000000   Number         0  stm32f1xx_hal_flash_ex.o ABSOLUTE
        ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c 0x00000000   Number         0  stm32f1xx_hal_gpio.o ABSOLUTE
        ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c 0x00000000   Number         0  stm32f1xx_hal_gpio_ex.o ABSOLUTE
        ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c 0x00000000   Number         0  stm32f1xx_hal_pwr.o ABSOLUTE
        ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c 0x00000000   Number         0  stm32f1xx_hal_rcc.o ABSOLUTE
        ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c 0x00000000   Number         0  stm32f1xx_hal_rcc_ex.o ABSOLUTE
        ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c 0x00000000   Number         0  stm32f1xx_hal_tim.o ABSOLUTE
        ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c 0x00000000   Number         0  stm32f1xx_hal_tim_ex.o ABSOLUTE
        ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c 0x00000000   Number         0  stm32f1xx_hal_uart.o ABSOLUTE
        ../clib/microlib/division.c              0x00000000   Number         0  uldiv.o ABSOLUTE
        ../clib/microlib/division.c              0x00000000   Number         0  uidiv.o ABSOLUTE
        ../clib/microlib/init/entry.s            0x00000000   Number         0  entry9b.o ABSOLUTE
        ../clib/microlib/init/entry.s            0x00000000   Number         0  entry9a.o ABSOLUTE
        ../clib/microlib/init/entry.s            0x00000000   Number         0  entry8b.o ABSOLUTE
        ../clib/microlib/init/entry.s            0x00000000   Number         0  entry8a.o ABSOLUTE
        ../clib/microlib/init/entry.s            0x00000000   Number         0  entry7a.o ABSOLUTE
        ../clib/microlib/init/entry.s            0x00000000   Number         0  entry11b.o ABSOLUTE
        ../clib/microlib/init/entry.s            0x00000000   Number         0  entry7b.o ABSOLUTE
        ../clib/microlib/init/entry.s            0x00000000   Number         0  entry5.o ABSOLUTE
        ../clib/microlib/init/entry.s            0x00000000   Number         0  entry2.o ABSOLUTE
        ../clib/microlib/init/entry.s            0x00000000   Number         0  entry11a.o ABSOLUTE
        ../clib/microlib/init/entry.s            0x00000000   Number         0  entry.o ABSOLUTE
        ../clib/microlib/init/entry.s            0x00000000   Number         0  entry10b.o ABSOLUTE
        ../clib/microlib/init/entry.s            0x00000000   Number         0  entry10a.o ABSOLUTE
        ../clib/microlib/longlong.c              0x00000000   Number         0  llushr.o ABSOLUTE
        ../clib/microlib/longlong.c              0x00000000   Number         0  llsshr.o ABSOLUTE
        ../clib/microlib/longlong.c              0x00000000   Number         0  llshl.o ABSOLUTE
        ../clib/microlib/printf/printf.c         0x00000000   Number         0  printf4.o ABSOLUTE
        ../clib/microlib/printf/printf.c         0x00000000   Number         0  printfb.o ABSOLUTE
        ../clib/microlib/printf/printf.c         0x00000000   Number         0  printf1.o ABSOLUTE
        ../clib/microlib/printf/printf.c         0x00000000   Number         0  printf3.o ABSOLUTE
        ../clib/microlib/printf/printf.c         0x00000000   Number         0  printf5.o ABSOLUTE
        ../clib/microlib/printf/printf.c         0x00000000   Number         0  printf6.o ABSOLUTE
        ../clib/microlib/printf/printf.c         0x00000000   Number         0  printfa.o ABSOLUTE
        ../clib/microlib/printf/printf.c         0x00000000   Number         0  printf8.o ABSOLUTE
        ../clib/microlib/printf/printf.c         0x00000000   Number         0  printf7.o ABSOLUTE
        ../clib/microlib/printf/printf.c         0x00000000   Number         0  printf0.o ABSOLUTE
        ../clib/microlib/printf/printf.c         0x00000000   Number         0  printf2.o ABSOLUTE
        ../clib/microlib/printf/stubs.s          0x00000000   Number         0  stubs.o ABSOLUTE
        ../clib/microlib/stdio/fputc.c           0x00000000   Number         0  fputc.o ABSOLUTE
        ../clib/microlib/stdio/semi.s            0x00000000   Number         0  semi.o ABSOLUTE
        ../clib/microlib/stdio/streams.c         0x00000000   Number         0  stdout.o ABSOLUTE
        ../clib/microlib/string/memset.c         0x00000000   Number         0  memseta.o ABSOLUTE
        ../clib/microlib/string/strlen.c         0x00000000   Number         0  strlen.o ABSOLUTE
        ../clib/microlib/stubs.s                 0x00000000   Number         0  iusefp.o ABSOLUTE
        ../clib/microlib/stubs.s                 0x00000000   Number         0  iusesemip.o ABSOLUTE
        ../fplib/microlib/fpadd.c                0x00000000   Number         0  dadd.o ABSOLUTE
        ../fplib/microlib/fpdiv.c                0x00000000   Number         0  ddiv.o ABSOLUTE
        ../fplib/microlib/fpepilogue.c           0x00000000   Number         0  depilogue.o ABSOLUTE
        ../fplib/microlib/fpfix.c                0x00000000   Number         0  dfixul.o ABSOLUTE
        ../fplib/microlib/fpmul.c                0x00000000   Number         0  dmul.o ABSOLUTE
        ..\Core\Src\gpio.c                       0x00000000   Number         0  gpio.o ABSOLUTE
        ..\Core\Src\main.c                       0x00000000   Number         0  main.o ABSOLUTE
        ..\Core\Src\stm32f1xx_hal_msp.c          0x00000000   Number         0  stm32f1xx_hal_msp.o ABSOLUTE
        ..\Core\Src\stm32f1xx_it.c               0x00000000   Number         0  stm32f1xx_it.o ABSOLUTE
        ..\Core\Src\system_stm32f1xx.c           0x00000000   Number         0  system_stm32f1xx.o ABSOLUTE
        ..\Core\Src\usart.c                      0x00000000   Number         0  usart.o ABSOLUTE
        ..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c 0x00000000   Number         0  stm32f1xx_hal.o ABSOLUTE
        ..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c 0x00000000   Number         0  stm32f1xx_hal_cortex.o ABSOLUTE
        ..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c 0x00000000   Number         0  stm32f1xx_hal_dma.o ABSOLUTE
        ..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c 0x00000000   Number         0  stm32f1xx_hal_exti.o ABSOLUTE
        ..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c 0x00000000   Number         0  stm32f1xx_hal_flash.o ABSOLUTE
        ..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c 0x00000000   Number         0  stm32f1xx_hal_flash_ex.o ABSOLUTE
        ..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c 0x00000000   Number         0  stm32f1xx_hal_gpio.o ABSOLUTE
        ..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c 0x00000000   Number         0  stm32f1xx_hal_gpio_ex.o ABSOLUTE
        ..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c 0x00000000   Number         0  stm32f1xx_hal_pwr.o ABSOLUTE
        ..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c 0x00000000   Number         0  stm32f1xx_hal_rcc.o ABSOLUTE
        ..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c 0x00000000   Number         0  stm32f1xx_hal_rcc_ex.o ABSOLUTE
        ..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim.c 0x00000000   Number         0  stm32f1xx_hal_tim.o ABSOLUTE
        ..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim_ex.c 0x00000000   Number         0  stm32f1xx_hal_tim_ex.o ABSOLUTE
        ..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_uart.c 0x00000000   Number         0  stm32f1xx_hal_uart.o ABSOLUTE
        cdrcmple.s                               0x00000000   Number         0  cdrcmple.o ABSOLUTE
        dc.s                                     0x00000000   Number         0  dc.o ABSOLUTE
        handlers.s                               0x00000000   Number         0  handlers.o ABSOLUTE
        init.s                                   0x00000000   Number         0  init.o ABSOLUTE
        startup_stm32f103xe.s                    0x00000000   Number         0  startup_stm32f103xe.o ABSOLUTE
        RESET                                    0x08000000   Section      304  startup_stm32f103xe.o(RESET)
        .ARM.Collect$$$$00000000                 0x08000130   Section        0  entry.o(.ARM.Collect$$$$00000000)
        .ARM.Collect$$$$00000001                 0x08000130   Section        4  entry2.o(.ARM.Collect$$$$00000001)
        .ARM.Collect$$$$00000004                 0x08000134   Section        4  entry5.o(.ARM.Collect$$$$00000004)
        .ARM.Collect$$$$00000008                 0x08000138   Section        0  entry7b.o(.ARM.Collect$$$$00000008)
        .ARM.Collect$$$$0000000A                 0x08000138   Section        0  entry8b.o(.ARM.Collect$$$$0000000A)
        .ARM.Collect$$$$0000000B                 0x08000138   Section        8  entry9a.o(.ARM.Collect$$$$0000000B)
        .ARM.Collect$$$$0000000D                 0x08000140   Section        0  entry10a.o(.ARM.Collect$$$$0000000D)
        .ARM.Collect$$$$0000000F                 0x08000140   Section        0  entry11a.o(.ARM.Collect$$$$0000000F)
        .ARM.Collect$$$$00002712                 0x08000140   Section        4  entry2.o(.ARM.Collect$$$$00002712)
        __lit__00000000                          0x08000140   Data           4  entry2.o(.ARM.Collect$$$$00002712)
        .text                                    0x08000144   Section       36  startup_stm32f103xe.o(.text)
        .text                                    0x08000168   Section        0  llushr.o(.text)
        .text                                    0x08000188   Section        0  memseta.o(.text)
        .text                                    0x080001ac   Section        0  strlen.o(.text)
        .text                                    0x080001ba   Section        0  uldiv.o(.text)
        .text                                    0x0800021c   Section       36  init.o(.text)
        .text                                    0x08000240   Section        0  llshl.o(.text)
        i.BusFault_Handler                       0x0800025e   Section        0  stm32f1xx_it.o(i.BusFault_Handler)
        i.DebugMon_Handler                       0x08000260   Section        0  stm32f1xx_it.o(i.DebugMon_Handler)
        i.Error_Handler                          0x08000262   Section        0  main.o(i.Error_Handler)
        i.HAL_DMA_Abort                          0x08000266   Section        0  stm32f1xx_hal_dma.o(i.HAL_DMA_Abort)
        i.HAL_DMA_Abort_IT                       0x080002ac   Section        0  stm32f1xx_hal_dma.o(i.HAL_DMA_Abort_IT)
        i.HAL_GPIO_Init                          0x080003dc   Section        0  stm32f1xx_hal_gpio.o(i.HAL_GPIO_Init)
        i.HAL_GetTick                            0x080005d4   Section        0  stm32f1xx_hal.o(i.HAL_GetTick)
        i.HAL_IncTick                            0x080005e0   Section        0  stm32f1xx_hal.o(i.HAL_IncTick)
        i.HAL_Init                               0x080005f0   Section        0  stm32f1xx_hal.o(i.HAL_Init)
        i.HAL_InitTick                           0x08000614   Section        0  stm32f1xx_hal.o(i.HAL_InitTick)
        i.HAL_MspInit                            0x08000654   Section        0  stm32f1xx_hal_msp.o(i.HAL_MspInit)
        i.HAL_NVIC_EnableIRQ                     0x08000690   Section        0  stm32f1xx_hal_cortex.o(i.HAL_NVIC_EnableIRQ)
        i.HAL_NVIC_SetPriority                   0x080006ac   Section        0  stm32f1xx_hal_cortex.o(i.HAL_NVIC_SetPriority)
        i.HAL_NVIC_SetPriorityGrouping           0x080006ec   Section        0  stm32f1xx_hal_cortex.o(i.HAL_NVIC_SetPriorityGrouping)
        i.HAL_RCC_ClockConfig                    0x08000710   Section        0  stm32f1xx_hal_rcc.o(i.HAL_RCC_ClockConfig)
        i.HAL_RCC_GetPCLK1Freq                   0x0800083c   Section        0  stm32f1xx_hal_rcc.o(i.HAL_RCC_GetPCLK1Freq)
        i.HAL_RCC_GetPCLK2Freq                   0x0800085c   Section        0  stm32f1xx_hal_rcc.o(i.HAL_RCC_GetPCLK2Freq)
        i.HAL_RCC_GetSysClockFreq                0x0800087c   Section        0  stm32f1xx_hal_rcc.o(i.HAL_RCC_GetSysClockFreq)
        i.HAL_RCC_OscConfig                      0x080008c8   Section        0  stm32f1xx_hal_rcc.o(i.HAL_RCC_OscConfig)
        i.HAL_SYSTICK_Config                     0x08000be8   Section        0  stm32f1xx_hal_cortex.o(i.HAL_SYSTICK_Config)
        i.HAL_UARTEx_RxEventCallback             0x08000c10   Section        0  stm32f1xx_hal_uart.o(i.HAL_UARTEx_RxEventCallback)
        i.HAL_UART_ErrorCallback                 0x08000c12   Section        0  stm32f1xx_hal_uart.o(i.HAL_UART_ErrorCallback)
        i.HAL_UART_IRQHandler                    0x08000c14   Section        0  stm32f1xx_hal_uart.o(i.HAL_UART_IRQHandler)
        i.HAL_UART_Init                          0x08000e80   Section        0  stm32f1xx_hal_uart.o(i.HAL_UART_Init)
        i.HAL_UART_MspInit                       0x08000ee4   Section        0  usart.o(i.HAL_UART_MspInit)
        i.HAL_UART_RxCpltCallback                0x08000f64   Section        0  stm32f1xx_hal_uart.o(i.HAL_UART_RxCpltCallback)
        i.HAL_UART_Transmit                      0x08000f66   Section        0  stm32f1xx_hal_uart.o(i.HAL_UART_Transmit)
        i.HAL_UART_TxCpltCallback                0x08001006   Section        0  stm32f1xx_hal_uart.o(i.HAL_UART_TxCpltCallback)
        i.HardFault_Handler                      0x08001008   Section        0  stm32f1xx_it.o(i.HardFault_Handler)
        i.MX_GPIO_Init                           0x0800100c   Section        0  gpio.o(i.MX_GPIO_Init)
        i.MX_USART1_UART_Init                    0x08001048   Section        0  usart.o(i.MX_USART1_UART_Init)
        i.MemManage_Handler                      0x08001080   Section        0  stm32f1xx_it.o(i.MemManage_Handler)
        i.NMI_Handler                            0x08001082   Section        0  stm32f1xx_it.o(i.NMI_Handler)
        i.PendSV_Handler                         0x08001084   Section        0  stm32f1xx_it.o(i.PendSV_Handler)
        i.SVC_Handler                            0x08001086   Section        0  stm32f1xx_it.o(i.SVC_Handler)
        i.SysTick_Handler                        0x08001088   Section        0  stm32f1xx_it.o(i.SysTick_Handler)
        i.SystemClock_Config                     0x0800108c   Section        0  main.o(i.SystemClock_Config)
        i.SystemInit                             0x080010ea   Section        0  system_stm32f1xx.o(i.SystemInit)
        i.UART_DMAAbortOnError                   0x080010ec   Section        0  stm32f1xx_hal_uart.o(i.UART_DMAAbortOnError)
        UART_DMAAbortOnError                     0x080010ed   Thumb Code    16  stm32f1xx_hal_uart.o(i.UART_DMAAbortOnError)
        i.UART_EndRxTransfer                     0x080010fc   Section        0  stm32f1xx_hal_uart.o(i.UART_EndRxTransfer)
        UART_EndRxTransfer                       0x080010fd   Thumb Code    78  stm32f1xx_hal_uart.o(i.UART_EndRxTransfer)
        i.UART_Receive_IT                        0x0800114a   Section        0  stm32f1xx_hal_uart.o(i.UART_Receive_IT)
        UART_Receive_IT                          0x0800114b   Thumb Code   194  stm32f1xx_hal_uart.o(i.UART_Receive_IT)
        i.UART_SetConfig                         0x0800120c   Section        0  stm32f1xx_hal_uart.o(i.UART_SetConfig)
        UART_SetConfig                           0x0800120d   Thumb Code   178  stm32f1xx_hal_uart.o(i.UART_SetConfig)
        i.UART_WaitOnFlagUntilTimeout            0x080012c4   Section        0  stm32f1xx_hal_uart.o(i.UART_WaitOnFlagUntilTimeout)
        UART_WaitOnFlagUntilTimeout              0x080012c5   Thumb Code   114  stm32f1xx_hal_uart.o(i.UART_WaitOnFlagUntilTimeout)
        i.USART1_IRQHandler                      0x08001338   Section        0  stm32f1xx_it.o(i.USART1_IRQHandler)
        i.UsageFault_Handler                     0x08001344   Section        0  stm32f1xx_it.o(i.UsageFault_Handler)
        i.__0sprintf$8                           0x08001348   Section        0  printf8.o(i.__0sprintf$8)
        i.__NVIC_SetPriority                     0x08001370   Section        0  stm32f1xx_hal_cortex.o(i.__NVIC_SetPriority)
        __NVIC_SetPriority                       0x08001371   Thumb Code    32  stm32f1xx_hal_cortex.o(i.__NVIC_SetPriority)
        i.__scatterload_copy                     0x08001390   Section       14  handlers.o(i.__scatterload_copy)
        i.__scatterload_null                     0x0800139e   Section        2  handlers.o(i.__scatterload_null)
        i.__scatterload_zeroinit                 0x080013a0   Section       14  handlers.o(i.__scatterload_zeroinit)
        i._printf_core                           0x080013b0   Section        0  printf8.o(i._printf_core)
        _printf_core                             0x080013b1   Thumb Code   996  printf8.o(i._printf_core)
        i._printf_post_padding                   0x080017c0   Section        0  printf8.o(i._printf_post_padding)
        _printf_post_padding                     0x080017c1   Thumb Code    36  printf8.o(i._printf_post_padding)
        i._printf_pre_padding                    0x080017e4   Section        0  printf8.o(i._printf_pre_padding)
        _printf_pre_padding                      0x080017e5   Thumb Code    46  printf8.o(i._printf_pre_padding)
        i._sputc                                 0x08001812   Section        0  printf8.o(i._sputc)
        _sputc                                   0x08001813   Thumb Code    10  printf8.o(i._sputc)
        i.main                                   0x0800181c   Section        0  main.o(i.main)
        .constdata                               0x080018a8   Section       18  stm32f1xx_hal_rcc.o(.constdata)
        aPredivFactorTable                       0x080018a8   Data           2  stm32f1xx_hal_rcc.o(.constdata)
        aPLLMULFactorTable                       0x080018aa   Data          16  stm32f1xx_hal_rcc.o(.constdata)
        .constdata                               0x080018ba   Section       16  system_stm32f1xx.o(.constdata)
        .constdata                               0x080018ca   Section        8  system_stm32f1xx.o(.constdata)
        .data                                    0x20000000   Section        8  main.o(.data)
        localVar                                 0x20000004   Data           4  main.o(.data)
        .data                                    0x20000008   Section       12  stm32f1xx_hal.o(.data)
        .data                                    0x20000014   Section        4  system_stm32f1xx.o(.data)
        .bss                                     0x20000018   Section       72  usart.o(.bss)
        HEAP                                     0x20000060   Section      512  startup_stm32f103xe.o(HEAP)
        STACK                                    0x20000260   Section     1024  startup_stm32f103xe.o(STACK)
    

    从这个例子里分析,每列依次代表:符号名、符号的值、类型、占用空间、对象(来源)。

    其中,类型主要有以下几种

  • Number:代表这只是一个标志,比如文件名(这个其实是猜想,不太确定),Number类型的符号都不占用空间,所以一般无关紧要。

  • Section:代表这是一个段,这个和汇编文件中的段是一个意思,我们可以看到在.s文件里定义的段名都在这里,比如HEAPSTACK。同时里面还有一些别的段,像.texti.Error_Handler是它所对应的后面的C文件或者汇编文件中所定义的段。

  • Data:代表这是一个数据,其实这个就是C语言中我们所定义的本地静态变量,比如,我们在启动文件中加这样一行:

      static uint32_t localVar[2];
    

    就可以在表里看到

        localVar                                 0x20000004   Data           8  main.o(.data)
    

    这个变量出现了,地址放在了0x20000004的位置(SRAM区),占用空间为8字节。烧写进MCU并使用串口打印这个变量的地址,可以看到这个变量的地址和.map文件中的一致。

    &localVar = 0x20000004	//这是串口打印的数据
    
  • .bss:特别的,.bss也是一个段(类型为Selection),这个段里放置了在其他文件里未初始化的全局变量。

  • Global Symbols
        Global Symbols
    
        Symbol Name                              Value     Ov Type        Size  Object(Section)
    
        BuildAttributes$$THM_ISAv4$P$D$K$B$S$PE$A:L22UL41UL21$X:L11$S22US41US21$IEEE1$IW$USESV6$~STKCKD$USESV7$~SHL$OSPACE$ROPI$EBA8$MICROLIB$REQ8$PRES8$EABIv2 0x00000000   Number         0  anon$$obj.o ABSOLUTE
        __ARM_use_no_argv                        0x00000000   Number         0  main.o ABSOLUTE
        _printf_a                                0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_c                                0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_charcount                        0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_d                                0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_e                                0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_f                                0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_flags                            0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_fp_dec                           0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_fp_hex                           0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_g                                0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_i                                0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_int_dec                          0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_l                                0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_lc                               0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_ll                               0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_lld                              0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_lli                              0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_llo                              0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_llu                              0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_llx                              0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_longlong_dec                     0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_longlong_hex                     0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_longlong_oct                     0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_ls                               0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_mbtowc                           0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_n                                0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_o                                0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_p                                0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_percent                          0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_pre_padding                      0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_return_value                     0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_s                                0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_sizespec                         0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_str                              0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_truncate_signed                  0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_truncate_unsigned                0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_u                                0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_wc                               0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_wctomb                           0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_widthprec                        0x00000000   Number         0  stubs.o ABSOLUTE
        _printf_x                                0x00000000   Number         0  stubs.o ABSOLUTE
        __cpp_initialize__aeabi_                  - Undefined Weak Reference
        __cxa_finalize                            - Undefined Weak Reference
        __decompress                              - Undefined Weak Reference
        _clock_init                               - Undefined Weak Reference
        _microlib_exit                            - Undefined Weak Reference
        __Vectors_Size                           0x00000130   Number         0  startup_stm32f103xe.o ABSOLUTE
        __Vectors                                0x08000000   Data           4  startup_stm32f103xe.o(RESET)
        __Vectors_End                            0x08000130   Data           0  startup_stm32f103xe.o(RESET)
        __main                                   0x08000131   Thumb Code     0  entry.o(.ARM.Collect$$$$00000000)
        _main_stk                                0x08000131   Thumb Code     0  entry2.o(.ARM.Collect$$$$00000001)
        _main_scatterload                        0x08000135   Thumb Code     0  entry5.o(.ARM.Collect$$$$00000004)
        __main_after_scatterload                 0x08000139   Thumb Code     0  entry5.o(.ARM.Collect$$$$00000004)
        _main_clock                              0x08000139   Thumb Code     0  entry7b.o(.ARM.Collect$$$$00000008)
        _main_cpp_init                           0x08000139   Thumb Code     0  entry8b.o(.ARM.Collect$$$$0000000A)
        _main_init                               0x08000139   Thumb Code     0  entry9a.o(.ARM.Collect$$$$0000000B)
        __rt_final_cpp                           0x08000141   Thumb Code     0  entry10a.o(.ARM.Collect$$$$0000000D)
        __rt_final_exit                          0x08000141   Thumb Code     0  entry11a.o(.ARM.Collect$$$$0000000F)
        Reset_Handler                            0x08000145   Thumb Code     8  startup_stm32f103xe.o(.text)
        ADC1_2_IRQHandler                        0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        ADC3_IRQHandler                          0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        CAN1_RX1_IRQHandler                      0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        CAN1_SCE_IRQHandler                      0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        DMA1_Channel1_IRQHandler                 0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        DMA1_Channel2_IRQHandler                 0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        DMA1_Channel3_IRQHandler                 0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        DMA1_Channel4_IRQHandler                 0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        DMA1_Channel5_IRQHandler                 0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        DMA1_Channel6_IRQHandler                 0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        DMA1_Channel7_IRQHandler                 0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        DMA2_Channel1_IRQHandler                 0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        DMA2_Channel2_IRQHandler                 0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        DMA2_Channel3_IRQHandler                 0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        DMA2_Channel4_5_IRQHandler               0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        EXTI0_IRQHandler                         0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        EXTI15_10_IRQHandler                     0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        EXTI1_IRQHandler                         0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        EXTI2_IRQHandler                         0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        EXTI3_IRQHandler                         0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        EXTI4_IRQHandler                         0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        EXTI9_5_IRQHandler                       0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        FLASH_IRQHandler                         0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        FSMC_IRQHandler                          0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        I2C1_ER_IRQHandler                       0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        I2C1_EV_IRQHandler                       0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        I2C2_ER_IRQHandler                       0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        I2C2_EV_IRQHandler                       0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        PVD_IRQHandler                           0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        RCC_IRQHandler                           0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        RTC_Alarm_IRQHandler                     0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        RTC_IRQHandler                           0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        SDIO_IRQHandler                          0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        SPI1_IRQHandler                          0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        SPI2_IRQHandler                          0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        SPI3_IRQHandler                          0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        TAMPER_IRQHandler                        0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        TIM1_BRK_IRQHandler                      0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        TIM1_CC_IRQHandler                       0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        TIM1_TRG_COM_IRQHandler                  0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        TIM1_UP_IRQHandler                       0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        TIM2_IRQHandler                          0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        TIM3_IRQHandler                          0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        TIM4_IRQHandler                          0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        TIM5_IRQHandler                          0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        TIM6_IRQHandler                          0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        TIM7_IRQHandler                          0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        TIM8_BRK_IRQHandler                      0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        TIM8_CC_IRQHandler                       0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        TIM8_TRG_COM_IRQHandler                  0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        TIM8_UP_IRQHandler                       0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        UART4_IRQHandler                         0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        UART5_IRQHandler                         0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        USART2_IRQHandler                        0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        USART3_IRQHandler                        0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        USBWakeUp_IRQHandler                     0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        USB_HP_CAN1_TX_IRQHandler                0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        USB_LP_CAN1_RX0_IRQHandler               0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        WWDG_IRQHandler                          0x0800015f   Thumb Code     0  startup_stm32f103xe.o(.text)
        __aeabi_llsr                             0x08000169   Thumb Code    32  llushr.o(.text)
        _ll_ushift_r                             0x08000169   Thumb Code     0  llushr.o(.text)
        __aeabi_memset                           0x08000189   Thumb Code    14  memseta.o(.text)
        __aeabi_memset4                          0x08000189   Thumb Code     0  memseta.o(.text)
        __aeabi_memset8                          0x08000189   Thumb Code     0  memseta.o(.text)
        __aeabi_memclr                           0x08000197   Thumb Code     4  memseta.o(.text)
        __aeabi_memclr4                          0x08000197   Thumb Code     0  memseta.o(.text)
        __aeabi_memclr8                          0x08000197   Thumb Code     0  memseta.o(.text)
        _memset$wrapper                          0x0800019b   Thumb Code    18  memseta.o(.text)
        strlen                                   0x080001ad   Thumb Code    14  strlen.o(.text)
        __aeabi_uldivmod                         0x080001bb   Thumb Code    98  uldiv.o(.text)
        __scatterload                            0x0800021d   Thumb Code    28  init.o(.text)
        __scatterload_rt2                        0x0800021d   Thumb Code     0  init.o(.text)
        __aeabi_llsl                             0x08000241   Thumb Code    30  llshl.o(.text)
        _ll_shift_l                              0x08000241   Thumb Code     0  llshl.o(.text)
        BusFault_Handler                         0x0800025f   Thumb Code     2  stm32f1xx_it.o(i.BusFault_Handler)
        DebugMon_Handler                         0x08000261   Thumb Code     2  stm32f1xx_it.o(i.DebugMon_Handler)
        Error_Handler                            0x08000263   Thumb Code     4  main.o(i.Error_Handler)
        HAL_DMA_Abort                            0x08000267   Thumb Code    70  stm32f1xx_hal_dma.o(i.HAL_DMA_Abort)
        HAL_DMA_Abort_IT                         0x080002ad   Thumb Code   296  stm32f1xx_hal_dma.o(i.HAL_DMA_Abort_IT)
        HAL_GPIO_Init                            0x080003dd   Thumb Code   462  stm32f1xx_hal_gpio.o(i.HAL_GPIO_Init)
        HAL_GetTick                              0x080005d5   Thumb Code     6  stm32f1xx_hal.o(i.HAL_GetTick)
        HAL_IncTick                              0x080005e1   Thumb Code    12  stm32f1xx_hal.o(i.HAL_IncTick)
        HAL_Init                                 0x080005f1   Thumb Code    32  stm32f1xx_hal.o(i.HAL_Init)
        HAL_InitTick                             0x08000615   Thumb Code    54  stm32f1xx_hal.o(i.HAL_InitTick)
        HAL_MspInit                              0x08000655   Thumb Code    52  stm32f1xx_hal_msp.o(i.HAL_MspInit)
        HAL_NVIC_EnableIRQ                       0x08000691   Thumb Code    26  stm32f1xx_hal_cortex.o(i.HAL_NVIC_EnableIRQ)
        HAL_NVIC_SetPriority                     0x080006ad   Thumb Code    60  stm32f1xx_hal_cortex.o(i.HAL_NVIC_SetPriority)
        HAL_NVIC_SetPriorityGrouping             0x080006ed   Thumb Code    26  stm32f1xx_hal_cortex.o(i.HAL_NVIC_SetPriorityGrouping)
        HAL_RCC_ClockConfig                      0x08000711   Thumb Code   280  stm32f1xx_hal_rcc.o(i.HAL_RCC_ClockConfig)
        HAL_RCC_GetPCLK1Freq                     0x0800083d   Thumb Code    20  stm32f1xx_hal_rcc.o(i.HAL_RCC_GetPCLK1Freq)
        HAL_RCC_GetPCLK2Freq                     0x0800085d   Thumb Code    20  stm32f1xx_hal_rcc.o(i.HAL_RCC_GetPCLK2Freq)
        HAL_RCC_GetSysClockFreq                  0x0800087d   Thumb Code    58  stm32f1xx_hal_rcc.o(i.HAL_RCC_GetSysClockFreq)
        HAL_RCC_OscConfig                        0x080008c9   Thumb Code   778  stm32f1xx_hal_rcc.o(i.HAL_RCC_OscConfig)
        HAL_SYSTICK_Config                       0x08000be9   Thumb Code    40  stm32f1xx_hal_cortex.o(i.HAL_SYSTICK_Config)
        HAL_UARTEx_RxEventCallback               0x08000c11   Thumb Code     2  stm32f1xx_hal_uart.o(i.HAL_UARTEx_RxEventCallback)
        HAL_UART_ErrorCallback                   0x08000c13   Thumb Code     2  stm32f1xx_hal_uart.o(i.HAL_UART_ErrorCallback)
        HAL_UART_IRQHandler                      0x08000c15   Thumb Code   616  stm32f1xx_hal_uart.o(i.HAL_UART_IRQHandler)
        HAL_UART_Init                            0x08000e81   Thumb Code   100  stm32f1xx_hal_uart.o(i.HAL_UART_Init)
        HAL_UART_MspInit                         0x08000ee5   Thumb Code   116  usart.o(i.HAL_UART_MspInit)
        HAL_UART_RxCpltCallback                  0x08000f65   Thumb Code     2  stm32f1xx_hal_uart.o(i.HAL_UART_RxCpltCallback)
        HAL_UART_Transmit                        0x08000f67   Thumb Code   160  stm32f1xx_hal_uart.o(i.HAL_UART_Transmit)
        HAL_UART_TxCpltCallback                  0x08001007   Thumb Code     2  stm32f1xx_hal_uart.o(i.HAL_UART_TxCpltCallback)
        HardFault_Handler                        0x08001009   Thumb Code     2  stm32f1xx_it.o(i.HardFault_Handler)
        MX_GPIO_Init                             0x0800100d   Thumb Code    54  gpio.o(i.MX_GPIO_Init)
        MX_USART1_UART_Init                      0x08001049   Thumb Code    48  usart.o(i.MX_USART1_UART_Init)
        MemManage_Handler                        0x08001081   Thumb Code     2  stm32f1xx_it.o(i.MemManage_Handler)
        NMI_Handler                              0x08001083   Thumb Code     2  stm32f1xx_it.o(i.NMI_Handler)
        PendSV_Handler                           0x08001085   Thumb Code     2  stm32f1xx_it.o(i.PendSV_Handler)
        SVC_Handler                              0x08001087   Thumb Code     2  stm32f1xx_it.o(i.SVC_Handler)
        SysTick_Handler                          0x08001089   Thumb Code     4  stm32f1xx_it.o(i.SysTick_Handler)
        SystemClock_Config                       0x0800108d   Thumb Code    94  main.o(i.SystemClock_Config)
        SystemInit                               0x080010eb   Thumb Code     2  system_stm32f1xx.o(i.SystemInit)
        USART1_IRQHandler                        0x08001339   Thumb Code     6  stm32f1xx_it.o(i.USART1_IRQHandler)
        UsageFault_Handler                       0x08001345   Thumb Code     2  stm32f1xx_it.o(i.UsageFault_Handler)
        __0sprintf$8                             0x08001349   Thumb Code    34  printf8.o(i.__0sprintf$8)
        __1sprintf$8                             0x08001349   Thumb Code     0  printf8.o(i.__0sprintf$8)
        __2sprintf                               0x08001349   Thumb Code     0  printf8.o(i.__0sprintf$8)
        __scatterload_copy                       0x08001391   Thumb Code    14  handlers.o(i.__scatterload_copy)
        __scatterload_null                       0x0800139f   Thumb Code     2  handlers.o(i.__scatterload_null)
        __scatterload_zeroinit                   0x080013a1   Thumb Code    14  handlers.o(i.__scatterload_zeroinit)
        main                                     0x0800181d   Thumb Code    78  main.o(i.main)
        AHBPrescTable                            0x08001892   Data          16  system_stm32f1xx.o(.constdata)
        APBPrescTable                            0x080018a2   Data           8  system_stm32f1xx.o(.constdata)
        Region$$Table$$Base                      0x08001908   Number         0  anon$$obj.o(Region$$Table)
        Region$$Table$$Limit                     0x08001928   Number         0  anon$$obj.o(Region$$Table)
        globalVar                                0x20000008   Data           8  main.o(.data)
        uwTickFreq                               0x20000010   Data           1  stm32f1xx_hal.o(.data)
        uwTickPrio                               0x20000014   Data           4  stm32f1xx_hal.o(.data)
        uwTick                                   0x20000018   Data           4  stm32f1xx_hal.o(.data)
        SystemCoreClock                          0x2000001c   Data           4  system_stm32f1xx.o(.data)
        huart1                                   0x20000020   Data          72  usart.o(.bss)
        gloablVarUsart                           0x20000068   Data          40  usart.o(.bss)
        Heap_Mem                                 0x20000090   Data         512  startup_stm32f103xe.o(HEAP)
        __heap_base                              0x20000090   Data           0  startup_stm32f103xe.o(HEAP)
        __heap_limit                             0x20000290   Data           0  startup_stm32f103xe.o(HEAP)
        __initial_sp                             0x20000690   Data           0  startup_stm32f103xe.o(STACK)
    

    这里放置了一些全局符号,像startup_stm32f103xe.o中使用EXPORT导出的符号就会出现在这个表里,你可以尝试使用EXPORT HEAP这样的汇编语句把Local Symbols里的符号声明为全局,那么它就会从本地符号的表中消失,再出现在全局符号的表里了。

    entry.o·entry2.o这样的文件是由编译器生成的,用于初始化堆栈以及完成进入main函数之前的一些必要操作,比如启动文件里的__main函数就来自于entry.o,可以在Section Cross References表中看到它们的关系。

    startup_stm32f103xe.o(.text) refers to entry.o(.ARM.Collect$$$$00000000) for __main
    

    内存映射表(Memory Map of the image)

    **划重点,这部分最重要。**这个部分描述了程序镜像的加载和执行布局。这部分的前两行如下:

      Image Entry point : 0x08000131
    
      Load Region LR_IROM1 (Base: 0x08000000, Size: 0x00001964, Max: 0x00040000, ABSOLUTE)
    

    第一行说明了程序的入点,也就是Reset_Handler函数所在的地址。(编译器如何知道Reset_Handler是入口呢?这个我没查到)

    第二行写明了程序的加载域,域名称为LR_IROM1,基地址为0x08000000,实际占用大小为0x00001964,即6472字节,最大大小为0x00040000ABSOLUTE表示这个区域的地址是固定的,不能被动态调整。其中基地址和大小都是在Target标签中设置的。

    后面分为两个部分,详细描述了两个执行域内的内存分布结构,分别为:

        Execution Region ER_IROM1 (Exec base: 0x08000000, Load base: 0x08000000, Size: 0x00001944, Max: 0x00040000, ABSOLUTE)
        Execution Region RW_IRAM1 (Exec base: 0x20000000, Load base: 0x08001944, Size: 0x00000690, Max: 0x0000c000, ABSOLUTE)
    

    区域一叫做ER_IROM1,基地址0x08000000,这个区域其实就是要存放在FLASH中的区域。

    区域二叫做RW_IRAM1,基地址0x20000000,这个区域就是要存放在SRAM中的区域。

    这几个区域是在哪里定义的呢,我们可以在输出文件夹里找到后缀为.sct的分散加载文件,这个文件就是MDK根据Target标签下的地址所生成的文件。

    在Linker标签下,只要勾选了Use Memory Layout from Target Dialog,就会自动生成这个分散加载文件,取消勾选这个选项,可以自定义自己的分散加载文件。

    这个文件的内容如下:

    ; *************************************************************
    ; *** Scatter-Loading Description File generated by uVision ***
    ; *************************************************************
    
    LR_IROM1 0x08000000 0x00040000  {    ; load region size_region
      ER_IROM1 0x08000000 0x00040000  {  ; load address = execution address
       *.o (RESET, +First)
       *(InRoot$$Sections)
       .ANY (+RO)
      }
      RW_IRAM1 0x20000000 0x0000C000  {  ; RW data
       .ANY (+RW +ZI)
      }
    }
    

    第一句定义了一个 加载域(Load Region),表示一段存储器区域的起始地址和大小。

    第二句定义了一个执行域,叫做ER_IROM1,表示程序运行时的代码和只读数据所在的存储器区域,在地址0x08000000中存放,其中包括:

  • *.o (RESET, +First):+First表示将 RESET 段(复位处理程序)放在区域的开头,并优先加载。(现在知道为什么必须要定义RESET域了吧)

  • *(InRoot$$Sections):用于放置一些与启动相关的特殊段。

  • .ANY (+RO):分配任意的只读段(放置常量)。

  • 随后定义了一个执行域,叫做RW_IRAM1,即读写数据区域,在地址0x20000000中存放,其中包括:

  • .ANY (+RW +ZI):分配所有可读写段(RW)和零初始化段(ZI)(ZI即初始化为零或者未初始化的全局变量)。
  • 回到.map文件,我们可以看到这两个域:ER_IROM1RW_IRAM1的内存映像。

    ER_IROM1域
    Execution Region ER_IROM1 (Exec base: 0x08000000, Load base: 0x08000000, Size: 0x00001944, Max: 0x00040000, ABSOLUTE)
    
        Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
    
        0x08000000   0x08000000   0x00000130   Data   RO            3    RESET               startup_stm32f103xe.o
        0x08000130   0x08000130   0x00000000   Code   RO         1769  * .ARM.Collect$$$$00000000  mc_w.l(entry.o)
        0x08000130   0x08000130   0x00000004   Code   RO         2039    .ARM.Collect$$$$00000001  mc_w.l(entry2.o)
        0x08000134   0x08000134   0x00000004   Code   RO         2042    .ARM.Collect$$$$00000004  mc_w.l(entry5.o)
        0x08000138   0x08000138   0x00000000   Code   RO         2044    .ARM.Collect$$$$00000008  mc_w.l(entry7b.o)
        0x08000138   0x08000138   0x00000000   Code   RO         2046    .ARM.Collect$$$$0000000A  mc_w.l(entry8b.o)
        0x08000138   0x08000138   0x00000008   Code   RO         2047    .ARM.Collect$$$$0000000B  mc_w.l(entry9a.o)
        0x08000140   0x08000140   0x00000000   Code   RO         2049    .ARM.Collect$$$$0000000D  mc_w.l(entry10a.o)
        0x08000140   0x08000140   0x00000000   Code   RO         2051    .ARM.Collect$$$$0000000F  mc_w.l(entry11a.o)
        0x08000140   0x08000140   0x00000004   Code   RO         2040    .ARM.Collect$$$$00002712  mc_w.l(entry2.o)
        0x08000144   0x08000144   0x00000024   Code   RO            4    .text               startup_stm32f103xe.o
        0x08000168   0x08000168   0x00000020   Code   RO         1772    .text               mc_w.l(llushr.o)
        0x08000188   0x08000188   0x00000024   Code   RO         1774    .text               mc_w.l(memseta.o)
        0x080001ac   0x080001ac   0x0000000e   Code   RO         1776    .text               mc_w.l(strlen.o)
        0x080001ba   0x080001ba   0x00000062   Code   RO         2058    .text               mc_w.l(uldiv.o)
        0x0800021c   0x0800021c   0x00000024   Code   RO         2071    .text               mc_w.l(init.o)
        0x08000240   0x08000240   0x0000001e   Code   RO         2074    .text               mc_w.l(llshl.o)
        0x0800025e   0x0800025e   0x00000002   Code   RO          216    i.BusFault_Handler  stm32f1xx_it.o
        0x08000260   0x08000260   0x00000002   Code   RO          217    i.DebugMon_Handler  stm32f1xx_it.o
        0x08000262   0x08000262   0x00000004   Code   RO           13    i.Error_Handler     main.o
        0x08000266   0x08000266   0x00000046   Code   RO         1138    i.HAL_DMA_Abort     stm32f1xx_hal_dma.o
        0x080002ac   0x080002ac   0x00000130   Code   RO         1139    i.HAL_DMA_Abort_IT  stm32f1xx_hal_dma.o
        0x080003dc   0x080003dc   0x000001f8   Code   RO         1074    i.HAL_GPIO_Init     stm32f1xx_hal_gpio.o
        0x080005d4   0x080005d4   0x0000000c   Code   RO          768    i.HAL_GetTick       stm32f1xx_hal.o
        0x080005e0   0x080005e0   0x00000010   Code   RO          774    i.HAL_IncTick       stm32f1xx_hal.o
        0x080005f0   0x080005f0   0x00000024   Code   RO          775    i.HAL_Init          stm32f1xx_hal.o
        0x08000614   0x08000614   0x00000040   Code   RO          776    i.HAL_InitTick      stm32f1xx_hal.o
        0x08000654   0x08000654   0x0000003c   Code   RO          298    i.HAL_MspInit       stm32f1xx_hal_msp.o
        0x08000690   0x08000690   0x0000001a   Code   RO         1234    i.HAL_NVIC_EnableIRQ  stm32f1xx_hal_cortex.o
        0x080006aa   0x080006aa   0x00000002   PAD
        0x080006ac   0x080006ac   0x00000040   Code   RO         1240    i.HAL_NVIC_SetPriority  stm32f1xx_hal_cortex.o
        0x080006ec   0x080006ec   0x00000024   Code   RO         1241    i.HAL_NVIC_SetPriorityGrouping  stm32f1xx_hal_cortex.o
        0x08000710   0x08000710   0x0000012c   Code   RO          932    i.HAL_RCC_ClockConfig  stm32f1xx_hal_rcc.o
        0x0800083c   0x0800083c   0x00000020   Code   RO          939    i.HAL_RCC_GetPCLK1Freq  stm32f1xx_hal_rcc.o
        0x0800085c   0x0800085c   0x00000020   Code   RO          940    i.HAL_RCC_GetPCLK2Freq  stm32f1xx_hal_rcc.o
        0x0800087c   0x0800087c   0x0000004c   Code   RO          941    i.HAL_RCC_GetSysClockFreq  stm32f1xx_hal_rcc.o
        0x080008c8   0x080008c8   0x00000320   Code   RO          944    i.HAL_RCC_OscConfig  stm32f1xx_hal_rcc.o
        0x08000be8   0x08000be8   0x00000028   Code   RO         1245    i.HAL_SYSTICK_Config  stm32f1xx_hal_cortex.o
        0x08000c10   0x08000c10   0x00000002   Code   RO          406    i.HAL_UARTEx_RxEventCallback  stm32f1xx_hal_uart.o
        0x08000c12   0x08000c12   0x00000002   Code   RO          420    i.HAL_UART_ErrorCallback  stm32f1xx_hal_uart.o
        0x08000c14   0x08000c14   0x0000026c   Code   RO          423    i.HAL_UART_IRQHandler  stm32f1xx_hal_uart.o
        0x08000e80   0x08000e80   0x00000064   Code   RO          424    i.HAL_UART_Init     stm32f1xx_hal_uart.o
        0x08000ee4   0x08000ee4   0x00000080   Code   RO          174    i.HAL_UART_MspInit  usart.o
        0x08000f64   0x08000f64   0x00000002   Code   RO          430    i.HAL_UART_RxCpltCallback  stm32f1xx_hal_uart.o
        0x08000f66   0x08000f66   0x000000a0   Code   RO          432    i.HAL_UART_Transmit  stm32f1xx_hal_uart.o
        0x08001006   0x08001006   0x00000002   Code   RO          435    i.HAL_UART_TxCpltCallback  stm32f1xx_hal_uart.o
        0x08001008   0x08001008   0x00000002   Code   RO          218    i.HardFault_Handler  stm32f1xx_it.o
        0x0800100a   0x0800100a   0x00000002   PAD
        0x0800100c   0x0800100c   0x0000003c   Code   RO          149    i.MX_GPIO_Init      gpio.o
        0x08001048   0x08001048   0x00000038   Code   RO          175    i.MX_USART1_UART_Init  usart.o
        0x08001080   0x08001080   0x00000002   Code   RO          219    i.MemManage_Handler  stm32f1xx_it.o
        0x08001082   0x08001082   0x00000002   Code   RO          220    i.NMI_Handler       stm32f1xx_it.o
        0x08001084   0x08001084   0x00000002   Code   RO          221    i.PendSV_Handler    stm32f1xx_it.o
        0x08001086   0x08001086   0x00000002   Code   RO          222    i.SVC_Handler       stm32f1xx_it.o
        0x08001088   0x08001088   0x00000004   Code   RO          223    i.SysTick_Handler   stm32f1xx_it.o
        0x0800108c   0x0800108c   0x0000005e   Code   RO           14    i.SystemClock_Config  main.o
        0x080010ea   0x080010ea   0x00000002   Code   RO         1735    i.SystemInit        system_stm32f1xx.o
        0x080010ec   0x080010ec   0x00000010   Code   RO          437    i.UART_DMAAbortOnError  stm32f1xx_hal_uart.o
        0x080010fc   0x080010fc   0x0000004e   Code   RO          447    i.UART_EndRxTransfer  stm32f1xx_hal_uart.o
        0x0800114a   0x0800114a   0x000000c2   Code   RO          449    i.UART_Receive_IT   stm32f1xx_hal_uart.o
        0x0800120c   0x0800120c   0x000000b8   Code   RO          450    i.UART_SetConfig    stm32f1xx_hal_uart.o
        0x080012c4   0x080012c4   0x00000072   Code   RO          453    i.UART_WaitOnFlagUntilTimeout  stm32f1xx_hal_uart.o
        0x08001336   0x08001336   0x00000002   PAD
        0x08001338   0x08001338   0x0000000c   Code   RO          224    i.USART1_IRQHandler  stm32f1xx_it.o
        0x08001344   0x08001344   0x00000002   Code   RO          225    i.UsageFault_Handler  stm32f1xx_it.o
        0x08001346   0x08001346   0x00000002   PAD
        0x08001348   0x08001348   0x00000028   Code   RO         1987    i.__0sprintf$8      mc_w.l(printf8.o)
        0x08001370   0x08001370   0x00000020   Code   RO         1247    i.__NVIC_SetPriority  stm32f1xx_hal_cortex.o
        0x08001390   0x08001390   0x0000000e   Code   RO         2083    i.__scatterload_copy  mc_w.l(handlers.o)
        0x0800139e   0x0800139e   0x00000002   Code   RO         2084    i.__scatterload_null  mc_w.l(handlers.o)
        0x080013a0   0x080013a0   0x0000000e   Code   RO         2085    i.__scatterload_zeroinit  mc_w.l(handlers.o)
        0x080013ae   0x080013ae   0x00000002   PAD
        0x080013b0   0x080013b0   0x00000410   Code   RO         1992    i._printf_core      mc_w.l(printf8.o)
        0x080017c0   0x080017c0   0x00000024   Code   RO         1993    i._printf_post_padding  mc_w.l(printf8.o)
        0x080017e4   0x080017e4   0x0000002e   Code   RO         1994    i._printf_pre_padding  mc_w.l(printf8.o)
        0x08001812   0x08001812   0x0000000a   Code   RO         1996    i._sputc            mc_w.l(printf8.o)
        0x0800181c   0x0800181c   0x00000080   Code   RO           15    i.main              main.o
        0x0800189c   0x0800189c   0x00000012   Data   RO          945    .constdata          stm32f1xx_hal_rcc.o
        0x080018ae   0x080018ae   0x00000010   Data   RO         1736    .constdata          system_stm32f1xx.o
        0x080018be   0x080018be   0x00000008   Data   RO         1737    .constdata          system_stm32f1xx.o
        0x080018c6   0x080018c6   0x00000002   PAD
        0x080018c8   0x080018c8   0x0000005a   Data   RO           16    .conststring        main.o
        0x08001922   0x08001922   0x00000002   PAD
        0x08001924   0x08001924   0x00000020   Data   RO         2081    Region$$Table       anon$$obj.o
    

    表中几列分别为:

  • Exec Addr:执行地址,即程序运行时对象所在的地址。
  • Load Addr:加载地址,区别与执行地址,当程序开始运行时,某些数据(如初始化了的全局变量)会被从FLASH加载到SRAM中。
  • Size:这个对象所占用的大小。
  • Type:类型,有以下几种值:Data:有具体值的数据;Code:代码;PAD:占位符,用于内存对齐的空白部分;Zero:表示在程序启动时,这段内存会被清零,而不是从闪存中加载任何值。
  • Attr:属性,RO表示只读,RW表示可读可写。
  • Idx:索引,不知道有什么用。
  • Section Name:段名,有一些常见的身影,比如.text,在启动文件中定义的函数就在这个段里;.constdata常量(const修饰的变量);RESET段;HEAP堆区;STACK栈区;另外.bss代表未初始化数据段,存放未初始化或初始化为零的全局和静态变量。
  • Object:对象,其实就是这个段来自于哪个文件。
  • 总体概览下来,在这个从地址0x08000000开始的ER_IROM1域中,首先放置的就是RESET段,中断向量表,随后是entry文件里的启动文件相关的段,__main函数就在这个段内,随后是startup_stm32f103xe.s这个启动文件里的.text段,再后是其他HAL库的C文件里的段,由于我勾选了使用微库并includestdio.hstring.h,所以还能看到print函数相关的段,再后才是main.c里的段。这些段中间为了对齐,还穿插了一些占位符。

    再最后是一些数据段,主要存放了一些const常量,从这里我们其实就可以看到,常量是存储在FLASH中的,并不会占用SRAM的空间。

    RW_IRAM1域
        Execution Region RW_IRAM1 (Exec base: 0x20000000, Load base: 0x08001944, Size: 0x00000690, Max: 0x0000c000, ABSOLUTE)
    
        Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
    
        0x20000000   0x08001944   0x00000010   Data   RW           17    .data               main.o
        0x20000010   0x08001954   0x0000000c   Data   RW          782    .data               stm32f1xx_hal.o
        0x2000001c   0x08001960   0x00000004   Data   RW         1738    .data               system_stm32f1xx.o
        0x20000020        -       0x00000048   Zero   RW          176    .bss                usart.o
        0x20000068        -       0x00000028   Zero   RW          177    .bss                usart.o
        0x20000090        -       0x00000200   Zero   RW            2    HEAP                startup_stm32f103xe.o
        0x20000290        -       0x00000400   Zero   RW            1    STACK               startup_stm32f103xe.o
    

    这个域首先是从地址0x08001944中加载了0x00000010的数据到0x20000000,这其实就是在从FLASH中取出要初始化为非零值的全局和静态变量值,给到SRAM中。(段名为.data

    可以看到,加载的地址刚好就是EX_IROM域的结束地址,即在加载域中,第一个执行域后还有一部分空间用于存放要初始化的全局或静态变量的初值。

    随后又清零了一些空间,用于存放未初始化或初始化为零的全局和静态变量。(段名为.bss

    最后划分出了堆和栈的空间。

    综上,总结出FLASH中的内存分布图与SRAM中的内存分布图。

    内存占用概况(Image component sizes)

    在最后一部分,统计了程序各个不同属性数据的内存占用情况。

  • 目标文件(用户文件)占用分析

          Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name
    
            60          6          0          0          0        815   gpio.o
           226         38         90         16          0     455793   main.o
            36          8        304          0       1536        800   startup_stm32f103xe.o
           128         24          0         12          0       5893   stm32f1xx_hal.o
           198         14          0          0          0      28923   stm32f1xx_hal_cortex.o
           374          8          0          0          0       1827   stm32f1xx_hal_dma.o
           504         42          0          0          0       2272   stm32f1xx_hal_gpio.o
            60          8          0          0          0        870   stm32f1xx_hal_msp.o
          1240         84         18          0          0       5100   stm32f1xx_hal_rcc.o
          1474         10          0          0          0      10064   stm32f1xx_hal_uart.o
            32          6          0          0          0       4286   stm32f1xx_it.o
             2          0         24          4          0       1107   system_stm32f1xx.o
           184         20          0          0        112       1737   usart.o
    
        ----------------------------------------------------------------------
          4526        268        472         32       1648     519487   Object Totals
             0          0         32          0          0          0   (incl. Generated)
             8          0          4          0          0          0   (incl. Padding)
    
        ----------------------------------------------------------------------
    

    列名含义如下:

  • Code (inc. data):代码段的大小,包含函数的机器指令。

  • RO Data:只读数据大小,例如字符串常量和静态的只读变量。

  • RW Data:读写数据段的大小,指已初始化的全局或静态变量。

  • ZI Data:未初始化数据段(.bss 段)的大小,通常用于存储初始化为零的全局或静态变量。

  • Debug:与调试相关的符号表和调试信息的大小。

  • Object Name:对应的目标文件名称。

  • 库文件占用分析

          Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Library Member Name
    
             0          0          0          0          0          0   entry.o
             0          0          0          0          0          0   entry10a.o
             0          0          0          0          0          0   entry11a.o
             8          4          0          0          0          0   entry2.o
             4          0          0          0          0          0   entry5.o
             0          0          0          0          0          0   entry7b.o
             0          0          0          0          0          0   entry8b.o
             8          4          0          0          0          0   entry9a.o
            30          0          0          0          0          0   handlers.o
            36          8          0          0          0         68   init.o
            30          0          0          0          0         68   llshl.o
            32          0          0          0          0         68   llushr.o
            36          0          0          0          0        108   memseta.o
          1172         50          0          0          0        420   printf8.o
            14          0          0          0          0         68   strlen.o
            98          0          0          0          0         92   uldiv.o
    
        ----------------------------------------------------------------------
          1470         66          0          0          0        892   Library Totals
             2          0          0          0          0          0   (incl. Padding)
    
        ----------------------------------------------------------------------
    
          Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Library Name
    
          1468         66          0          0          0        892   mc_w.l
    
        ----------------------------------------------------------------------
          1470         66          0          0          0        892   Library Totals
    
        ----------------------------------------------------------------------
    
  • 总计大小

          Code (inc. data)   RO Data    RW Data    ZI Data      Debug   
    
          5996        334        472         32       1648     517827   Grand Totals
          5996        334        472         32       1648     517827   ELF Image Totals
          5996        334        472         32          0          0   ROM Totals
    
  • ROM 的总使用情况

        Total RO  Size (Code + RO Data)                 6468 (   6.32kB)
        Total RW  Size (RW Data + ZI Data)              1680 (   1.64kB)
        Total ROM Size (Code + RO Data + RW Data)       6500 (   6.35kB)
    

    其中ROM的大小就是代码大小(Code)+常量数据大小(RO Data)+初始化不为零的全局和静态变量大小(RW Data)。

  • 启动过程分析

    根据以上分析,我们来梳理以下整个系统的启动过程,并补充一些启动细节。

    1. 从地址0x00000000中取得堆栈指针(这个位置由硬件映射到FLASH的0x08000000),赋值给MSP堆栈指针寄存器
    2. 从地址0x00000004中取得复位函数,赋值给PC程序计数器。
    3. 开始运行Reset_Handler函数
    4. 运行SystemInit函数,这个函数用来初始化系统时钟等硬件相关设备。
    5. 运行__main函数,这个函数执行以下几个步骤:
      1. RW Data(初始化不为零的全局和静态变量)从加载地址复制到运行地址中(FLASH中复制到SRAM中),像.map文件中描述的那样。
      2. 初始化ZI Data(初始化为零或未初始化的全局和静态变量),像.map文件中描述的那样。
      3. 运行__rt_entry函数
    6. __rt_entry函数中,执行以下一个步骤:
      1. 调用 __user_setup_stackheap()函数与__rt_stackheap_init()函数,这两个函数按照分散加载文件(.sct)所描述的各区域的绝对地址设置堆和栈。如果没有这一步,我们在.s文件中设置的堆和栈的段就都白瞎了。
      2. 调用__rt_lib_init()函数,这个函数用于初始化所引用的库函数,如果需要,还可以为 main() 设置argcargv参数。
      3. 调用 main()函数

    至此,整个系统就跑起来啦。

    作者:LoneySmoke

    物联沃分享整理
    物联沃-IOTWORD物联网 » 【万字长文&全网最全】STM32启动过程详解

    发表回复