历史上的今天
返回首页

历史上的今天

今天是:2025年04月18日(星期五)

正在发生

2019年04月18日 | STM32 KEIL里的MAP文件分析

2019-04-18 来源:eefocus

一、文件分析流程


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)

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


推荐阅读

史海拾趣

Compound Photonics公司的发展小趣事

在Micro LED领域,Compound Photonics同样展现出了强大的实力。公司曾与Plessey合作开发Micro LED产品,双方的合作一度被业界看好。然而,就在合作即将取得突破时,Meta公司突然出手收购了Plessey的产能,使得Compound Photonics失去了一个重要的合作伙伴。面对这一突如其来的竞争压力,Compound Photonics不得不重新调整战略,寻找新的合作伙伴。

ELANTEC (Renesas )公司的发展小趣事

Renesas Electronics的前身可以追溯到1958年,当时日立制作所成立了半导体部门。随着技术的不断进步和市场的扩大,该部门逐渐发展壮大,成为日立公司内的一个重要业务部门。进入20世纪90年代,随着半导体市场的竞争加剧,日立公司决定将半导体业务独立出来,以便更加灵活地应对市场变化。1999年,日立半导体部门正式更名为ELANTEC,开始了独立发展的道路。

成都振芯/国腾(CORPRO)公司的发展小趣事

在北斗卫星导航系统的发展过程中,CORPRO始终扮演着重要角色。作为北斗终端的最大供应商之一,CORPRO通过不懈的技术研发和产品迭代,成功实现了北斗设备零部件的国产化。同时,公司还构建了“元器件-终端-系统及运营”的完整产业链,在高性能集成电路板块取得了显著成就。此外,CORPRO还是首批承担“核高基”核心电子器件项目企业中唯一的一家民营企业,体现了其在电子行业的领先地位和创新能力。

Advanced Interconnections Corp公司的发展小趣事

随着市场竞争的加剧,AIC公司意识到品质是赢得客户信赖的关键。于是,公司加大了对生产过程的管控力度,从原材料采购到生产流程,再到产品检验,都实行了严格的质量控制。同时,AIC公司还建立了完善的售后服务体系,及时响应客户需求,解决产品使用过程中出现的问题。这些举措使AIC公司的产品赢得了客户的广泛好评,进一步巩固了市场地位。

Electronicon Kondensatoren GmbH公司的发展小趣事

1992年,ELECTRONICON成立了卷绕电容器部门,并专注于该领域的研发与生产。该部门拥有238名员工,致力于为客户提供高品质的照明、电机和电力电容器产品。随着部门的不断发展壮大,ELECTRONICON在电容器领域的市场份额也得到了进一步提升。

B&K Precision公司的发展小趣事

为了进一步拓展国际市场,B&K Precision在全球范围内设立了多个分公司和办事处。其中,2012年在中国设立的分公司百科中国仪器有限公司是一个重要的战略布局。这一举措不仅加强了公司在亚洲市场的地位,也为各地客户提供了更为迅速和便捷的售后服务保障。同时,通过与国际知名企业的合作与交流,B&K Precision不断吸收先进的技术和管理经验,为公司的持续发展注入了新的动力。

以上五个故事,展现了B&K Precision公司从车库起步到成为全球电子测量领域领导者的发展历程。通过不断创新和拓展业务,公司成功应对了市场变化和挑战,成为了电子行业中的佼佼者。

问答坊 | AI 解惑

某一老师的MPS430的PPt讲稿

某一老师的MPS430的讲稿,刚入门者参考参考…

查看全部问答>

PPP连接的问题

我使用串口进行PPP拨号连接,LCP、PAP都过去了,到了IPCP时,已经可以分配IP地址,进入数据通信打开状态,为什么服务器端还给我发服务器(网关)的IP地址请求包啊?这个包在NCP配置阶段已经发过了,并且我发过ack包过去了。 有哪位仁兄遇见过类似 ...…

查看全部问答>

转让一些板子(已结束)

1.    ok6410 买来2.3个月,具体我也不知道了。装了android系统后当时间看看。没真正开发过。720元。 2.    lm3s8962 申请来的。芯片太贵,放弃学习。248元。加钱换cc2530板子最好,我有无限龙3700元那个套件的光盘 ...…

查看全部问答>

2MFLASH怎么挂在C6416的EMIFA口上啊?AEA[22:3]

2MFLASH怎么挂在C6416的EMIFA口上啊?AEA[22:3] 好象要通过SDRAM把程序读入DSP内存,希望高手详细解答!!…

查看全部问答>

求助

MSP430中I/O管脚与TAx管脚的对应关系? 是所有系列都一样吗? 急~~…

查看全部问答>

研究可以不坐着吗?

这些天腰是越来越疼了,每天除了坐还是坐。 谁有没有办法可以让研究的人站起来用电脑? 尽可能保证打字速度又兼顾鼠标精度。…

查看全部问答>

有没有大神有ccs4的教程可以共享一下,多谢

刚刚开始学习dsp,买的仿真器只支持ccs4,没有教程,很纠结,希望好心人帮助 …

查看全部问答>

dsp移植opencv

小弟最近在搞opencv移植dsp,但对dsp的某些外部数据导入不是太懂,具体如下 const char* cascade_name =\"cars3.xml\"; cascade = (CvHaarClassifierCascade*) cvLoad(cascade_name, 0, 0, 0); 我需要把cascade这个结构体编译进dsp内,请问大家 ...…

查看全部问答>

程序中运算符号

|=和= ^=和~ 各有什么分别呢?用在什么情况下?…

查看全部问答>

【TI首届低功耗设计大赛】带测量功能的蓝牙遥控插座设计

简略的设计,希望能做个参考。 主电路:双向可控硅控制线路的开断。 测量电路:差分放大电路设计,康铜丝检流,电阻分压测量大电压。 辅助电源:阻容分压将220V交流变直流,再转成正负3.3V 主电路连接: …

查看全部问答>