STM32 KEIL里的MAP文件分析

发布者:huanli最新更新时间:2019-04-18 来源: eefocus关键字:STM32  KEIL  MAP 手机看文章 扫描二维码
随时随地手机看文章

一、文件分析流程


1、第一部分:Section Cross References
主要是各个源文件生成的模块之间相互引用的关系。

stm32f10x.o(STACK) refers (Special) to stkheap2.o(.text) for __use_two_region_memory
比如上面这句话,stm32f10x.o是stm32f10x.s生成的目标文件模块,(STACK)是文件内定义的一个段,链接器把它视为一个Section,输入节。它引用了模块stkheap2.o输入节(.text)里面的一个全局符号__use_two_region_memory(可能是一个函数或变量)。这个(Special)不知道是什么含义。

剩下的基本都是这类的意思。

stm32f10x_vector.o(.text) refers to __main.o(!!!main) for __main
__main.o(!!!main) refers to kernel.o(.text) for __rt_entry
kernel.o(.text) refers to usertask.o(.text) for main
上面这几个对于程序意义比较重大用户在启动代码中调用了__main.o模块中的__main函数,__main又调用了kernel.o中的__rt_entry函数,最后kernel.o又调用了用户定义的main主函数。


2、第二部分:Removing Unused input sections from the image.
就是将库中没有用到的函数从可执行映像中删除掉,减小程序的体积。


    Removing os_mbox.o(.text), (1094 bytes).
    Removing os_mutex.o(.text), (1744 bytes).
    Removing os_sem.o(.text), (1016 bytes).


3、第三部分:Image Symbol Table


Local Symbols
符号表里的局部符号。


   ../../angel/boardlib.s  0x00000000   Number         0  boardinit1.o ABSOLUTE
   ../../angel/handlers.s  0x00000000   Number     0  __scatter_copy.o ABSOLUTE
   ../../angel/kernel.s     0x00000000   Number       0  kernel.o ABSOLUTE
   ../../angel/rt.s    0x00000000   Number         0  rt_raise.o ABSOLUTE
   ../../angel/scatter.s   0x00000000   Number         0  __scatter.o ABSOLUTE
   ../../angel/startup.s   0x00000000   Number         0  __main.o ABSOLUTE
   ../../angel/sys.s    0x00000000   Number         0  sys_exit.o ABSOLUTE
   ../../angel/sysapp.c    0x00000000   Number         0  sys_wrch.o ABSOLUTE
   ../../armsys.c       0x00000000   Number         0  _get_argv.o ABSOLUTE
   ../../division_7m.s  0x00000000   Number         0  rtudiv10.o ABSOLUTE
   ../../fpinit.s   0x00000000   Number         0  fpinit.o ABSOLUTE
   ../../heapalloc.c     0x00000000   Number         0  hrguard.o ABSOLUTE
   ../../printf.c     0x00000000   Number     0  _printf_outstr_char.o ABSOLUTE
   ../../signal.c     0x00000000   Number         0  defsig_exit.o ABSOLUTE
   ../../stdlib.c     0x00000000   Number         0  exit.o ABSOLUTE
   ../../stkheap.s      0x00000000   Number         0  heapext.o ABSOLUTE

   以上是一些系统内部的局部符号,还有用户的一些局部符号

4、第四部分:Global Symbols

全局符号
    _terminate_user_alloc                      - Undefined Weak Reference
    _terminateio                              - Undefined Weak Reference
    __Vectors       0x08000000   Data           4  stm32f10x_vector.o(RESET)
    __main         0x08000131   Thumb Code     8  __main.o(!!!main)
    __scatterload    0x08000139   Thumb Code     0  __scatter.o(!!!scatter)
    __scatterload_rt2  0x08000139   Thumb Code    44  __scatter.o(!!!scatter)

这些是一些系统的全局符号



后面这两个符号我认为很重要,在运行库代码将可执行映像从加载视图转变为可执行视图的过程中起到了关键作用。Number是指它并不占据程序空间,而只是一个具有一定数值的符号,类似于程序中用define和EQU定义的。所以这里,我先放下map文件的分析,先通过仿真调试,看这两个数值在程序中怎么用。

 

 果然,在刚开始执行程序时,R10和R11的值就已经被赋值成了这两个值。


   很快就将0x08002dc0到0x08002dcf处的16个字节,4个双字加载到了R0-R3,我们可以分析一下里面的内容,R0就是程序加载视图的RW区的起始地址(0x08002de0),R1就是要输出的执行视图的RW区的地址(0x20000000),R2就是要复制的RW数据的个数,R3是复制函数 ( __scatterload_copy)的地址,类似于一个回调函数。接下来就要用了:0x0800011E 4718  BX  r3这条指令去执行复制工作。


  接下来又将0x08002dd0到0x08002ddf处的16个字节,4个双字加载到了R0-R3,我们可以分析一下里面的内容,R0就是程序加载视图的RW区的起始地址(0x08002de0+0x20=0x08002e00),R1就是要输出的执行视图的RW区的地址(0x20000020),R2就是要复制的RW数据的个数,R3是ZI区域建立函数(  __scatterload_zeroinit )的地址。

执行完成后,程序就会进入BL.W  __rt_entry处进行库的初始化工作。


    经过这么一分析,现在我对于程序的加载映像和执行映像有了较深的理解:

    程序的Code加上RO_Data总共是0x2dc0这么大,地址范围0x0800,0000到0x8000,2dbf。

    然后在0x0800,2dc0-2dcf共16个字节放了RW加载映像地址(0x0800,2de0)、执行映像地址(0x2000,0000)、RW长度(0x20)和将该段数据从加载映像复制到执行映像的函数地址。

    在0x0800,2dd0-2ddf共16个字节放了ZI加载映像地址(0x0800,2e00)、执行映像地址(0x2000,0020)、ZI长度(0x480)和建立ZI、HEAP和STACK执行映像的函数地址。

    在上面的第二个阶段,将ZI清零阶段,程序的ZI长度实际上只有0x20,而库代码留出了0x60的长度。因此数据区的顶端为0x2000,00a0-1。接下来从0x2000,00a0开始为堆的起始地址,堆长度加上程序栈长度为0x2000,04a0,这就是堆栈顶端,也是__initial_SP的初始值。

程序进入_rt_entry后,还要对heapstack进行处理,但我没有看到有什么用的变化。从中对库留出的ZI数据区进行了一些处理,我暂时也看不明白。好了,调试就到这里,回到map文件分析的正途。


5、第五部分:


Memory Map of the image
//映像的内存分布

  Image Entry point : 0x080000ed
//程序的入口点:这里应该是RESET_Handler的地址

  Load Region LR_IROM1 (Base: 0x08000000, Size: 0x00002e00, Max: 0x00020000, ABSOLUTE)
//程序的加载映像地址和长度,2e00=2dc0(代码和常数)+0x20(Region Table是RW的加载和执行地址、ZI与HEAPSTACK的执行地址)+0x20(已经初始化的数据)。

    Execution Region ER_IROM1 (Base: 0x08000000, Size: 0x00002de0, Max: 0x00020000, ABSOLUTE) //这段RO区域的加载映像和执行映像一致。
    Base Addr    Size         Type   Attr      Idx    E Section Name        Object
    0x08000000 0x000000ec   Data   RO      3    RESET               stm32f10x.o
    0x080000ec 0x00000008  Code   RO  191  * !!!main             __main.o(c_w.l)
    Execution Region RW_IRAM1 (Base: 0x20000000, Size: 0x000004a0, Max: 0x00005000, ABSOLUTE) //RW数据区 ZI数据区 Heap和Stack数据区。

    Base Addr    Size         Type   Attr      Idx    E Section Name      Object
    0x20000000   0x00000001   Data   RW        100    .data               tft018.o
    0x20000040   0x00000060   Zero   RW        212    .bss                libspace.o(c_w.l)
    0x20000160   0x00000200   Zero   RW        194    HEAP                startup_stm32f10x_hd.o
    0x20000360   0x00000400   Zero   RW        193    STACK               startup_stm32f10x_hd.o

6、第六部分:Image component sizes

这是指出各个模块的输入节的大小

      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name

       972         58          0         10         32       2416   can.o
       824        168          0         15          0       1791   candemo.o
       928         88          0          0          0       4529   stm32_init.o
        52         18        236          0       1024       2700   stm32f10x.o
      1836         32       4874          1          0       8076   tft018.o

最后给出总长度:这个11744应该=0x2dc0,1184应该0x4a0。11776应该是=0x2e00。

    Total RO  Size (Code + RO Data)                11744 (  11.47kB)
    Total RW  Size (RW Data + ZI Data)              1184 (   1.16kB)
    Total ROM Size (Code + RO Data + RW Data)      11776 (  11.50kB)

二、总结
感觉经过这么分析一遍,对于嵌入式系统程序的静态结构和动态执行流程的了解又深入了一些,当然也还是有些问题并没有了解透彻:留待以后慢慢解决吧。


关键字:STM32  KEIL  MAP 引用地址:STM32 KEIL里的MAP文件分析

上一篇:STM32堆和栈(Heap & Stack)及SRAM存储使用
下一篇:stm32的IO重映射

推荐阅读最新更新时间:2024-11-11 06:19

玩转STM32(8)配置JLink调试器
前面已经介绍了怎么样编译项目,生成一个HEX文件,但是这个目标文件还是储存在电脑上,这样你辛苦写出来的代码,还是一个没有什么作用的文件,即使已经把开发语言变成了机器语言,也是无济于事的。那么怎么样才能把这个目标文件搬到STM32的CPU里面呢?这是有很多种方法的,比如采用STM32的烧写器;比如把目标文件发送给ST公司,让生产这个CPU时,直接写入去;在我这里采用开发的模式,就是使用前面介绍的JLink调试器,它为开发电脑与STM32的CPU建立起一座桥梁,可以把目标文件运送到CPU里面,也可以把CPU里的数据运送出来。有了这座桥梁,就会很方便电脑与STM32的CPU沟通,并且快捷,无论写入文件的速度,还是读取CPU的状态。
[单片机]
玩转<font color='red'>STM32</font>(8)配置JLink调试器
基于STM32的USB枚举过程学习笔记(一)
之前使用ST官方的库以及网络的资料,完成了使用USB HID类进行STM32和PC机的通讯。由于其他原因并没有深入的分析,虽然实现了功能,但是关于USB设备的枚举,以及具体的通讯方式都没有清晰的概念,所以现在回头重新学习USB相关知识。主要参考资料是《圈圈教你玩USB》、USB枚举过程图解,ST官方的USB HID例程。 一,USB数据包 1. USB数据包分类 USB总线上的数据传输以包为基本的单位。USB协议规定了四种包:令牌包、数据包、握手包、特殊包。不同的包通过包中的8位PID域区分。 令牌包 令牌包用于启动 一次USB传输,USB的数据传输必须由主机发起。令牌包有四种: 输出令牌包
[单片机]
stm32串口的flag和it标志位
今天用到stm32的串口,对串口进行配置进行接受数据。之后大家也可以想象到结果是什么,完全没有用哎! 后来慢慢的发现了问题的所在,现做笔记如下: ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT); USART_IT参数: #define USART_IT_PE ((uint16_t)0x0028) #define USART_IT_TXE ((uint16_t)0x0727) #define USART_IT_TC ((uint16_t)0x0626) #define
[单片机]
STM32学习笔记之定时器的配置
实验目的: 让蜂鸣器每隔一秒响一次; 实验步骤: 实验程序: /************************led.c***********************/ #include stm32f4xx.h //在SYSTEM目录下可以找到 #include sys.h void LED_Init(void){ RCC- AHB1ENR |= 1 5; //使能GPIO端口的F时钟 GPIO_Set(GPIOF,PIN9|PIN10,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_25M,GPIO_PUPD_PU);
[单片机]
<font color='red'>STM32</font>学习笔记之定时器的配置
STM32的串口中断
总的来说,STM32单片机的串口还是很好理解的,编程也不算复杂。当然我更愿意希望其中断系统和51单片机一样的简单。 对于接收终端,就是RXNE了,这只在接收完成后才产生,在执行USART_ITConfig(USART1, USART_IT_RXNE, ENABLE)代码时不会进入ISR。但麻烦的就是发送有关的中断了:TXE或者TC,根据资料和测试的结果,TXE在复位后就是置1的,即在执行USART_ITConfig(USART1, USART_IT_TXE, ENABLE)后会立即产生中断请求。因此这造成一个麻烦的问题:如果没有真正的发送数据,TXE中断都会发生,而且没有休止,这将占用很大部分的CPU时间,甚至影响其他程
[单片机]
STM32开发笔记16: 使用静态库加快Keil编译速度
单片机型号:STM32L053R8T6 使用Stm32CubeMx生成的源文件数量比较多,编译的时候会占用很长的时间,我们仔细观察这些文件除了main.c外,其它的文件我们基本上是调用其中的函数,并不需要对其进行改动。所以,可以仿照Freescale MQX的设计方法,分层进行编译,下图是在进行项目设计时候的层次结构。 第0层用于存储Stm32CubeMx生成的工成文件,第2层处理除main.c以外的所有文件,第3层加入应用层的逻辑结构。 第0层的处理方法,大家参考Stm32CubeMx的使用方法,就可以了。 第1层的处理方法,也非常简单,可通过以下步骤完成: 1、在工程目录结构
[单片机]
<font color='red'>STM32</font>开发笔记16: 使用静态库加快<font color='red'>Keil</font>编译速度
STM32的PWM设置4路相差90度的输出信号
void TIM_Encoder_Config(u16 PPS)//设置编码器的4路相差90度的PWM信号 { double temp = 4000; /* Time Base configuration */ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_BDTRInitTypeDef TIM_BDTRInitStructure; temp = temp*72/PPS -1; TIM_TimeBaseStructure.TIM_Period = (u16)temp
[单片机]
keil c51的内部RAM(idata)动态内存管理程序
  程序比较简单,但感觉比较有意思,个人认为有一定应用价值,希望大家有更好的思路和方法,互相促进。   程序的基本思路是:在CPU堆栈指针SP以上的RAM区域,通过把堆栈指针SP上移若干个字节,把空出的RAM区域供用户使用,当用户在使用完后又可以把该RAM区域释放。   头文件dmalloc51.h /* ********************************************************************************************************* * C51内部RAM动态内存申请函数 ,动态内存释放函数 * (c)
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved