- 论坛徽章:
- 0
|
[Mar 11]
1. 经过昨晚的调式,read一个block已经测试成功。
首先熟悉下初始化读CID过程:
(1) 配置SDI的GPIO,主要用到了6个引脚DAT0~3,CMD,CLK
(2) 配置SDIPRE,初始工作时钟SDCLK,可以让card在200~400kHz下工作。
(3) 设置了CLK,就可以使能该CLK,[SDICON]
(4) 设置(SDIDTIMER,SDIBSIZE,SDIFSTA),读写数据时用,可以先不设置。
(5) 先延时1s左右,让sd card电压升到稳定状态.接下来就是发送CMD了.
CMD0 --> CMD8 ---> CMD55 --> CDM41 -- OCR.bit31 is set or not --> CMD2
^------------------------^
发送CMD2之后, 如果之前都配置正确的话, CMD2的RESP里就有CID信息了.
初始化完之后,就可以尝试read a block, 先配置好(4)的几个寄存器, DTimer可以设大一点,否则容易发生
timeout, 接着发CMD3来获取一个RCA,可以连续发2个CMD3,来确定以下RCA值是否会变.有了RCA,之后凡是有用到
RCA作参数的都用该RCA值,CMD3之后card进入stand-by state.接下来可以发个CMD9, 来读取下CSD的信息
(如果有必要).然后发CMD7, 让sd card进入transfer state. 在该状态下可以配置sd card的blksize,
bus width等等.在transfer state下, 可以发送相应的read,write命令了.
昨天的主要问题还是出在arg的配置上,CMD55的arg是[31:16]RCA,[15:0]stuff bits.
由于第一次在发ACMD41的时候,当时还没有RCA从card端传过来,故用的是0x0, 读完CID以后,
用CMD3获取了一个RCA,故之后的命令中有RCA作参数的就需要指定CMD3获取的RCA,而我在之后用到
CMD55的地方,RCA还用的是0,所以cmdsta一直timeout状态。注意到了以后,之后凡是用到RCA的
都用了正确的RCA值。另外,在填host端与card端的block size 与bus width时要注意一致。
在blksize上,我两端都直接设置为通用的512bytes/blk, bus采用4位来传输数据。发完读一块数据命令
CMD17后,就可以循环读取SDIDAT上的数据了.这里的数据都是来自FIFO的,故要检测是否读完,可以判断下
SDIFSTA的BIT12,当FIFO empty的时候就可以结束数据读取了. 还需要注意的是发送命令的参数
[31:0]data address 这个参数是表示要读取的是哪个块.这个data addr应该设为blksize的整数倍:
BLKN * BLKSIZE, BLKN就是block的index了.
数据读是读了,但是不知道对不对.所以往里面写一块数据,然后再读出来验证以下.
2. 编写write函数。
往一个block里写数据的命令是CMD24,写哪一块取决与arg,也就是data address.写之前与读一样都得
先配置SDIDATCON.
write a block data成功, 但是写完立刻读,发现没数据读出来.fifo为空. 先读,后写同一块区域时,
可行, 数据是上一次写操作时的数据,此操作验证了write函数已经成功.
于是测试先往连续10个block里写不同的数据,然后接着读取这10个block里的数据.结果发现第一块读取
数据失败,后9个block可正常读取,数据也正确.经多次测试及讨论,最后问题确定在SDIDATCON这个寄存器的
BlkNum这段位域上,这个位域表示的是block num(0~4095),我原以为可以随便填个数,后来才知道这个位域表示
一次要发的block数,所以发一个block时,该位域值设为1才正确.填完之后,收发一切正常.
3. 总结一下read,write时要注意的地方. 首先当然是要填对相关寄存器的值,以及各命令要用的参数. 设置都
正确了,接下来就是判断status register了.这里的几个registers的一些判断位比较容易混淆:
SDIDatSta 显示数据传输状态及正确性. 数据发送,接收完毕后,DatFin位都会置一.但是不表示数据发送,接收结束,
因为FIFO里还留有数据.
SDIFSTA 这里的状态位域比较重要,因为数据都是先存放在FIFO里的,跟read,write的操作密切相关.
write时检测TFDET位, set时可以发送数据.由于测试时是单块数据发送,FIFO里不会存留数据,
写一次立即被发送,故可以直接将一块数据写入SDIDAT中.
read时检测RFDET位,set时表示有数据过来,可以接收.还有一位RFLast需要注意,该位不是说数据接收
结束,而是表示SD端数据发送完毕,FIFO里还留有数据,所以只要判断RFDET位即可,FIFO empty时即可
结束接收. |
|