Exynos 4412作为32的CPU,可以使用的地址范围可以达到4G. CPU上电后4412内部的控制器会对这4G的地址范围做个映射,如下图:
一部分映射到soc内部的存储器iRom/IRAM(0x0000_0000~0x0206_0000), 一部分映射到DRAM控制器(0x4000_0000~0xA000_0000),通过读写DRAM控制器的地址就可以控制
我们通常所说的DDR内存,还有一部分映射到特殊功能寄存器SFR(Special Function Register)(0x1000_0000~0x1400_0000),特殊功能寄存器可以理解为芯片厂商留给嵌入式开发人员的控制接口,用于控制片内外设,比如GPIO、UART、ADC,IIC等,每个片内外设都有对应的特殊寄存器,通过读写这些寄存器地址就可以控制这些外设硬件。
cpu上电后会首先执行0地址处的代码,从上图可以看出0地址对应IROM, IROM里存放着一小段代码,跟我们自己写的代码没什么不同,只是由芯片厂商事先烧进去,无源码。cpu就首先执行IROM,下图是IROM的执行流程图:
大概就是关闭看门狗,关闭中断及MMU,关闭数据缓存,打开指令缓存,清除TLB,然后将其他核进入IDLE模式,只留CPU0,然后根据OM引脚确定启动设备(SD/nand flash/其他),把Bl1从启动设备读出存入IRAM,然后启动BL1(Boot loader1)。下图是BL1的启动流程:
BL1存放跟特定芯片相关的代码,主要也是设置程序运行环境(初始化中断、设置栈等 );然后从启动设备上把 BL2读入iRAM;最后启动它。BL2就是我们自己写的裸机程序或uboot,是特定平台相关的代码。
我们从BL2开始关注, IROM和BL1都无源码由三星提供,我们只要知道它们是用来加载BL2就可以了。裸机程序和uboot阶段我们都从SD启动,目前只考虑SD启动的情况。
下图是BL1/BL2在SD卡和IRAM中的存储位置:
BL1 位于SD 卡偏移地址512 字节处,iROM 从这个位置读入8K 字节的数据,存在 iRAM 地址 0x02021400位置处。所以 BL1 不能大于 8K。
BL2位于SD卡偏移地址(512+8K)字节处, BL1从这个位置读入14K字节的数据,存在iRAM地址0x02023400处。BL2 不能大于(14K – 4)字节,最后 4 字节用于存放较验码。
如果我们的程序大于(14K – 4)字节,那么需要截取前面(14K – 4)字节用来制作 BL2 并烧入SD卡偏移地址 16K 字节处。当 BL2 启动后,由它来将存放在 SD 卡另外位置的、完整的程序读入内存。
假设我们写了个裸机程序led.c用来点亮led,编译后生成led.bin. 具体怎么写后面讨论,这里只讲解编译后的代码怎么烧到sd卡执行。
从上面的启动流程可以看出需要3部分代码,IROM, BL1, BL2.
IROM已烧好, BL1有三星提供的E4412_N.bl1.bin烧到SD 卡偏移地址512 字节处, BL2就是我们写的led.bin, 用mkbl2工具把led.bin制成bl2.bin烧到SD卡偏移地址(512+8K)字节处。用三星提供的sd_fusing.sh脚本就可以完成这些步骤,脚本如附件,首先ls /dev/sd*查看我们的SD卡设备,一般最后一个“不带数字的”设备节点就是 SD 卡的设备名,执行sudo ./sd_fusing.sh /dev/sdb ../../luoji4412/led/led.bin就可以把BL1,BL2烧到SD卡,然后开关拨到SD卡启动,上电就会按上面的流程执行IROM,BL1,BL2,执行到我们自己写的裸机程序。
sd_fusing工具: http://download.csdn.net/detail/cyj88jyc/9210865