S5PV210 SD卡启动分析

S5PV210 SD卡启动分析:
1.SD卡启动的难点?
CPU不能直接和SD通过总线式访问(IO方式),而是要通过时序。
2.S5PV210是如何做的?
210首先启动内部的BL0,BL0会根据OMPIN来判断启动设备,如果启动设备是SD卡,则BL0会从SD卡读取前16KB(不一定是16,反正16是工作的)到SRAM中去启动执行(这部分就是BL1,这就是steppingstone技术)
3.SD卡启动流程的问题?
bin文件小于16KB,这个时候相当于整个bin文件都是被当做BL1加载到SRAM中去运行的。
bin文件大于16KB,这个时候整个bin文件就要分散加载,也就是镜像要分成两部分,第一部分大小是16KB,第二部分任意大小,然后第一部分作为BL1启动,负责去初始化DRAM,并将第二部分加载到DRAM中去运行。
4.IROM中如何去读取的SD/NANDFLASH的?
samsung内置了一些代码去初始化外部的SD/NandFlash,并留了各种SD/NandFlash的代码在IROM中,BL0执行的时候就是通过这些device copy function来读取的外部的SD/NandFlash里面的BL1的。
5.扇区和块的概念
早期的块设备就是软盘硬盘这类磁存储设备,这种设备的存储单元不是以字节为单位,而是以扇区为单位。磁存储设备读写的最小单元就是扇区,不能只读取或写部分扇区。这个限制是磁存储设备本身物理方面的原因造成的,也成为了我们编程时必须遵守的规律。
一个扇区有好多个字节(一般是512个字节)。早期的磁盘扇区是512字节,实际上后来的磁盘扇区可以做的比较大(譬如1024字节,譬如2048字节,譬如4096字节),但是因为原来最早是512字节,很多的软件(包括操作系统和文件系统)已经默认了512这个数字,因此后来的硬件虽然物理上可能支持更大的扇区,但是实际上一般还是兼容512字节扇区这种操作方法。
一个扇区可以看成是一个块block(块的概念就是:不是一个字节,是多个字节组成一个共同的操作单元块),所以就把这一类的设备称为块设备。常见的块设备有:磁存储设备硬盘、软盘、DVD和Flash设备(U盘、SSD、SD卡、NandFlash、Norflash、eMMC、iNand)
linux里有个mtd驱动,就是用来管理这类块设备的
磁盘和Flash以块为单位来读写,就决定了我们启动时device copy function只能以整块为单位来读取SD卡
6.做一个分散加载的实验
大于16KB的bin文件使用SD卡启动?
将我们的代码分为2部分:第一部分BL1小于等于16KB,第二部分为任意大小,iROM代码执行完成后从SD卡启动会自动读取BL1到SRAM中执行;BL1执行时负责初始化DDR,然后手动将BL2从SD卡copy到DDR中正确位置,然后BL1远跳转到BL2中执行BL2
细节1:程序怎么安排?程序整个分为2个文件夹BL1和BL2,各自管理各自的项目
细节2:BL1中要完成:关看门狗、设置栈、开iCache、初始化DDR、从SD卡复制BL2到DDR中特定位置,跳转执行BL2
细节3:BL1在SD卡中必须从Block1开始(Block0不能用,这个是三星官方规定的),长度为16KB内,我们就定为16KB(也就是32个block);BL1理论上可以从33扇区开始,但是实际上为了安全都会留一些空扇区作为隔离,譬如可以从45扇区开始,长度由自己定(实际根据自己的BL2大小来分配长度,我们实验时BL2非常小,因此我们定义BL2长度为16KB,也就是32扇区)。
33是怎么算的? 16KB = 16000Byte / 512Byte = 31.25 取32,所以BL1大小取32个扇区,所以理论上BL2可以从33扇区开始放。
(5)细节4:DDR初始化好之后,整个DDR都可以使用了,这时在其中选择一段长度足够BL2的DDR空间即可。我们选0x23E00000(因为我们BL1中只初始化了DDR1,地址空间范围是0x20000000~0x2FFFFFFF)。
在这里插入图片描述
下面我们看copy和跳转的代码:
函数指针的使用: p(1,2,3,4,5);
typedef unsigned int bool;

// 通道号:0,或者2
// 开始扇区号:45
// 读取扇区个数:32
// 读取后放入内存地址:0x23E00000
// with_init:0
typedef bool(pCopySDMMC2Mem)(int, unsigned int, unsigned short, unsigned int, bool);

typedef void (*pBL2Type)(void);

函数功能:
// 从SD卡第45扇区开始,复制32个扇区内容到DDR的0x23E00000,然后跳转到23E00000去执行

void copy_bl2_2_ddr(void)

{
// 第一步,读取SD卡扇区到DDR中

pCopySDMMC2Mem p1 = (pCopySDMMC2Mem)0xD0037F98);

p1(2, SD_START_BLOCK, SD_BLOCK_CNT, (unsigned int *)DDR_START_ADDR, 0);		// 读取SD卡中的BL2到DDR中
// 第二步,跳转到DDR中的BL2去执行
pBL2Type p2 = (pBL2Type)DDR_START_ADDR;
p2();

}
实际:pCopySDMMC2Mem p1 = (pCopySDMMC2Mem)0xD0037F98);这句是错误的,应该写成:pCopySDMMC2Mem p1 = (pCopySDMMC2Mem)(*(unsigned int )0xD0037F98);
因为:samsung是把pCopySDMMC2Mem这个函数的指针放在0xD0037F98这个位置的,实际上使用的时候就要(
(unsigned int *)0xD0037F98)先取出里面的数据,里面的数据就是指向pCopySDMMC2Mem这个函数的指针。

代码分成两部分启动的缺陷:
代码分为2部分,这种技术叫分散加载。这种分散加载的方法可以解决问题,但是比较麻烦。代码完全分2部分,完全独立,代码编写和组织上麻烦,第二,无法让工程项目兼容SD卡启动和NorFlash启动等各种启动方式。SD卡启动程序是两部分的,而NorFlash启动程序是一个整体的,
uboot中的做法:
第二种思路:程序代码仍然包括BL1和BL2两部分,但是组织形式上不分为2部分而是作为一个整体来组织。它的实现方式是:iROM启动然后从SD卡的扇区1开始读取16KB的BL1然后去执行BL1,BL1负责初始化DDR,然后从SD卡中读取整个程序(BL1+BL2)到DDR中,然后从DDR中执行(利用ldr pc, =main这种方式以远跳转从SRAM中运行的BL1跳转到DDR中运行的BL2)。
总结:
实际uboot从SD卡启动时是这样的:iROM先执行,根据OMpin判断出启动设备是SD卡,然后从SD卡的block1开始读取16KB(8KB)到SRAM中执行BL1,BL1执行时负责初始化DDR,并且从SD卡的49扇区开始复制整个uboot到DDR中指定位置(0x23E00000)去备用;然后BL1继续执行直到ldr pc, =main时BL1跳转到DDR上的BL2中接着执行uboot的第二阶段
总结:uboot中的这种启动方式比上节讲的分散加载的好处在于:能够兼容各种启动方式。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值