当前位置:首页 > > 充电吧
[导读]1、问题一个工程包含众多源文件,需要指定一个入口地址,如IAR IDE中默认的入口地址(符号或者标号)"__iar_program_start"(在$TOOLS_DIR$\arm\lib目录下的cst

1、问题

一个工程包含众多源文件,需要指定一个入口地址,如IAR IDE中默认的入口地址(符号或者标号)"__iar_program_start"(在$TOOLS_DIR$armlib目录下的cstart.s文件中定义)。对于一般程序而言,入口地址就是程序首先被执行的指令(函数)。然后,在嵌入式系统中,必须考虑芯片复位时的异常向量表,在异常向量表中的复位异常跳转的地址,也是程序首先执行的地址。那么此时的program entry和复位异常跳转地址的孰是孰非?哪个才是真正的入口执行?

毫无疑问,肯定是复位异常首先被执行,那为什么需要配置"program entry"?

 

2、这得从系统的角度去寻找答案。在main函数运行之前,必须要有硬件初始化、软件初始化,其中软件初始化一般包含全局变量、0初始化变量、堆栈等等,这部分的初始化称为系统初始化,一般由启动代码完成。IAR IDE工具在默认的情况下会根据工程配置,在最终可执行的镜像中加入合适的启动代码。注意这里的【默认情况】是如何实现的:通常而言构建构成包括编译、链接,编译工程源代码得到目标文件,将目标文件和库文件作为输入,送给链接器链接得到可执行文件(镜像)。链接器链接时,解决了外部引用符号的重定位、地址安排等,但是,对于链接器而言,程序从哪里开始执行呢?

1)默认的main?非也,

2)链接器不需要知道程序从哪里开始执行,只需要强制低把启动代码加入,就可以实现从复位异常-》系统初始化-》main完成。但是,这样的链接器动作太过死板,如果用户需要另外的启动方式,则使用此链接器不能达到目标。

故,链接器必须知道程序的入口地址,当链接器得到程序的入口地址之后,才会链接包含入口地址的模块(库文件或者目标文件),并且依据此入口地址构建函数调用栈,在函数调用栈中的每一个函数都需要找到定义的模块,链接器由此得到所有需要链接的模块(库、目标文件),最后才是所有模块的链接形成可执行文件。

因此,“program entry”是为了给链接器指示用的。

 

3、异常向量表的复位异常跳转地址和“program entry”看来没有直接的关系,因为

1)芯片复位后,经复位异常跳转,不一定调到“program entry”处执行;

2)异常向量表需要配合目标系统硬件的启动方式、内存地址等众多因素,其最主要的作用是,芯片复位后调到启动代码处执行,以及发生中断、其他异常时,跳转到相应的处理代码处。

 

4、如果用户自行编写启动代码,只需要将该启动代码添加入工程,重新指定“program entry”则可以完成用户自定义的启动方式,重写了IAR IDE默认提供的cstartup.s启动文件。

 

5、为了验证上述猜想,做一个测试。新建一个简单的main工程,工程只有一个main.c源文件:

int main()
{
  return 0;
}

1)在默认情况下,工程选项配置成“__iar_program_entry”,如下图

编译后,查看生成的map文件:

*******************************************************************************
*** ENTRY LIST
***

Entry                    Address  Size  Type      Object
-----                    -------  ----  ----      ------
?main                 0x00000100        Code  Gb  cmain.o [5]
Abort_Handler         0x0000015c        Code  Wk  vectortrap.o [5]
CSTACK$$Base          0x00100000         --   Gb  - Linker created -
CSTACK$$Limit         0x00102000         --   Gb  - Linker created -
FIQ_Handler           0x0000015c        Code  Wk  vectortrap.o [5]
FIQ_STACK$$Base       0x00102100         --   Gb  - Linker created -
FIQ_STACK$$Limit      0x00102200         --   Gb  - Linker created -
IRQ_Handler           0x0000015c        Code  Wk  vectortrap.o [5]
IRQ_STACK$$Base       0x00102000         --   Gb  - Linker created -
IRQ_STACK$$Limit      0x00102100         --   Gb  - Linker created -
Prefetch_Handler      0x0000015c        Code  Wk  vectortrap.o [5]
Region$$Table$$Base   0x00000000         --   Gb  - Linker created -
Region$$Table$$Limit  0x00000000         --   Gb  - Linker created -
SWI_Handler           0x0000015c        Code  Wk  vectortrap.o [5]
Undefined_Handler     0x0000015c        Code  Wk  vectortrap.o [5]
__cmain               0x00000100        Code  Gb  cmain.o [5]
__exit                0x00000138        Code  Gb  XXexit.o [5]
__iar_init_vfp        0x000000ec        Code  Gb  fpinit.o [4]
__iar_init_vfp_v6     0x000000d8        Code  Gb  fpinit.o [4]
__iar_program_start   0x00000080        Code  Gb  cstartup.o [5]
__low_level_init      0x00000124   0x8  Code  Gb  low_level_init.o [3]
__vector              0x00000000        Data  Gb  cstartup.o [5]
_call_main            0x00000110        Code  Gb  cmain.o [5]
_exit                 0x0000014c        Code  Gb  cexit.o [5]
_main                 0x00000118        Code  Gb  cmain.o [5]
exit                  0x00000134   0x4  Code  Gb  exit.o [3]
main                  0x0000012c   0x8  Code  Gb  main.o [1]

entry栏是函数名称,也是函数的入口地址;object栏是来源的目标文件。可以看到,“__iar_program_start“位于cstartup.o文件中,也就是IAR默认提供的启动文件。从__iar_program_start开始执行,还调用了其他的函数,所以在可执行文件中,还可以看到其他的entry,比如_main,?main,SWI_Handler等等(这些entry都在IAR安装目录下的armsrclibarm目录下的文件中定义)。这些都是因为从"__iar_program_entry"开始执行时的函数调用栈中的函数。

2)更改程序的入口为main,如下图:

 编译后,查看生成的map文件

*******************************************************************************
*** ENTRY LIST
***

Entry                    Address  Size  Type      Object
-----                    -------  ----  ----      ------
Region$$Table$$Base   0x00000000         --   Gb  - Linker created -
Region$$Table$$Limit  0x00000000         --   Gb  - Linker created -
__iar_init_vfp        0x00000094        Code  Gb  fpinit.o [4]
__iar_init_vfp_v6     0x00000080        Code  Gb  fpinit.o [4]
main                  0x000000a8   0x8  Code  Gb  main.o [1]

对比可以发现,在最终可执行文件中,仅包括了main目标文件的main entry。链接器链接时,直接从mian entry开始执行,不再调用其他的函数,故不用链接到IAR系统提供的库,也不用自动加入启动代码。

总结:program entry是为了链接器服务的,它给出了链接器在链接时需要链接的模块,从而为用户提供重写启动代码的方法。

关于异常向量表如何配合目标硬件系统,将在后面的文件补充。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭