09. SD卡启动详解

时间:2024-04-09 20:32:52

1. MMC技术演进

1)NandFlash & NorFlash芯片

这些芯片单纯由Flash颗粒组成,并且只针对存储单元实现了基本的读写接口,需要外部的SoC来提供Flash读写的控制器
缺点:
① 读写接口的时序比较复杂,且不同厂家的Flash接口不一致
② 没有坏块管理机制,需要SoC自己管理Flash坏块

2)MMC卡 & SD卡 & MicroSD卡(TF卡)

A. 代际关系

从技术演进的时间关系上说,上述存储设备的出现时间如下,
MMC --> SD --> MicroSD(TF)

说明1:MicroSD卡就是原先的TF卡,于2004年正式更名
说明2:MMC标准比SD标准早,SD标准兼容MMC标准(即MMC卡可以被SD读卡器读写,而SD卡不可以被MMC读卡器读写)
说明3:MircoSD与SD的只是体积大小的区别,传输原理相同,相当于SD卡的小型化

B. 技术共性

① Flash + Controller
这些卡内部也是Flash存储颗粒,但是比NandFlash芯片增加了Controller,用于进行ECC校验、坏块管理和损耗均衡(Wear leveling)
09. SD卡启动详解

② 统一标准规范
这些卡均遵循各自的标准规范,而不再是各个厂家单独定义。比如SD卡必须遵照SD规范设计。这些规范规定了SD卡的读写速度、读写接口时序、读写命令集、卡尺寸大小、引脚个数及定义。这样不同厂家的SD卡可以通用

3)iNand & MoviNand

iNand & MoviNand相当于SD卡的芯片化,二者均遵循eMMC接口标准,差别在于,
iNand是Sandisk公司根据eMMC标准生产的芯片
MoviNand是三星公司根据eMMC标准生产的芯片

目前很多嵌入式设备(e.g. 手机)不再使用外部扩展卡,而是内置大容量eMMC芯片

注意:在S5PV210中SD卡/MMC卡/eMMC芯片均由SD/MMC controller管理

4)SD协议简介

A. 物理接口与协议

SD卡的物理接口随模式不同而异,具体如下,
09. SD卡启动详解

SPI协议特点(低速、接口时序简单):
① SPI协议是单片机中广泛使用的一种通信协议,并不是为SD卡专门发明的
② 相对于SD协议,SPI速度比较低
③ SD卡支持SPI协议,就是为了支持单片机使用

SD协议特点(高速、接口时序复杂):
① SD协议是原先专门用来和SD卡通信的,目前也可以用SDIO协议与其他芯片通信(比如SDIO WiFi)
② SD协议要求SoC中有SD控制器,运行在高速率下,要求SoC的主频不能太低
③ 在SD模式下,SD卡工作是通过命令(CMD)驱动的

B. 速度等级

09. SD卡启动详解

C. 容量等级

09. SD卡启动详解

2. x210的SD卡启动

1)拨码与启动

A. 拨码开关设置

x210的启动拨码开关支持iNand启动和USB启动,具体电路如下,
09. SD卡启动详解
OM[5]:通过拨码开关选项
OM[4]:0
OM[3]:1
OM[2]:1
OM[1]:0
OM[0]:1

对照S5PV210 iROM手册可知,
当OM[5] == 0时,启动设备为SD/MMC
当OM[5] == 1时,使用UART -> USB的启动方式
此处需要注意2点:
① UART -> USB启动是一套完整流程,先尝试UART启动,当UART启动time out时从USB启动
② 根据拨码开关电路,OM[0]的值为1,这个选项对应了X-TAL(USB)晶振,这点和实际情况不符,此处存疑~~
09. SD卡启动详解

B. 启动channel

① 如果选择从SD/MMC/eMMC启动,默认从channel 0启动。如果从channel 0启动失败,Second boot从channel 2启动
② 需要注意的是,SD/MMC/eMMC的channel 2也是所有启动设备的Second boot设备,即从其他存储设备启动失败时,均会尝试从MMC channel 2启动

09. SD卡启动详解

在x210中,iNand接在MMC channel 0
09. SD卡启动详解

同时设置了2个SD卡槽,分别使用MMC channel 2和channel 3
09. SD卡启动详解

09. SD卡启动详解

因此,如果想从SD卡启动,必须破坏iNand中的Uboot,使其校验不通过,从而进入MMC channel 2的Second boot流程。
破坏方式是进入Linux系统控制台,然后擦除Uboot所在分区的第2个扇区(seek=N即skip N obs-sized blocks at start of output,obs-size默认为512B)
busybox dd if=/dev/zero of=/dev/mmcblk0 bs=512 seek=1 count=1 conv=sync
sync // 此处再执行一次sync命令以保万全

说明:根据S5PV210的启动流程,只要Uboot的前16KB校验失败,启动自然就进入Second boot流程

2)iROM对SD/MMC启动的支持

在之前介绍的iRAM布局中,有2个部分与SD卡启动密切相关,即External Copy Function和Global Variable

09. SD卡启动详解

A. Global Variable

09. SD卡启动详解

当从MMC设备启动时,与该设备相关的信息必须被记录在Global Variable区域

示例:
在x210 Uboot的movi_bl2_copy函数中就会根据0xD0037488(V210_SDMMC_BASE)中的数值判断当前的SD channel,进而从适当的设备中拷贝BL2至内存中
09. SD卡启动详解

验证:
SD卡启动时,打印如下
09. SD卡启动详解
可见SD卡启动确实使用了channel 2

USB启动时,打印如下
09. SD卡启动详解

通过验证可推测,Global Variable中的数值应该是iROM代码写入的,我们的代码可以读取相关数据,并执行相应的分支

B. External Copy Function

09. SD卡启动详解

S5PV210的iROM代码中提供了一组从外部存储设备拷贝数据到内存的函数,iROM在读取BL1时也是使用这些函数
09. SD卡启动详解

在x210的Uboot代码中,也使用iROM提供的拷贝函数实现BL2的拷贝。代码中使用的0xD0037F98对应的就是CopySDMMCtoMem函数
09. SD卡启动详解

CopySDMMCtoMem函数的使用方法如下,
09. SD卡启动详解

需要注意如下3点:
拷贝函数实际在iROM当中,所以使用时需要解一次引用
② CopySDMMCtoMem函数的第一个参数是MMC channel
③ 这些函数均在iROM设定的时钟频率下工作(e.g. 此处在20MHz工作),如果后续需要更高的传输速度,需要在Uboot中实现SD/MMC驱动(e.g. driver/mmc.c)

3)扇区布局

09. SD卡启动详解

如果使用SD卡,需要空出第0号扇区,从第1号扇区使用。根据实际测试,x210应该是将SD卡和iNand均作为SD/MMC设备使用

说明:扇区和块的概念
早期的块设备是软盘硬盘这类磁存储设备,这种设备的存储单元不是以字节为单位,而是以扇区为单位
早期磁盘每个扇区512字节,但是后期磁盘可以支持1/2/4KB的扇区。但是由于之前很多软件(包括操作系统和文件系统)已经默认使用512B,因此后来的硬件虽然物理上支持更大的扇区,但实际上还是兼容512B扇区的操作

4)S5PV210为什么要支持SD卡启动

如果说iROM + iRAM的设置是为了省去NorFlash,那么支持SD卡启动就可以省去Flash烧录器
x210在贴片完成后,iNand中没有内容,拨码至eMMC启动自然会进入SD卡启动流程,此时只要将支持刷机的Uboot和需要烧写的文件放入SD卡,就可以实现量产刷机
关于量产卡的制作可以参考下面的文档,其核心就是SD卡分作2部分使用,
① 从编号1扇区开始烧写uboot.bin,该代码需要支持SD卡升级流程(当然,为适应S5PV210的启动流程,uboot.bin烧写时会分为BL1 & BL2,后文中有叙述)
② 从SD卡的256MB之后构建FAT 32分区,将要烧写的文件放入其中。量产刷机时,uboot就是从该分区获取要烧写的文件并进行刷机

x210v3s开发板SD卡烧写教

程.pdf

1.66MB

3. bootloader分散加载方案

核心:拆分代码,单独编译链接镜像

1)代码拆分

① 代码拆分原因
根据S5PV210的启动流程,BL1最大16KB,也就是说iROM最多从SD卡中读取16KB数据作为BL1运行。但目前Uboot编译出的镜像文件一般在200 ~ 500KB,所以需要将代码拆分编译
09. SD卡启动详解

09. SD卡启动详解

② BL1代码解析
链接地址:0xD0020010(如果BL1中没有地址相关操作,链接地址无妨)
主要工作:
a. 核心初始化(e.g. 关闭看门狗、设置栈等)
b. 初始化内存
c. 将BL2从SD卡拷贝到内存
d. 跳转到内存继续运行

核心代码分析:
09. SD卡启动详解
说明:拷贝完成后,直接跳转到拷贝的内存目的地址运行,因此后续的led3函数不会被调用(此处设置仅为验证)

③ BL2代码解析
链接地址:0x23E00000(其实是经过初始化的内存就可以,此处选择该值只是为了和x210的Uboot相同)
主要工作:此处只是简单跳转到主函数运行
09. SD卡启动详解

注意:此处的BL1 & BL2代码只是为了示意分散加载方案的实现,因此失于简陋,很多需要做的处理并没有做(e.g. BL1和BL2均没有清bss段)

④ 烧写位置说明
09. SD卡启动详解

BL1从编号1扇区开始:
从SD卡的编号1扇区开始使用,是S5PV210芯片的要求

BL2从编号2扇区开始:
BL1从编号1扇区开始,最大16KB,也就是需要32个扇区,所以BL2的起始地址 >= 33即可。此处从45开始,中间空余的扇区可以存放Uboot环境变量等信息

参考代码:

sd_relocat

e.zip

14.19KB

2)串口打印说明

09. SD卡启动详解

破坏iNand中的Uboot后启动会失败,如果不插入SD卡,打印如上方的红框所示
SD checksum Error:iNand启动时,BL1校验失败
SD Init Error:Second boot MMC channel 2 SD卡初始化失败
Uart negotiation Error:Second boot失败后会尝试从UART启动,此处为Uart time out打印
Insert an OTG cable into the connector:UART启动失败后,会尝试从USB启动
09. SD卡启动详解

插入SD卡后启动,如果启动成功,就只会有BL1校验错误的SD checksum Error打印。并且如我们的预期,能实现LED的闪烁

特别注意:此处的串口打印源自UART1,即iROM中使用UART1打印;而我们自己的裸机代码中使用UART0打印

3)分散加载方案的缺陷

① BL1 & BL2完全分离,代码编写和组织比较麻烦(e.g. 两部分代码需要分别编译链接,但相互之间又有联系)
② 不能兼容SD卡和其他启动方式

4. Uboot单镜像烧写方案

核心:一份代码,一个镜像,截取16KB制作BL1

1)实现方法

① 使用一份代码编译出一个uboot.bin镜像
② 从uboot.bin中截取16KB(x210实现中是8KB),并计算其校验值,然后在该部分代码前加头,构成BL1
③ 将BL1烧写到SD卡编号1扇区
④ 将整个uboot.bin烧写到SD卡编号49扇区

说明:启动运行流程
① iROM先运行,由于iNand中的Uboot已被破坏,进入Second boot流程,从MMC channel 2的SD卡启动
② 从SD卡的编号1扇区开始读取16KB(8KB)至iRAM运行,这部分就是BL1
③ BL1需要完成内存初始化,然后从SD卡的第编号49扇区读取整个uboot.bin至Uboot的链接地址
④ 跳转到内存中运行
特别注意:此处不是跳转到内存的Uboot链接地址处运行,而是跳转到内存中接着BL1运行。

说明:一般情况下,BL1和BL2是汇编代码和C代码的分水岭。BL2的起始地址是一个C函数,BL1在完成环境初始化和代码重定位后,就是跳转到BL2的起始C函数开始运行

2)脚本分析

09. SD卡启动详解

① uboot_inand.bin就是编译出的完整Uboot镜像,大小约384KB
② 首先调用mkbl1程序从uboot_inand.bin中读出8KB,并对其校验加头构成BL1
③ 然后将BL1烧写到SD卡编号1扇区
④ 最后将整个uboot_inand.bin烧写到SD卡编号49扇区

3)验证与实现

说明:由于x210提供的一套uboot源代码环境还没有验证过(补充:后续已验证可行,但需要简单修正脚本~~),目前使用mkv210_image.c代码制作BL1

① 添加movi_bl2_copy函数
09. SD卡启动详解
此处我们从编号45扇区开始,拷贝64个扇区的内容至链接地址

② 在start.S中调用movi_bl2_copy实现代码重定位
09. SD卡启动详解

说明1:code_relocate函数用于实现从iRAM到DDR的代码重定位,此处不再调用
说明2:在调用过movi_bl2_copy之后,直接跳转到DDR中运行start_main函数

③ 修改链接器脚本,确保movi.c被链接到前16KB
09. SD卡启动详解
将BL1阶段需要用到的代码链接到最前端

5. 解决x210软开关问题

1)x210软启动电路分析

09. SD卡启动详解

① MP1482芯片的作用:当外部适配器电压在一定范围内变化时,稳压芯片的输出电压都是5V
② MP1482芯片有一个EN(Enable)引脚,这个引脚可以控制芯片是否工作。EN为高电平时有输出电压,EN为低电平时稳压芯片无输出。有2个因素会影响EN引脚的电平,
a. POWER按键,POWER按键按下时EN为高电平;POWER按键弹起时EN为低电平
b. POWER_LOCK引脚,若该引脚为EINT0模式或为POWER_LOCK模式但输出为低电平,EN为低;若该引脚为POWER_LOCK模式,且输出为高,则EN为高电平
③ 图中的EINT1引脚作为中断提供给CPU,用于实现唤醒

说明:x210为什么使用软启动?
一般开发板使用拨码开关做电源开关,虽然使用简单,但是整个开发板要么通电,要么没电,无法实现休眠 / 低功耗等电源模式。使用软启动的电路,比较接近实际产品

2)相关寄存器说明

软开关在设计时有一个置锁电路,用EINT0(GPH0_0)引脚来控制。而EINT0关键可以用作PS_HOLD_CONTROL功能,具体寄存器如下(datasheet P470)
09. SD卡启动详解

PS_HOLD_CONTROL寄存器,共有3个位有用,
bit 0,0表示这个引脚为GPIO功能,1表示这个引脚为PS_HOLD功能
bit 9,0表示这个引脚方向为输入,1表示这个引脚方向为输出
bit 8,0表示这个引脚输出为低电平,1表示输出为高电平

因此,要想将软启动置锁,需要将bit 0、8、9均置为1

3)代码实现

09. SD卡启动详解

09. SD卡启动详解

代码中在关闭看门狗之前将PS_HOLD置锁,可以尽快实现开发板始终通电的目的。需要注意的是,开发板置锁后,POWER按键已经失效,关机时需要按下复位按键