×
嵌入式 > 嵌入式开发 > 详情

引用 ARM开发,对entry point的含义

发布时间:2020-08-19 发布时间:
|

从事了这么久的ARM开发,对entry point的含义一知半解,今日再次拿出一本写得还算不错的ARM教材来翻,书中这一段仅仅是把英文手册单纯翻译成中文,并没有讲到真正的实质。不是ARM公司手册写得不详细,而是多数中文教材的编写采用的方式是: english--华文 mapping,但英文手册是有系列组织的suite,而书本往往翻译自系列中的一篇,容易使得读者管中窥豹。

摘要:ARM link的时候-entry ‘行标号’ 选项用于指定程序的入口地址,其实就是ICE把代码load完之后自动跳入的地址,最后的程序中这个工作是由bootloader来完成的,当然bootloader也可以跳到别的入口地址去。几乎所有的成品ARM芯片都有内置的bootloader,因此开发者看到的程序入口点就是entry point。对于FPGA上的ARM系统调试,ARM复位后跳转到一个固化地址,就需要自己写bootloader代码并通过scatter加载到rom中(我们的EAS片上存储器包括rom在内全部用FPGA的ram实现,tape out的时候bootloader代码会被固化到chip的rom中)

1.entry point在编译中的指定

看了make file,entry point的指定是在link的时候用命令行参数的方式告诉编译器的,

armlink ... -Entry reset_handler

如果采用RVDS或ADS,工程属性中有entry point选项可供设置,但最终还是作为参数传递给armlink。

这样, 在连接ICE并loadimage之后,ICE会通过JTAG把代码映像搬移到内存中,然后把当前PC指针指向reset_handler,但引出了一个问题:在最终的产品中不存在ICE和JTAG,ARM上电复位后跳向固化的复位地址,如0xFFFF0000,那么由谁来让PC指针指向我们指定的entry point呢?答案是:由bootloader代码来完成,进一步引出2个问题:1,谁来生成bootloader?2,怎么把bootloader定位到硬件复位地址?

2. 自己写bootloader并通过scatter文件将之定位到硬件复位地址。

或许某些开发工具会自动的为我们生成bootloader,这里介绍的是自力更生的方法。

首先介绍bootloader,这里仅实现中断向跳转:

AREA Vect, CODE, READONLY ;编译器伪指令,scatter根据这些属性来组织程序映像

ENTRY ;这个entry和本文中的entry point是没有关系的,它表示的是汇编程序代码部分的开始

LDR PC, Reset_Addr

LDR PC, Undefined_Addr

LDR PC, SWI_Addr

LDR PC, Prefetch_Addr

LDR PC, Abort_Addr

NOP ; Reserved vector

LDR PC, IRQ_Addr

LDR PC, FIQ_Addr

Reset_Addr DCD Reset_Handler

Undefined_Addr DCD Undefined_Handler

SWI_Addr DCD SWI_Handler

Prefetch_Addr DCD Prefetch_Handler

Abort_Addr DCD Abort_Handler

IRQ_Addr DCD IRQ_Handler

FIQ_Addr DCD FIQ_Handler

Reset_Handler

LDR PC, =0x00000000;

然后是scatter文件:

ROM_LOAD 0x00000000

{

ROM_EXEC 0x00000000

{

* (InRoot$$Sections); 实现搬移scatter的代码,编译器自动生成

*(+RO) ; 除了bootloader的所有代码段放这里

}

D-TCM 0x00400000 0x003FFFFF

{

* (+RW,+ZI);这里放所有的RW段(char ch=4;)和ZI段(char ch; ch会被初始化零)。

}

}

ROM2 0xFFFF0000

{

BOOTLOAD 0xFFFF0000

{

bootloader.o(+RO) ;bootloader的程序段放这里

}

}

scatter也是在link的时候通过参数‘-scatter 文件名’传递的。

3.总结

在以上条件下,比较使用ICE和最终产品中的启动顺序:当使用ICE调试时,ICE读入映像文件,找到其中的scatter信息,通过JTAG把代码段和数据段放到指定的位置,然后把PC设为-entry所指定的标号,这就是为什么当我们loadimage之后看到的是在entry point中指定的行号所在的源代码。当脱离ICE运行时,ARM上电后跳转到硬件复位地址0xFFF0000 (ROM),我们已事先在那里烧入了我们的bootloader,bootloder从外设中读入加载映像文件(如片外nand,I2C,UART等)并放入scatter的加载域中(0x00000000),然后跳转到0x000000,由于我们已在scatter中将InRoot$$Sections定位在那里,所以它被执行,它负责把映像文件从加载域搬移到执行域中,然后跳转到__main,__main是arm编译器自动生成的,它负责清零ZI段和初始化C库,最后__main跳向C代码的入口main()




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
智能化系统工程设计中的若干技术问题