《朱老师物联网大讲堂》学习笔记
学习地址:www.zhulaoshi.org
重定位引入和链接脚本
位置无关编码
位置有关编码
我们在设计程序的时候会给程序指定一个运行地址,
比如0xD0020010
这里是通过链接器中指定来设置的,它的另一个说法也叫链接地址,
链接地址可以通过上面的-Ttext或者链接脚本来指定。
程序的运行地址和我们的设置有关,即PIC
位置无关代码和指定的运行地址有关。
链接地址:我们认为会运行的地址
运行地址:程序实际运行的地址
在现实中,大部分都是位置有关代码
对于位置有关代码而言,
最终执行的运行地址和编译链接时侯给定的链接地址必须相同,
否则一定出错。
arm-linux-ld -Ttext 0x0 -o led.elf $^arm-linux-ld -Ttext 0x0 -o led.elf $^
在这句命令中,我们用-Ttext 0x0来指定链接地址是0x0,
而我们用dnw下载指定的地址是0xD0020010,
这里面该作何解释呢?
这是因为s5pv210在内部做了映射,把SRAM映射到了我们这里的0x0地址
在memory map中IROM&IRAM里面0x00000000和0xD0000000就是映射
我们目前涉及的代码都还是位置无关代码,所以其实还不存在这个问题
再来看看启动过程
三星推荐的启动方式中:bootloader必须小于96KB并大于16KB,假定bootloader为80KB,启动过程是这样子:先开机上电后BL0运行,BL0会加载外部启动设备中的bootloader的前16KB(BL1)到SRAM中去运行,BL1运行时会加载BL2(bootloader中80-16=64KB)到SRAM中(从SRAM的16KB处开始用)去运行;BL2运行时会初始化DDR并且将OS搬运到DDR去执行OS,启动完成。ps:为什么不直接加载完,还分2次,目前只能先解释为,不知道bootloader是多大,所以分2次,也可能有一些其它的细节原因。
uboot实际使用的方式:uboot大小随意,假定为200KB。启动过程是这样子:先开机上电后BL0运行,BL0会加载外部启动设备中的uboot的前16KB(BL1)到SRAM中去运行,BL1运行时会初始化DDR,然后将整个uboot搬运到DDR中,然后用一句长跳转(从SRAM跳转到DDR)指令从SRAM中直接跳转到DDR中继续执行uboot直到uboot完全启动。uboot启动后在uboot命令行中去启动OS。ps:这里,是从DDR中uboot的16KB之后开始执行,
uboot的这种方式,更加灵活不用那么麻烦,但是你从存储空间大小上就可以看出来,它做了很多可以不用做的事情,所以有些厂商会针对自己的板子自己写bootloader,大小很小,也很稳定。
在此引出冲定位的意义,链接地址和实际运行地址,没办法完全一致,又因为位置有关码的存在,所以需要我们重定位,
还有一种解决上述加载的方法,是分散加载,分别指定BL1和uboot的链接地址,这种方式,也可以理解为一种手工重定位,重定位是以代码的方式来实现的重定位,