【笔记】ARM裸机程序开发_part4

10 SD卡详解

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

1.10.1.1、软盘、硬盘、光盘、CD、磁带
(1)存储原理大部分为磁存储,缺点是读写速度、可靠性等。优点是技术成熟、价格便宜。广泛使用在桌面电脑中,在嵌入式设备中几乎无使用。
(2)现代存储的发展方向是Flash存储,闪存技术是利用电学原理来存储1和0,从而制成存储设备。所以闪存设备没有物理运动(硬盘中的磁头),所以读写速度可以很快,且无物理损耗。
1.10.1.2、纯粹的Flash:NandFlash、NorFlash
(1)这些是最早出现的、最原始的Flash颗粒组成芯片。也就是说NandFlash、NorFlash芯片中只是对存储单元做了最基本的读写接口,然后要求外部的SoC来提供Flash读写的控制器以和Flash进行读写时序。
(2)缺陷:1、读写接口时序比较复杂。2、内部无坏块处理机制,需要SoC自己来管理Flash的坏块;3、各家厂家的Flash接口不一致,甚至同一个厂家的不同型号、系列的Flash接口都不一致,这就造成产品升级时很麻烦。
(3)NandFlash分MLC和SLC两种。SLC技术比较早,可靠性高,缺点是容量做不大(或者说容量大了太贵,一般SLC Nand都是512MB以下);MLC技术比较新,不成熟,可靠性差,优点是容量可以做很大很便宜,现在基本都在发展MLC技术。

1.10.1.3、SD卡、MMC卡、MicroSD、TF卡
(1)这些卡其实内部就是Flash存储颗粒,比直接的Nand芯片多了统一的外部封装和接口。
(2)卡都有统一的标准,譬如SD卡都是遵照SD规范来发布的。这些规范规定了SD卡的读写速度、读写接口时序、读写命令集、卡大小尺寸、引脚个数及定义。这样做的好处就是不同厂家的SD卡可以通用。

1.10.1.4、iNand、MoviNand、eSSD
(1)电子产品如手机、相机等,前些年趋势是用SD卡/TF卡等扩展存储容量;但是近年来的趋势是直接内置大容量Flash芯片而不是外部扩展卡。
(2)外部扩展卡时间长了卡槽可能会接触不良导致不可靠。
(3)现在主流的发展方向是使用iNand、MoviNand、eSSD(还有别的一些名字)来做电子产品的存储芯片。这些东西的本质还是NandFlash,内部由Nand的存储颗粒构成,再集成了块设备管理单元,综合了SD卡为代表的各种卡的优势和原始的NandFlash芯片的优势。
(4)优势:
1、向SD卡学习,有统一的接口标准(包括引脚定义、物理封装、接口时序)。
2、向原始的Nand学习,以芯片的方式来发布而不是以卡的方式;
3、内部内置了Flash管理模块,提供了诸如坏块管理等功能,让Nand的管理容易了起来。

10.2 SD卡的特点和背景知识
SD卡和MMC
SD卡是后来的,兼容MMC。Nand芯片无统一的标准接口
SD卡和TF卡
SD卡就是TF卡,两者一样
但习惯上,SD用于数码相机等…,TF卡广泛应用于手机、GPS等
习惯上认为TF卡小,SD卡大。TF卡可以放进卡套成为SD卡

SD卡大哥认SanDisk!=v=


10.3 SD卡的编程接口

SD卡9个引脚连接外接
6个信号线
4DAT
1CLK //SD卡的通信需要时钟,由SOC提供。
1CMD //管理使用命令发送至管理模块
2个GND
1个电源

SD卡与SRAM/DDR/SROM的不同
SRAM等,以总线方式访问,初始化之后直接[用地址访问]
SD卡需要时序和接口协议

SD支持两种协议:SD协议和SPI协议

SPI协议:
SPI是单片机中广泛使用的一种通信协议,并不是专门为SD卡使用的
SD卡兼容SPI,是可以允许单片机通过SPI操作SD卡
SPI相对SD协议是速度比较低的

SD协议:专门用来和SD卡通信。
SDIO的运行,要求SoC有SD控制器,而且SoC主频不能太低
不过话说回来有些wifi芯片也是使用SDIO的呢。。。

SD的热插拔,发现与找到:
开机,ENABLE INT OF CARD DETECT
插入 / 拔出 卡槽后
SOC发了一个信号,发生一个检测中断,即可知道卡来了或者卡走了

现在一般不用单片机驱动SD卡,连stm32都有库。linux、Uboot连驱动都准备好了完全不用动手。


10.4 SD卡启动过程详解【非常重要,是将来uboot用到的】

SoC为何要支持SD卡启动
一个普遍性的原则:SoC支持的启动方式越多,可选择性越大,适用性就越广
可以不借用专用烧录工具的情况下进行SD卡刷机。
注意;这里不是说fusing tools,而是指Jlink等烧录工具。对于普通用户来说不用JLink什么的真是太好了。比如安卓手机有两种刷机方式,
一种称为“线刷”,类似DNW刷机方式
一种称为“卡刷”,类似SD卡刷机方式

总之:方便量产,方便过程,方便用户

九鼎的板子出厂前做了什么?
我们的板子出厂时候要先将量产卡插入SD卡槽,然后iNand启动,iNand里面什么都没有于是2nd启动,即SD卡启动。启动后执行刷机操作对iNand进行刷机,完成后自动重启。此时iNand有了image,可以启动了。刷机完成拔掉SD卡,烧机近48小时,再测试测试玩一下,无死机即可装箱发货。

SD卡启动的难点在哪里?
CPU可以直接访问SRAM、DDR、NorFlash。因为总线式访问。
但是SD卡不能够,人家SD依赖时序的,cpu是不能直接和SD卡打交道的。
啊忘了一点,SD卡内部介质就是NandFlash。

NorFlash:台式机笔记本内的BIOS,这个bios类似uboot
NandFlash:

三星在2440中使用了SteppingStone的技术,让NandFlash也可以作为启动介质。
这个steppingstone翻译为“启动基石”,在SoC内部内置4kb的SRAM,读取 Nand开头的4KB。
但是不能在Nand中启动,最后要在SRAM以内启动
进一步发展:6410得到完善,210芯片时已经完全成熟。

210中 读取iROM(BL0),基本初始化
判断启动方式
若启动方式是SD卡:
BL0读取SD卡前的16KB,引导BL1。

读取启动代码到96KB的SRAM,初始化DRAM,加载系统。

SD卡启动的bin文件大小16KB问题
第一种情况:镜像大小 <16kb
相当于整个镜像作为BL1,直接加载
第二种情况:镜像大小 >16kb
第一部分16KB作为BL1,初始化DRAM
第二部分是剩下的,加载到DRAM中执行。uboot就是这样做的

【最重要的:却隐含没有讲的】
问题:IROM究竟是怎样读取SD卡/NandFlash的?
三星在iROM中内置了一些代码去初始化nand等外设。BL0执行时是调用device copy function来读取外部的SD卡或者NandFlash中的BL1。
iROM中的一点代码就好比新车出厂时带的一点油。
这个代码回头我们还可以用。


10.5 SD启动详解2

IROM_appli全局变量有3个
globalBlockSize 大小
globalSDHCInfoBit 型号
V210_SDMMC_BASE 当前启动channel

SDHC SDhigh capacity 高容量SD卡,属于SD卡的扩展版本。
SD最大2GB
SDHC最大支持32GB
SDXC最大支持2TB

device copy function
CopySDMMCtoMem 里面是一个函数指针

/**
* This Function copy MMC(MoviNAND/iNand) Card Data to memory.
* Always use EPLL source clock.
* This function works at 20Mhz.
* @param u32 StartBlkAddress : Source card(MoviNAND/iNand MMC)) Address.(It must block address.)
* @param u16 blockSize : Number of blocks to copy.
* @param u32* memoryPtr : Buffer to copy from.
* @param bool with_init : determined card initialization.
* @return bool(u8) - Success or failure.
*/

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

这边看文档是看不清楚的,这个要看别人的代码

(int, unsigned int , unsigned short, unsigned int*, bool)
channel号
0或者[2] 起始块地址 复制多少块 复制到哪里去 一般给0

扇区和块的概念【重点】
最早的可编程块设备就是:软盘和硬盘,磁存储设备。存储单元不是以字节为单位,而是以扇区为单位的。

为什么叫扇区?磁盘存的时候是一圈一圈的,磁头在中间旋转。一个磁盘从中心分成6个扇形的区域,这就是扇区,是磁存储的读写最小单元。不能只读取扇区的一部分。这是磁存储本身原因造成的,这是编程时候必须遵守的规则。
——扇区有多个字节,一般规定扇区上512字节大小,后来有了2048/4096等。

一个扇区可以看做一个“块”,这就是块设备的来源。
linux中有个mtd驱动,就是用来管理块设备的。
磁道MDR DBR磁头柱面这些东西,如果写文件系统的话,需要对其了如指掌。

1 宏定义
#define CopySDMMCtoMem(z,a,b,c,e)(((bool()(int, unsigned int, unsigned short, unsigned int, bool))(*((unsigned int *)0xD0037F98)))(z,a,b,c,e))
简单方便
但是不可以做静态参数检查

2 函数指针
typedef bool(pCopySDMMC2Mem)(int, unsigned int, unsigned short, unsigned int, bool)
//实际使用
pCopySDMMC2Mem p1 = (pCopySDMMC2Mem)((unsigned int)0xD0037F98) //绑定函数地址

p1(x,x,x,x,x)
或者
(*p1)(x,x,x,x,x) //p1是函数指针的时候两种调用方法是一样的

下面的任务:
我们烧录小于16K的情况已经实现了,其实就是前面做的裸机
在后来遇到大于16K的时候,比如LCD显示图片,这就肯定大于16K了,我们必须想办法搞定大于16K的时候SD卡启动的问题,写代码解决。


10.7 SD卡启动实战

九鼎给我们的烧录程序给我们隐藏了一些烧录的细节
linux中的脚本可以帮我们做同样的事,writesd文件
“seek = 1”意思是从block1开始烧录
SD卡刚开始的时候Block0是“reserved”,这部分三星规定不能用

16KB是32个扇区,0扇区禁用,1-32存放BL1
BL2理论上可以从33扇区开始,但实际上为了安全会留出一部分比如从50开始。

all:
	make -C ./BL1		//-C进入当前子目录去make
	make -C ./BL1
clean:
	...

另外一个细节,DDR初始化之后,DDR就可以用了,这个时候要选择一段长度足够BL2的空间即可
我们选择0x23E0 0000,这个地址是因为uboot使用了这个地址

注意!我们只初始化了0x2000 0000~0x2FFF FFFF。共512M

要操作的几点:(可能不全,备忘)
1 BL1 , BL2文件夹创建好,里面各自弄好makefile
BL1工作到初始DDR结束
2 makefile中名字记得改Bootloader1.bin ,Bootloader2.bin
3 BL1链接脚本地址 = 0x0,其实就是0xd0020010。这是开头吗
4 在总工程里添加sd_relocate.c文件,使用device copy fun
从50扇区开始,我们往里写32扇区
5 writesd脚本中的if=…路径记得要./BL1…

第一步:读取sd卡扇区到DDR中
(int, unsigned int , unsigned short, unsigned int*, bool)
channel号
0或者[2] 起始块地址 复制多少块 复制到哪里去 一般给0
【2】 【45】 【32】 【0x23E0 0000】 0
第二步:跳转到DDR的BL2中执行
我们的BL1 BL2是属于两个程序,是不能ldr pc, =main跳转的,怎么办呢?
我们使用地址强制跳转!【这个我想过来了23333】

//定义一个函数指针
typedef void(*pBL2TYPE)(void)
...
pBL2TYPE   P = (pBL2TYPE)0x23E0 0000;	
p();
BL1完成!

BL2中的start.s
只需要调用//run on dram程序就可以了
ldr pc , =led_blink,这个函数名字要改,以后再说。

要操作的几点:(可能不全,备忘)
1 Makefile中删除添加头的部分
删除gcc…后面的东西,只需要arm-linux-gcc编译和链接
BL2中没有头了嘛,这个很容易理解。


SD烧录有好处有坏处
SD卡连接linux,先插卡
在VMWARE,虚拟机选项中选择SD卡
ls /dev/sd*
设备就是/dev/sdb sdb1是第一个分区,一般只有一个分区
如果不是sdb记得去writesd脚本中修改

./writesd

老师上节课出错,排错的方法很精髓,使用了bl led,卡住可能出现问题的语句
有一个错误是这样的:
原语句
pCopySDMMC2Mem p1 = (pCopySDMMC2Mem)0xD0037F98
正确写法(前面已经更正)

pCopySDMMC2Mem p1 = (pCopySDMMC2Mem)((unsigned int)0xD0037F98)
这里少了一个层次
函数本体不在D0037F98,现在的情况是函数不在这里,这里还是个指针
D0037F98存放了另一个地址,另一个地址需要*0xD0037F98才能取到。注意~

【课程总结】
代码分成两部分,这种技术称为分散加载。BL1和BL2是完全分开的,可以解决问题,但是比较麻烦。而且另一个缺陷是无法让工程同时支持SD卡启动、Nand启动等

第二种思路:程序代码仍然包括BL1/BL2,但组织时作为一个整体。
实现方式是:
irom启动,从SD卡读取16KB的BL1执行,初始化DDR
然后从SD卡中读取整个程序(BL1+BL2)到DDR中,到DDR中执行
DDR执行的时候使用长跳转来执行。
是SRAM中运行的BL1跳转到DDR中运行的BL2
这个就是uboot的启动方式。

【关于uboot】
uboot编译之后有200多K,前16KB为BL1,剩下的是BL2。烧录的时候,先截取uboot.bin的前16KB烧录到SD卡的block1-32,然后将整个uboot烧录到SD卡某个扇区,比如49扇区。
uboot在SD启动时,
<第一阶段>
1 irom先执行,OMpin判断启动方式为SD卡
2 在SD卡的block1读取16KB到SRAM执行BL1,初始化DDR
3 并且BL1从sd卡的49扇区复制整个uboot到DDR(0x23e00000)备用
4 然后BL1继续执行直到 ldr pc, =main时BL1跳转到BL2中执行uboot第二阶段

uboot其实不是很难,难是觉得他的结构很复杂,他跟linux内核相比真的是一个天上一个地下,所以不需要觉得uboot很难。

uboot启动的启动方式可以是万能的,SD能启动,NAND可以启动,USB也可以。
这就是uboot的优势所在。


10.8 解决x210的软开关问题
软启动原理,在bv3底板上
MP1482是一个稳压元件,有个ENABLE引脚,就是让芯片工作或不工作,EN为高有输出,为低就没有输出。这个引脚电平可控。

相关因素有3个,硬件知识【暂时跳过不写!】

为什么要软启动?
一般设计用拨码开关做开关电源,设计简单,但是电路太简单
不能做休眠模式和低功耗方式。

EINT0是复用的,一个是GPIO。另一个是PS_HOLD_CONTROL,属于GPIO子功能
在s5pv210裸机教程.pdf中有对这方面软开关置锁的说明。
其中一个位PS_HOLD_OUT_EN如果为1了,那么这个GPIO就被强占了

分析:启动置锁,只需要将bit0,8,9置1即可
非常简单,只要给PS_HOLD_CONTROL的bit089写1即可按下松手不断电。
而且放的越往前越好,干脆第0步,放在WDT之前

	ldr r0 , 0xe010e81c
	ldr r1 , [r0]	//不直接ldr r1, #301,是因为便于升级
	orr r1, r1, #300		
	orr r1, r1, #1	//分两步orr:是因为#301是非法立即数
	str r1, [r0]

我们置锁了,power键就不能用了,想要关机就按reset


11 Nand和iNand

NandFlash接口:有一部分数据线和一部分控制线
型号命名含义
示例:K9F2G08
K9F 三星公司的Nand
2G 表示Flash大小是2Gbit = 256MB
08 表示是8位的,即数据线有8根
数电知识:
字母上面有横线,代表低电平开启。

R/B 代表高电平R状态,低电平B状态
R:ready B:busy
Nand的数据位
有8位的和16位的,看到时候我们要注意。可以看出Nand是一个并行器件。
数据上不一定全部是存储的有效数据,也有可能是地址或命令

Nand的功能框图
NandFlash可以看成一个矩阵式存储器,其中分成多个小块,彼此以一定单位组成整个Nand
块设备,不能一次精确到位。只能按块访问是物理上的障碍。

Nand可以被访问的最小单元是“page”,中文名是页
单词访问:一次读写,至少要读写一个page,读取的是page的整数倍。
page的大小是2KB+64B
那么每次至少要读写2KB,或者读n x 2KB,没有更小的单元了。
【典型的块设备】
注意:现在有些块设备为了方便,提供了一个random read模式,可以读一个位,这是非典型的

页往上还有一个单位,叫做“Block”,块
一个Block包括多个页
在我们K9F08中 1个block = 64个page
块往上就是整个Nand
1个device = 2048个block

读写是的最小单位是页!擦除的最小单位是块


iNand

Nand的缺点:
每一个不同公司的nand产品甚至一个产品的不同型号可能有多个块,一个块有多少个页、一个页大小可能是大页2048、小页512种种不同,结构非常混乱。一旦升级或者换芯片就会软硬件重新升级移植,非常麻烦。如此inand产生了。
以后肯定会向inand/EMMC方向发展。

带内数据和带外数据
Nand的每个页由两部分组成:2KB+64B,两者都是存储空间,但有不同
2K 带内数据 :真正的存储空间,存有效数据 (计算容量时只考虑这个)
64B 带外数据 :不存有效数据,是作附加用途的譬如存储ECC数据、坏块标志等。
ECC:error correction code,错误校验码。
坏块标志:定义64B的其中一个位,用以标记一个块是好的还是坏的
(往往由文件系统定义固定位)
NandFlash相比NorFlash,本身出错概率高,容易位反转。明明是1读成0。所以将有效信息存储到Nand中时,都会同时按照一定算法计算ECC信息。(比如CRC16)将ECC信息同时存储到带外数据区。读取数据时,会再通过读出数据计算一次ECC并且校验;校验通过则证明Nand数据可信,否则校验失败,只能丢弃或尝试修复。
坏块:是不可避免的。出现了无法擦除或无法读写的情况。而且随着使用,坏块会越来越多。为了管理Nand,底层的软件发明了一种坏块标志机制。访问时出现了坏块就跳过这个块,其他的照用不误。

NAND的地址时序
4或者5cycle,通过IO发送给芯片对nand进行寻址。寻址最小单位是字节。【读写是页】
我们要按照特定时序和顺序依次写入。

Nand的命令码:1st+2nd cycle
按照Nand接口给Nand发送命令、地址、数据
命令就按照命令码发送。
譬如读操作:1st发00h 2nd发30h
写代码:发80h,写命令、地址、数据,发10h


nand的常见操作

坏块检查思路:
统一把块擦除。擦干净应该是0xff
读各个块内容
不是0xff则再来一次,仍不是是坏块

页写操作:
确保页是干净的。否则会出错。
write 在 flash中就是program

Nand结构:矩阵存储颗粒+接口电路 ---- 连接SOC的nand控制器

【Nand没有学的很透,代码需要参考=.=】


讲SD卡和Nand的时候,学单片机的时候会讲的非常细致,我们学嵌入式要高一个层次,暂时不需要搞的特别详细。
210不是stm32,是没有库的。库是以驱动的形式给我们封装了。
嵌入式最主要的任务是重在联络各个硬件设备。

iNand/eMMC的物理接口
注意:iNand接口就是eMMC标准接口

iNand结构:也是 矩阵存储颗粒+接口电路 ---- 连接SOC的nand控制器
不同之处在于接口电路功能不同
1 iNand的接口电路功能很复杂,遵从eMMC接口协议和外部通信。此外提供ECC校验相关的逻辑,SoC对此不用自己写代码,大大简化了编程难度。ECC是个非常麻烦的事情,有60多个寄存器。<这是最大的进步>
2 iNand接口电路提供了icache,提高了速度。要发就发,要收就收,不需要代码校验。

iNand芯片内部使用MLC,性价比高。
接口非常简单,8数据线,1时钟线,1命令线。和S5PV210的SD卡物理接口对比,都是1时钟线,1命令线,此处接线是非常类似的,没有Nand那么多那么复杂。我们实际操作iNand的时候,和SD卡相比几乎是一样的。物理是一样的,软件操作也是几乎一样的。
【iNand几乎就是芯片化的SD卡】

我们的代码几乎就是以前的 SD卡,全局上有80-90%是相同的。

我们的开发板支持4通道SD/MMC,实际0通道接了iNand,2通道和3通道接了SD卡。
这个设计在项目中很常用哦!我记得冲击点系统中的iNand,甚至还有USB都与此相似啊喂=.=

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值