供电电压,主机发送引脚波形是否正常,发送有发送无接收看接收引脚是否虚焊,短接发送和接收,时钟是否开启配置是否正确,发送后有没有延时接收,协议中的校验是否通过,根据原理图,数据手册查看配置是否正确(寄存器,dts)。换板子。
emmc读写速度慢:是1线,还是4,8线,emmc和控制器本身支持的最高速率,还有dts的配置,cache(sync)是否有影响,驱动强度;回写,调度。
bus-width,驱动电流,控制器版本号,插卡dmseg无打印 fstab自动挂载
sd卡:工作在命令和响应模式
MSYS:cpu(1G),ddr(200M)
DSYS: 视频,编解码
PSYS:内部外设,串口,sd接口,I2c,(前面30-40M)usb
block层:实现mmc为块设备,和块设备那套对接,实现并注册卡的驱动,加入到bus上。
core:抽象host,bus ,card实体,向底层提供便利的host要用的api。提供检测卡的插入,向bus注册sd卡。
host:提供并注册host驱动,实现host ops,用platform bus去match。
sd卡插入后的流程:中断检测总线上是否有卡,init card(standy_by),在bus上add card,找到driver match上,probe函数。
OCR: 卡操作电压寄存器 32位, 只读,每隔0.1V占1位, 第31位卡上电过程是否完成
CID: 卡身份识别寄存器 128bit,只读, 厂家号,产品号,串号,生产日期
SCR: 卡配置寄存器, 可写的 64bit 是否用Security特性(LINUX不支持),以及数据位宽(1bit或4bit)
RCA: 卡地址寄存器: 可写的 16bit SD host和卡进行协商的一个地址,内核中会在代码里面记录这个地址,卡这 边则写到RCA寄存器
CSD: 卡专有数据寄存器 部分可读写 128bit, 卡容量,最大传输速率,读写操作的最大电流、电压,读写擦出块的最大长度等
硬件接口:
(SD卡有9个pin:1个VDD,2个VSS(GND),CLK,CMD,DATA0-DATA3, 【DATA3可以作为卡检测脚】)
卡类型:1.不可知 2.sd_v1 3.sd_v2 34.sd_hc 5.mmc
sd卡状态机(总共9种):1.空闲 2.准备好 3.transfer 4.出错状态 5.卡编程状态(在接口电路中,还没写到内存颗粒中)
卡回复类型(总共9种)
通信电压范围:2.0-3.6V;工作电压范围:2.0-3.6V
最大读写速率:10Mbyte/s
对F1来说,SDIOCLK来自HCLK(72Mhz,系统时钟);对F4来说,SDIOCLK来自PLL48CK(48Mhz)。
控制器,resources(gpio,时钟,中断),sd卡
mmc裸机
状态机和命令
sd卡裸机代码(soc控制器和sd通信(发命令和收响应))
判断通道0(inand)还是通道2(sd卡),
1.通过gpio(gpio复用)设置为sd卡工作模式(用哪些GPIO查原理图,数据手册,MMC_D0如GPJ0_3 查GPJ_0 可以配置成输入输出,sd,中断模式)
2.设置上拉 enable(GPG0PUD_REG)
3.设置soc控制器clk(96M 分频为48M)
4.sd卡控制器的一些设置,比如复位soc控制器(延时10ms判断),清中断
5.先设置sd卡时钟(400K,设置低版本的时钟,后面判断如果高版本设置高版本时钟)(时钟要等稳定),后面识别sd卡后再给合适的时钟
6.检查cmd线是否准备好(查看PRNSTS寄存器值)
7.检查data线是否准备好
8.发送cmd0(复位所有mmc卡到空闲状态),不需要response。
8.cmd8(命令吗+cmd type)查看是否有响应,没有就是卡的版本太低,或者没卡,不识别的卡,sd卡电压不对。等待sd 卡response,检查错误。
8.acmd41=cmd55+cmd41 acmd41有回复OCR寄存器就是sd卡,acmd41没回复就是mmc卡。根据OCR查看sd卡是否上电完成。
9.cmd2,读出卡的cid寄存器,cmd3,读出rca寄存器,读出卡的相对地址,使卡进入stand-by状态。
读写:
9. 发cmd7使卡进入transfer状态
10.cmd16设置块大小
11.获取csd相关信息,block大小,卡的容量
11.根据sd的版本重新设置时钟
12.清中断,cmd24 cmd25读写,此时sd卡变为programming状态,等写完成,转换为transfer状态
通道2的detect函数去掉
OCR: 卡操作电压寄存器 32位, 只读,每隔0.1V占1位, 第31位卡上电过程是否完成
CID: 卡身份识别寄存器 128bit,只读, 厂家号,产品号,串号,生产日期
SCR: 卡配置寄存器, 可写的 64bit 是否用Security特性(LINUX不支持),以及数据位宽(1bit或4bit)
RCA: 卡地址寄存器: 可写的 16bit SD host和卡进行协商的一个地址,内核中会在代码里面记录这个地址,卡这 边则写到RCA寄存器
CSD: 卡专有数据寄存器 部分可读写 128bit, 卡容量,最大传输速率,读写操作的最大电流、电压,读写擦出块的最大长度等
命令:sd卡probe流程
SD卡的操作模式
卡识别模式
数据传输模式
最多支持64个命令: CMD0~CMD63,(其中CMD57~63是保留的)
卡寻址通过会话地址方式实现,地址在初始化的时候分配给卡。SD 总线上 的基本操作是command/response。 数据传送采用块方式,数据块后接CRC 校验位,操作包括单数据块和多数据块。多数据块更适合快速写操作,多数据块传输当在 CMD 线出现停止命令时结束。 数据传输可以在主机端设置采用单数据线或多数据线方式。 块写操作在DAT0 数据线写操作期间使用忙信号,无论用来传输的信号线数 目是多少。
MMC/SD通过发命令的方式来实现卡的初始化和数据访问
命令:通过CMD线
响应:通过CMD线
数据:通过4条数据线
命令类型:
Broadcast Commands ( bc), no response
Broadcast Commands with Response (bcr )
Addressed (point-to-point) Commands (ac )
Addressed (point-to-point) Data Transfer Commands (adtc)
问题,
1.从csd寄存器读出卡的版本信息,能读出来,但是如果卡的版本信息大于5就报错。
nand(nand芯片本身(包含接口电路,存储空间),soc nand flash控制器)
nand寻址的最小单位是字节。
nand的最小读写单位是page。页对齐。
page上面是block(例如1block= 64 page)
page是读写的最小单位,block是擦除的最小单位。
地址有30位,而io线只有8位(有些有16位),需要通过4cycle或者5cycle来发送。
2K+64 64是ECC和坏块标记。
soc中有一个nand控制器。
现在有些块设备可以支持random read。
命令,地址,数据。
坏块检查:1.线块擦除 2.再读出来,检查是否0xff(是表明不是坏块)
擦干净是0xFF
初始化:
1.配置nandflash rNFCONF rNFCONT
2.配置GPIO
3. nand_reset
读
获取row地址,发出片选信号,清0状态位。
write 00h(命令线)(写是80h)->
write address(地址线)(通过5cycle写入页地址)->
清status寄存器(rNFSTAT)->
write data(数据线)->
write 10h(命令线)->
等待空闲->
nand_read8(例如读一页2K的数据)
(读取read status register):根据状态寄存器判断数据是否写成功(将页数据写到接口电路缓冲区,接口电路将数据从缓冲区写到真正的存储系统中需要时间(soc不断读取状态寄存器(soc控制器自带,soc发命令响应得到),只有nand接口电路写完))->
读状态:读取是否写成功,不管是否写成功取消片选
ECC(nand控制器主要的寄存器)(用SFR来控制,通过读写SFR寄存器来读写nand芯片)
soc控制器的寄存器:
1.NFCONF(设置5 cycle)
2.NFCONT
3.NFCMD NFADDRESS NFDATA
4.NFECCD0-4
5.NFSBLK(操控块,放块地址)
6.NFSTAT(状态寄存器)
C语言
擦除
int nand_block_erase(unsigned long block_num)
{
计算:row =block_num *nand_block_size(row地址,即页地址)
片选
发送命令->row address(rNFADDR)->rNFSTAT(清状态位)->发送命令->等待状态位变化(标志写完成)->校验(读)
取消片选
}
ddr裸机代码
chanel>dimm>rank>chip>BANK>row/colomn
1个i7 cpu->2个channel->每个channel2个DIMM->每个DIMM两个rank->每个rank有8个chip(内存颗粒8bit,cpu64bit,需要8个chip)->每个chip八个bank
ddr接口:
x210 2个DMC(DRM0,DRM1,每片256M内存) 一共2片内存(2 chip) 4bank 13根地址线 BA0-BA3:选bank 32根数据线
DMC0 0x20000000-0x2FFFFFFF 256M
MDC1 0x30000000-0x3FFFFFFF 256M
BA0-BA3(2的3次方):选bank 8个bank(128Mib/每个,即16M) 再通过row(14)+colomn(10) address
2的24次方(2的20次方是M,这里是2的4次方)是16M(128Mbit)
ddr裸机(根据数据手册27步操作)
DMC0
1.设置io端口强度(和总线连接,抗干扰)数值:1x,2x,3x,4x(例如:ELFIN_GPIO_BASE,MP1_0DRV_SR_OFFSET)
2.设置ddr时钟:(APB_DMC_0_BASE+DMC_CONTROL0) 同步工作DLL PLL(倍频)通过时钟总线 200M->1G PLL(锁相环,时钟稳定)
3.关闭自动重刷新 DMC0_CONTROL(时序不会)
4.设置burst length(4或者8,一次读取多少位),设置2chip DMC0_MEMCONTROL
5.(memconifg寄存器)1.设置DMC0的起始地址(0x20对0x20000000)2.设置基地址演码(即设置内存长度,0xF8对0x7 相反,F0000000和0FFFFFFF相对(256M),如果是E0(512M))3.设置row和colomn 4.设置8bank DMC_MEMCONFIG_0
6.设置auto refresh时间 TIMINGAREF 7.8us*133Mhz=1038 0x40E x210时钟200M(0x618)
7.发送命令吗 1.nop 命令7 2.PLL 1 3.EMSR等等。 DMC_DIRECTCMD
按照ddr控制器时序要求,ddr的配置非常专业细致,ddr源厂配置。我们只要配置一些通用的参数。
放到start.s中测试。led灯亮