S5PV210中的SD卡启动详解

来源:朱有鹏老师的嵌入式课程笔记

主流的外存设备介绍

内存一般指的是RAM(random access memory,随机访问存储器),外存一般指ROM(read only memory,只读存储器),前者可以访问任意字节,掉电后丢失数据,后者以块为单位进行访问(比如已512字节为一个块,如果要读取第80字节数据,需要将整个512字节都读出来),掉电后数据不丢失。

软盘、硬盘、光盘、CD、光盘

磁存储,读写速度慢,可靠性低。广泛使用在桌面电脑,嵌入式设备几乎没有在用

Flash闪存

Flash存储即闪存计数,是当前存储技术发展的主流,利用电学原理存储1、0,无需磁存储设备的磁头等物理运动。因此读写速度快,寿命长。

纯粹的flash:NandFlash、NorFlash

NandFlash和NorFLash是出现最早的Flash颗粒组成芯片,仅针对存储最基本的功能提供接口,要求SoC来提供Flash读写控制器。

缺点包括:1、读写接口时序比较复杂。2、内部无坏块处理机制,需要SoC自己来管理Flash的坏块;3、各家厂家的Flash接口不一致,甚至同一个厂家的不同型号、系列的Flash接口都不一致,这就造成产品升级时很麻烦。

NorFlash可以总线访问,但是造假昂贵,一般用于bios中,NandFlash一般是块访问,是将来存储发展的方向。

SD卡、MMC卡、MicroSD卡、TF卡

这些卡其实是把纯粹的NandFlash进行了接口封装,使其具有统一、规范的接口。譬如SD卡都是遵照SD规范来发布的。这些规范规定了SD卡的读写速度、读写接口时序、读写命令集、卡大小尺寸、引脚个数及定义。这样做的好处就是不同厂家的SD卡可以通用

iNand、MoviNand、eSSD

这些东西的本质还是NandFlash,内部由Nand的存储颗粒构成,再集成了块设备管理单元,综合了SD卡为代表的各种卡的优势和原始的NandFlash芯片的优势。

优势:1、向SD卡学习,有统一的接口标准(包括引脚定义、物理封装、接口时序)。2、向原始的Nand学习,以芯片的方式来发布而不是以卡的方式;3、内部内置了Flash管理模块,提供了诸如坏块管理等功能,让Nand的管理容易了起来

SSD

内部也是NandFLash,和eSSD的区别就在于,SSD做成硬盘的样子,eSSD做成芯片的样子

SD卡基础知识

概述

SD卡和MMC卡区别:MMC卡的标准比SD卡早,SD卡能兼容MMC卡接口,但是反过来不行。

SD卡和NandFlash、NorFlash的区别:前者有统一的接口规范,后者没有。

SD卡和MicroSD卡区别:原理完全相同,只是大小不一样;SD卡有写保护,后者没有。MicroSD卡就是TF。

SD卡和SRAM/DDR/SROM的区别:后者的存储芯片可以通过总线访问,初始化之后直接由SoC寻址访问,SD卡的访问则需要遵循一定的协议(SPI协议)

SD卡编程接口

在这里插入图片描述

SD卡有9个引脚与外界连接

针脚4位SD模式1位SD模式SPI模式
名称描述名称描述名称描述
1CD/DAT3卡监测/数据位3CD卡监测CS芯片选择
2CMD命令/回复CMD命令/回复DI数据输入
3VSS1VSS1VSS1
4VCC电源VCC电源VCC电源
5CLK时钟CLK时钟CLK时钟
6VSS2VSS2VSS2
7DAT0数据位0DAT数据位DO数据输出
8DAT1数据位1RSV保留RSV保留
9DAT2数据位2RSV保留RSV保留

SPI协议和SD卡协议

SD卡支持SD卡协议和SPI协议。SPI协议是单片机中广泛使用的协议,并不是为SD卡专门设计的,它的速度比SD卡协议慢,之所以支持SPI协议,也是为了兼容单片机。

SD协议开始专门用于SD卡通信,后来也扩展到其他的外设。SD协议对主频有要求。

SD卡的热插拔检测流程

首先使能SD卡插拔中断,然后SD卡插拔后会触发这个中断,在中断处理函数中通过SD卡控制器中的1bit判断SD卡的状态,如果是1表示插入,0表示拔出

在这里插入图片描述

SD卡启动详解

由于SD卡不能和SoC直接打交道,以前只有NorFlash可以作为启动介质,比如BIOS,三星为了卖NandFlash,研究出一种NandFlash启动的技术,简单来说就是,在SoC内部有一块小的SRAM,启动的时候从NandFlash中读取启动程序到SRAM中去执行。

SD卡启动步骤:

  1. 210启动首先执行内部的iROM(也就是BL0),BL0会判断OMpin来决定从哪个设备启动,如果启动设备是SD卡,则BL0会从SD卡读取前16KB,到SRAM中去启动执行(这部分就是BL1)
  2. BL1执行之后剩下的就是软件的事情了,SoC就不用再去操心了。
  3. 如果镜像小于16KB,那么BL1加载执行完毕就结束了,比如裸机部分的代码。如果镜像大于16KB,比如操作系统程序,可以将前16KB作为BL1,剩余部分作为BL2,BL1的工作就是初始化更大空间的DRAM,然后加载BL2到DRAM中去执行,剩下的就是BL2中程序做的事情,比如启动整个操作系统。

从BL0加载之后就可以从SD卡中读取BL1可以看出,BL0中包含了SD卡初始化程序。

在这里插入图片描述

我们在往SD卡烧录BL1的时候,需要跳过SD卡的第一个块区,整个烧录软件屏蔽了这个细节,如果自己烧录,则需要手动跳过,具体命令为:

#!/bin/sh
sudo dd iflag=dsync oflag=dsync if=210.bin of=/dev/sdb seek=1

SD卡编程实战

BL1、BL2编程流程

总体思路,通过BL1初始化DDR,然后从BL2读取程序,并转跳到BL2去执行,BL2实现LED灯的闪烁。需要确定以下问题:1)BL2的代码从SD卡的哪个扇区开始记录,一共多长;2)读取BL2的代码存放在DDR的哪个位置。

1)假设BL2从SD卡的45号扇区开始(BL1 16K,预留1个扇区,理论上33号扇区开始就可以放BL2程序,安全起见中间留一段缓存扇区)。

2)读取BL2的代码存放在DDR 0x23E00000位置(人为确定,地址随意)

BL1的主函数

#define WTCON		0xE2700000

#define SVC_STACK	0xd0037d80

.global _start					// 把_start链接属性改为外部,这样其他文件就可以看见_start了
_start:
	// 第1步:关看门狗(向WTCON的bit5写入0即可)
	ldr r0, =WTCON
	ldr r1, =0x0
	str r1, [r0]
	
	// 第2步:设置SVC栈	为了能够运行c程序
	ldr sp, =SVC_STACK
	
	// 第3步:开/关icache
	mrc p15,0,r0,c1,c0,0;			// 读出cp15的c1到r0中
	//bic r0, r0, #(1<<12)			// bit12 置0  关icache
	orr r0, r0, #(1<<12)			// bit12 置1  开icache
	mcr p15,0,r0,c1,c0,0;

	// 第4步:初始化ddr
	bl sdram_asm_init

	// 第5步:重定位,从SD卡第45扇区开始,复制32个扇区内容到DDR的0x23E00000
	bl copy_bl2_2_ddr
	
	// 汇编最后的这个死循环不能丢
	b .

​ BL2就是LED灯闪烁的代码

从SD卡读取数据的步骤

SoC从SD卡读取数据需要经过SD/MMC控制器,该控制器屏蔽了SD卡访问的细节,并提供了接口函数供SoC调用,如从SD卡读取数据到内存,可以调用宏CopySDMMCtoMem ,其定义了一个地址为0xD0037F98的函数指针,细节为:

#define CopySDMMCtoMem(z,a,b,c,e)(((bool(*)(int, unsigned int, unsigned short, unsigned int*, bool))(*((unsigned
int *)0xD0037F98)))(z,a,b,c,e))
//z: 通道号:0,或者2
//a: 开始扇区号:45
//b: 读取扇区个数:32
//c: 读取后放入内存地址:0x23E00000
//e: with_init:0

那么我们从SD卡读数据到内存,只需调用上述接口函数即可,比如想从SD卡第45扇区开始,复制32个扇区内容到DDR的0x23E00000,然后跳转到23E00000去执行,可以通过如下代码实现:

#define SD_START_BLOCK	45
#define SD_BLOCK_CNT	32
#define DDR_START_ADDR	0x23E00000
typedef unsigned int bool;
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中,这边强制类型转换是为了编译器能对函数的传参进行校验,否则直接使用CopySDMMCtoMem无法享受编译器的校验
	pCopySDMMC2Mem p1 = (pCopySDMMC2Mem)0xD0037F98;
	
	p1(2, SD_START_BLOCK, SD_BLOCK_CNT, (unsigned int *)DDR_START_ADDR, 0);// 读取SD卡到DDR中
	// 第二步,跳转到DDR中的BL2去执行
	pBL2Type p2 = (pBL2Type)DDR_START_ADDR;
	p2();
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值