S5P4418裸机编程的实现(替换2ndboot)

参考说明:文中有参考aven_paul博主的S5P4418启动镜像分析一文,具体参考http://blog.csdn.net/aven_paul/article/details/46772285

掰搿实验室博主的“点亮user Led”一文,具体参考http://weibo.com/p/1001603914482173772682

              S5P4418是四核cortex-A9的SOC,这么强大的处理器非操作系统不能充分发挥其性能,但是对于打算深入了解和学习更好的使用它来说,裸机编程更能让你了解从Power on -> internalRom --> boot mode choose --> Loading & Launch bootloader(BL1 --> BL2 )->......的详细过程,更能体现从SOC到board再到program的层层衔接,丝丝相扣的严谨设计。本文由于使用nanoPi2硬件,只能使用SD作为boot源,因此以SD卡为基础描述裸机编程的实现。

             通过S5P4418启动镜像分析我们了解到。SD卡内的镜像是这样的,

Block0 Sd/emmc卡信息

Block1

Nsih.bin
Block2 2ndboot.bin
Block63 Nsih.bin
Block64 u-boot.bin

        并有网友已经以把自己的程序.bin替换u-boot.bin的方式实现出来,见“点亮user Led”http://weibo.com/p/1001603914482173772682,同时文中给出了修改SD卡内绝对位置数据的方法,即使用winhex工具定位到绝对位置并修改。

        根据网友的这些文章,我觉得应该能对裸机编程有个初步的概念,但是同时给我们带来一些疑惑,而且2ndboot不提供源码,对于我们希望刨根问底的人来说,总感觉缺少点东西不能把控,那可不可以把我们的程序直接替换2ndboot.bin来跑裸机呢?想到就马上动手去试,不过还有些前提工作要做。

        1. 找到2ndboot.bin被internalRom搬运到什么地方来Launch?

         2. 如果用替代2ndboot.bin的方法来做的话,我们的bin最大可以做到多大呢?

        带着这些一文,我们还是要去官方手册找答案

        首先,我们要看看系统的memory map

                          S5P4418裸机编程的实现(替换2ndboot)_第1张图片

           看这个map,我们会发现InternalRAM的地址是0xFFFF0000,根据手册我们知道InternalRAM有32KB。好,是不是InternalRom会把2ndboot的内容loading到这个地址来运行呢?为此我们重新编译了“点亮user LED”的例子里的三个文件,只是将链接指令改为arm-linux-ld -Ttext=0xffff0000 start.o main.o -o main了。我们把生成的main.bin用winhex放到SD卡的block2也就是0x400位置,把卡插入nanoPi2的bootSD卡槽,上电,very good ,LED闪烁起来了。

           是不是就完了呢?也许..吧,也许还没有

           既然能动了,我们也希望知道为什么

           好,继续看官方手册第3章 System boot。由于我们使用的是 Internal ROM boot,使用SD卡启动,因此切换到3.4.4节SDHCBOOT。

                       S5P4418裸机编程的实现(替换2ndboot)_第2张图片

      这个表格告诉我们,我们可以使用的是1to32block,我们的点亮LED的程序小于只有1k不到,所以不会超出范围,下面红框圈住的这句话,描述InternalROM将SD卡里的数据从Block1开始load到InternalRAM,我们的main.bin是写入SD卡的block2来替代2ndboot的,按照道理应该是0xFFFF0000+0x200才是我们的main.bin的放置位置,我们将编译器连接修改一下am-linux-ld -Ttext=0xFFFF0200 start.o main.o -o main。完整编译后将main.bin用winhex写入SD卡的0x400处,将卡插入nanoPi2,上电,LED开始闪烁,跟连接地址0xffff0000的效果一样,这是为什么呢?

          带着疑问,我重新查看了start.s,发现内部用到的跳转指令b start 和b main全部是相对位置跳转。同时我继续看官方手册关于Nsih的相关说明。

S5P4418裸机编程的实现(替换2ndboot)_第3张图片

S5P4418裸机编程的实现(替换2ndboot)_第4张图片

原来,block1中存放的Nsih是迁移后的exception vector 。当系统reset后,通过exception vector 看到,其跳转到Reset_Handler处。Reset_Handler指向向的是哪里呢?我们找打了官方的镜像提取出其中Nsih信息后,发现,该地址正是0xFFFF0200。

S5P4418裸机编程的实现(替换2ndboot)_第5张图片

也就是说,系统reset后通过InternalRom的加载,又经过exception vector的跳转,跳到了我们的被InternalROM Load到InternalRAM中的地址中去的main.bin中来运行来了。

         同时也就意味着,如果使用arm-linux-ld -Ttext=0xffff0000 是不妥的,一旦main.bin中出现绝对跳转,程序将跑飞。

总结一下:要将自己的程序替换2ndboot来实现SD卡启动的裸机编程

                       1.  将main.bin写入SD卡的block2即0x400处;

                       2. 如果main.bin小于15KB,则编译时的链接器的-Ttext=0xFFFF0200

                       3.2. 如果main.bin大于15kB(512*(32-1)),则需要先写在0x400处写入一个从main.bin中分离出的包含load其余代码的小于15KB的部分,通过这个15k的代码将main中其余的部分加载到内存,如果main.bin大于InternalRAM,则需要自己写外部DRAM的代码。这部分暂时不在本文中讨论。

参考文档:http://wiki.friendlyarm.com/wiki/images/3/3d/SEC_Users_Manual_S5P4418_Users_Manual_Preliminary_Ver.0.10.pdf

参考程序:

S5P4418裸机编程的实现(替换2ndboot)_第6张图片

S5P4418裸机编程的实现(替换2ndboot)_第7张图片

注:绝对寻址测试

将start.s改为如下代码:


.text
.global _start
_start:
	b st
	.word 0x00000000
	.word 0x00000000
	.word 0x00000000
	.word 0x00000000
	.word 0x00000000
	.word 0x00000000
	.word 0x00000000
st:
	ldr pc, =on_sram
on_sram:
	ldr sp, =0xffff1000
	bl main
halt_loop:
	b halt_loop

使用arm-linux-ld -Ttext=0xFFFF0200  start.o main.o -o main
+ arm-linux-objcopy -I elf32-littlearm -O binary main main.bin

得到的main.bin通过winhex写入SD卡的0x400地址内,将SD卡插入nanoPi2,上电,小灯闪烁起来,由此可以验证替代2ndboot.bin来使用我们的裸机代码时,被搬运到InternalRAM中的地址确实是0xFFFF0200。

你可能感兴趣的:(裸机开发)