IAR IDE学习之---关于工程设置中“program entry”作用的猜想

1、问题

一个工程包含众多源文件,需要指定一个入口地址,如IAR IDE中默认的入口地址(符号或者标号)"__iar_program_start"(在$TOOLS_DIR$\arm\lib目录下的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安装目录下的arm\src\lib\arm目录下的文件中定义)。这些都是因为从"__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是为了链接器服务的,它给出了链接器在链接时需要链接的模块,从而为用户提供重写启动代码的方法。

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

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值