s5pv210 -uboot(三)SD卡启动流程分析

https://blog.csdn.net/wangweijundeqq/article/details/78886155 --------------------- 本文来自 MrT_WANG 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/wangweijundeqq/article/details/78886155?utm_source=copy

一.主流的外存设备发展及介绍

2017/12/12 23:08

**

1.首先,清楚内存和外存的区别:

**

一般是把这种RAM(random access memory,随机访问存储器,特点是任意字节读写,掉电丢失)叫内存, 
把ROM(read only memory,只读存储器,类似于Flash SD卡之类的,用来存储东西,掉电不丢失,不能随机地址访问,只能以块为单位来访问)叫外存

2.存储设备按发展趋势分类:

● 磁存储设备:软盘、硬盘、光盘、CD、磁带 
● Flash:NandFlash、NorFlash 
缺点:时序复杂,无坏块处理机制,接口不统一 
NandFlash:MLC(可靠性差,容量大)、SLC(可靠性高、容量小) 
现在基本都在发展MLC技术 
● 扩展卡式Flash:SD卡、MMC卡、MicroSD(TF卡) 
内部为NnadFlash存储颗粒,外部封装了接口,接口标准统一、通用。 
缺点:频繁使用导致卡槽接触不可靠 
● iNand、MoviNand、eSSD: 
内部为NandFlash芯片,集成块设备存储单元,集成了扩展卡式Flash 的优点 
接口标准统一(时序、物理封装、引脚定义),以芯片级封装发布 
芯片内部具有Flash管理模块:具有能坏块管理等功能 
● SSD:固态硬盘 
内部为NandFlash芯片,外部封装为硬盘接口 
**

3.SD卡简介

** 
SD卡是具有大容量、高性能、安全等多种特点的多功能存储卡,它比MMC卡多了一个进行数据著作权保护的暗号认证功能(SDMI规格),读写速度比MMC卡要快4倍,达2M/秒。 
SD插槽支持MMC卡。 
SD卡和Nand、Nor等Flash芯片差异 
(1)SD卡/MMC卡等卡类有统一的接口标准,而Nand芯片没有统一的标准(各家产品会有差异)

二. SD卡编程接口

**

1.SD卡3种模式的引脚定义

** 
这里写图片描述 
SD卡的引脚接口支持两种通信协议:SD协议和SPI协议。 
SPI协议是单片机中广泛使用的一种通信协议,接口时序简单,是一种低速通信协议。 
SD通信协议是一个统一标准的通信协议。SoC通过SD卡的九针引脚以SD/SPI协议向SD卡管理模块发送命令、时钟、数据等信息,需要按照时序处理操作SD卡。 
**

2.S5PV210的SD/MMC控制器

** 
(1)SD协议要求SoC中有SD控制器,数据手册Section8.7,为SD/MMC控制器介绍。 
(2)SD卡内部除了存储单元Flash外,还有SD卡管理模块,我们SoC和SD卡通信时,通过9针引脚以SD协议/SPI协议向SD卡管理模块发送命令、时钟、数据等信息,然后从SD卡返回信息给SoC来交互。工作时每一个任务(譬如初始化SD卡、譬如读一个块、譬如写、譬如擦除····)都需要一定的时序来完成(所谓时序就是先向SD卡发送xx命令,SD卡回xx消息,然后再向SD卡发送xx命令····)

三.SD卡启动流程1

**

1.S5PV210的启动过程回顾

** 
(1)210启动首先执行内部的iROM(也就是BL0),BL0会判断OMpin来决定从哪个设备启动,如果启动设备是SD卡,则BL0会从SD卡读取前16KB(不一定是16,反正16是工作的)到SRAM中去启动执行(这部分就是BL1,这就是steppingstone技术) 
(2)BL1执行之后剩下的就是软件的事情了,SoC就不用再去操心了 
**

2.SD卡启动流程(bin文件小于16KB时和大于16KB时)

** 
(1)启动的第一种情况是整个镜像大小小于16KB。这时候相当于我的整个镜像作为BL1被steppingstone直接硬件加载执行了而已。 
(2)启动的第二种情况就是整个镜像大小大于16KB。(只要大于16KB,哪怕是17KB,或者是700MB都是一样的)这时候就要把整个镜像分为2部分:第一部分16KB大小,第二部分是剩下的大小。然后第一部分作为BL1启动,负责去初始化DRAM并且将第二部分加载到DRAM中去执行(uboot就是这样做的)。 
**

3.最重要的但是却隐含未讲的东西

** 
(1)问题:iROM究竟是怎样读取SD卡/NandFlash的? 
(2)三星在iROM中事先内置了一些代码去初始化外部SD卡/NandFlash,并且内置了读取各种SD卡/NandFlash的代码在iROM中。BL0执行时就是通过调用这些device copy function来读取外部SD卡/NandFlash中的BL1的。 
**

4.S5PV210读取Flash设备数据的方式

** 
三星系列SoC支持SD卡/NandFlash启动,主要是依靠SteppingStone技术,具体能支持steppingstone技术的是内部的iROM代码。 
S5PV210内部iROM内部固化了多个设备拷贝函数,这些函数支持从SD/MMC、eMMC、OneNand、eSSD设备拷贝数据到SDRAM中。

设备拷贝函数说明如下: 
● NF8_ReadPage_Adv(0xD0037F90):2K、4K,8bit总线 
● NF16_ReadPage_Adv(0xD0037F94):2K,5 cycle ,16位总线 
● CopySDMMCtoMem(0xD0037F98):从SD/MMC设备拷贝到SDRAM 
● CopyMMC4_3toMem(0xD0037F9C):从eMMC设备拷贝到SDRAM 
● CopyOND_ReadMultiPages(0xD0037FA0):从OneNand设备拷贝到SDRAM 
● CopyOND_ReadMultiPages_Adv(0xD0037FA4):从OneNand设备拷贝到SDRAM 
● Copy_eSSDtoMem(0xD0037FA8): 从eSSD设备拷贝SDRAM(CPUPIO模式) 
● Copy_eSSDtoMem_Adv(0xD0037FAC):从eSSD拷贝SDRAM(UDMA) 
● NF8_ReadPage_Adv128p(0xD0037FB0):每块128页,每页2K的Nand

**

四.S5PV210读取SD卡数据的方式

**

1.CopySDMMCtoMem函数解读:

这里写图片描述

#define CopySDMMCtoMem(z,a,b,c,e) (((bool(*)(int, unsigned int, unsigned short, unsigned int*, bool))(*((unsigned int *)0xD0037F98)))(z,a,b,c,e))
  • 1

● 参数1:SD卡通道,0或者2通道,我们板子SD卡通道为2 
● 参数2:块起始地址(块地址) 
● 参数3:拷贝块的数量 
● 参数4:数据拷贝到什么地址 
● 参数5:返回状态

思考:为什么读取SD卡时以块为单位?

这就涉及到扇区和块的概念,一个扇区有好多个字节(一般是512个字节),一个扇区可以看成是一个块block(块的概念就是:不是一个字节,是多个字节组成一个共同的操作单元块),所以就把这一类的设备称为块设备。常见的块设备有:磁存储设备硬盘、软盘、DVD和Flash设备(U盘、SSD、SD卡、NandFlash、Norflash、eMMC、iNand)。 
磁盘和Flash以块为单位来读写,就决定了我们启动时只能以整块为单位来读取SD卡

**

2.使用函数指针调用设备拷贝函数

** 
第一种方法:宏定义方式来调用。好处是简单方便,坏处是编译器不能帮我们做参数的静态类型检查。

#define CopySDMMCtoMem(z,a,b,c,e)(((bool(*)(int, unsigned int, unsigned short, unsigned int*, bool))(*((unsigned int *)0xD0037F98)))(z,a,b,c,e))
  • 1

第二种方法:用函数指针方式来调用。

typedef unsigned int bool;
typedef bool(*pCopySDMMC2Mem) (int, unsigned int, unsigned short, unsigned int *, bool);
// 实际使用时
pCopySDMMC2Mem p1 = (pCopySDMMC2Mem)0xD0037F98;
p1(x, x, x, x, x);  // 第一种调用方法,编译器默认就是一个函数指针
(*p1)(x, x, x, x, x);   // 第二种调用方法,和上面一样,
*p1(x, x, x, x, x); // 错误,因为p1先和()结合,而不是先和*结合。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

五、SD卡启动模式编程

S5PV210启动过程:开发板上电后,BL0执行时会从启动设备加载BL1到iRAM中执行,BL1执行时会初始化SDRAM,将BL2从启动设备拷贝到DDR,然后从BL1远跳转到BL2执行。 
总体思路:将我们的代码分为2部分:第一部分BL1小于等于16KB,第二部分为任意大小,iROM代码执行完成后从SD卡启动会自动读取BL1到SRAM中执行;BL1执行时负责初始化DDR,然后手动将BL2从SD卡copy到DDR中正确位置,然后BL1远跳转到BL2中执行BL2。 
**

BL1阶段工作

** 
● 关看门狗 
● 设置栈 
● 开iCache 
● **初始化DDR 
● 从SD卡拷贝BL2到DDR 
● 远跳转执行BL2** 
这里写图片描述
说明:如图,S5PV210规定BL1从block1开始,BL1长度为16KB内,我们就定为16KB(也就是32个block),即BL1从block1-block32, 
**

BL2阶段工作:

** 
● 跳转到BL2执行时,点亮LED灯。 
BL2理论上可以从33扇区开始,但我们为了安全会用一些空扇区作为隔离区,故可以从45扇区开始,定义BL2长度为16KB,也就是32扇区 
BL2从block45-block76。BL1的运行地址和链接地址为0xD0020010。 
说明:BL2的运行地址为DDR中的地址,因此链接地址需要设定为DDR的地址。 
我们选0x23E00000(因为我们BL1中只初始化了DDR1,地址空间范围是0x20000000~0x2FFFFFFF)

六.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卡启动细节

** 
(1)uboot编译好之后有200多KB,超出了16KB。uboot的组织方式就是前面16KB为BL1,剩下的部分为BL2. 
(2)uboot在烧录到SD卡的时候,先截取uboot.bin的前16KB(实际脚本截取的是8KB)烧录到SD卡的block1~bolck32;然后将整个uboot烧录到SD卡的某个扇区中(譬如49扇区) 
(3)实际uboot从SD卡启动时是这样的:iROM先执行,根据OMpin判断出启动设备是SD卡,然后从S卡的block1开始读取16KB(8KB)到SRAM中执行BL1,BL1执行时负责初始化DDR,并且从SD卡的49扇区开始复制整个uboot到DDR中指定位置(0x23E00000)去备用;然后BL1继续执行直到ldr pc, =main时BL1跳转到DDR上的BL2中接着执行uboot的第二阶段。

总结:uboot中的这种启动方式比上节讲的分散加载的好处在于:能够兼容各种启动方式。 
代码分析:E:\Linux\13.sd_relocate

在linux下使用dd命令烧录程序,插上SD卡,开发板正常运行看到LED闪烁。 
这里写图片描述

七.遇到的问题:

**

插上分别使用九鼎1烧录好的SD卡和在linux下使用dd命令刷写uboot,启动都没有反应?

**

最终问题是SD卡没有启动起 
采用的方法是从新刷机,板子刷入安卓系统,由于SD卡无法启动,故采用USB—dnw刷机方式: 
刷机分2步:第一步刷x210_usb.bin,地址是0xd0020010;第二步刷uboot.bin,刷机地址是0x23e00000,uboot启动起来后,先fdisk -c 0去重新分区,然后再fastboot….再按照刷机过程刷入系统。 
然后重启,等待系统开机完毕 
然后破坏开发板iNand中的bootloader以从SD2启动(参考 二.ARM裸机刷系统(SD卡uboot+串口+usb otg刷机方式)),即解决了这个问题。 

猜你喜欢

转载自blog.csdn.net/coolperl/article/details/82687243