注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
黄腾酒的个人空间 https://home.eeworld.com.cn/space-uid-535320.html [收藏] [复制] [分享] [RSS]
日志

LPC1768 学习(一)系统初始化

已有 4901 次阅读2014-7-5 19:50 |个人分类:LPC1768| LPC1768, NXP, arm-m3

年前的时候,曾经自己琢磨过crotex-m3内核的LPC1768,但当时没有细看程序怎么执行。现在用jlink调试一下,能看到程序不是从main主函数开始执行的。最开始执行的是startup_LPC17xx.s文件。
第一句是LDR R0, =SystemInit LDR在ARM指令集中,通常都是做加载指令的 ,但是它也可以作伪指令。
例如:
1.LDR r0,=name 像这种带符号的是伪指令,而不是ARM指令,LDR伪指令用于加载立即数或一个地址值到指定寄存器。
(1)如果name是立即数:LDR R0,=0x123 将0x123存入R0
(2)如果name是个表示符:LDR R0,=NAME 将NAME的地址存入R0
2.LDR R1,[R0如果没有等号,LDR指令用于从内存中读取数据放入寄存器中,该指令是将R0地址处的数据读出,保存到R1中。
所以,LDR R0, =SystemInit就是把SystemInit的地址送给R0,而SystemInit的地址就是系统初始化函数的地址。
第二句是BLX     R0 BLX属于跳转指令集,在ARM中,跳转指令集有四条。如下:
1、B指令
B指令的格式为:
B{条件}目标地址
B指令时最简单的跳转指令。一旦遇到一个B指令,ARM处理器将立即跳转到给定的目标地址,从那里继续执行。需要注意的存储在跳转指令中的实际值是相对当前PC值的一个偏移量,而不是一个绝对地址, 它的值由汇编器来计算(参考寻址方式中的相对寻址)。它是24位有符号数,左移两位后扩展为32位,表示的有效偏移为26位(前后32MB的地址空间)。以下指令:
B Label  程序无条件跳转到标号Label处执行
2、BL指令
BL指令的格式为:
BL{条件}目标地址
BL是另一个跳转指令,但跳转之前,会在寄存器R14中保存PC的当前内容,因此,可以通过将R14的内容重新加载到PC中,来返回到跳转指令之后的那个指令处执行。该指令是实现子程序调用的一个基本单 常用的手段。以下指令:
BL Label 当程序无条件跳转到标号Label处执行时,同时将当前的PC值保存到R14中
3、BX指令
BX指令的格式为:
BX{条件}目标地址
BX指令跳转到指令中所指定的目标地址,目前地址处的指令既可以是ARM指令,也可以是Thumb指令。
4、BLX指令
BLX指令的格式为:
BLX{条件}目标地址
BLX指令从ARM指令集跳转到指令中所指定的目标地址,并将处理器的工作状态由ARM指令集切换到Thumb指令集,该指令同时将PC的当前内容 保存到寄存器R14中。因此,当子程序使用Thumb指令集,而调用者使用ARM指令集时,可以通过BLX指令实现子程序的调用和处理器工作状态 的切换。
综上可以知道
                LDR     R0, =SystemInit
                BLX     R0
就是跳到SystemInit(),所以第一个执行的函数不是main(),而是SystemInit()。
关于SystemInit()是执行什么,我也不想多说,网上这方面的说明很多。可以看看下面这个地址:
http://tangcheng3.blog.163.com/blog/static/54044458201110159586255/

2014年3月23日
补充:
今天,在学习周立功的LPC1700实例的时候,发现原来CM3的启动不是我以上想的那样,也就是说我以前想错了。
通过比较,两个版本的启动文件,最后发现了,这个不同:
@version: V1.01
Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  __main
                LDR     R0, =__main
                BX      R0
                ENDP

@version: V1.02
Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  SystemInit
                IMPORT  __main
                LDR     R0, =SystemInit
                BLX     R0
                LDR     R0, =__main
                BX      R0
                ENDP

可以看到两个版本的启动文件明显不一样,1.01版本的复位之后就跳到主函数了,而1.02版本的先跳到systeminit(),执行完后再跳到主函数。
所以,使用1.01版的启动文件,就需要在主函数里面调用systeminit(),而使用1.02版头文件不需要。
评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章