发新帖我要提问
12
返回列表
打印
[应用相关]

STM32之SD卡

[复制链接]
楼主: equivalent
手机看帖
扫描二维码
随时随地手机跟帖
21
equivalent|  楼主 | 2019-7-22 15:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
六、STM32与SD卡相配的外设--SDIO适配器

1、SDIO adapter 结构图

使用特权

评论回复
22
equivalent|  楼主 | 2019-7-22 15:38 | 只看该作者
2、命令状态机(CPSM)

  当发送命令和接收响应时,启动CPSM状态机。

使用特权

评论回复
23
equivalent|  楼主 | 2019-7-22 15:38 | 只看该作者
3、数据通道状态机

  当传输数据时,启动数据通道状态机。

使用特权

评论回复
24
equivalent|  楼主 | 2019-7-22 15:39 | 只看该作者
4、FIFO

  有关FIFO的资料参考:异步FIFO的FPGA实现

  数据FIFO(先进先出)子单元是一个具有发送和接收单元的数据缓冲区。

  FIFO包含一个每字32位宽、共32个字的数据缓冲区,和发送与接收电路。因为数据FIFO工作在AHB 时钟区域(HCLK/2),所有与SDIO时钟区域(SDIOCLK)连接的信号都进行了重新同步。依据TXACT和RXACT标志,可以关闭FIFO、使能发送或使能接收。TXACT和RXACT 由数据通道子单元设置而且是互斥的:

    ─ 当 TXACT 有效时,发送 FIFO 代表发送电路和数据缓冲区
    ─ 当 RXACT 有效时,接收 FIFO 代表接收电路和数据缓冲区

使用特权

评论回复
25
equivalent|  楼主 | 2019-7-22 15:39 | 只看该作者
5、SDIO的特殊功能寄存器

SDIO电源控制寄存器(SDIO_POWER)
SDIO时钟控制寄存器(SDIO_CLKCR) : 时钟选择、分频
SDIO参数寄存器(SDIO_ARG)
SDIO命令寄存器(SDIO_CMD):控制发送命令
SDIO命令响应寄存器(SDIO_RESPCMD):包含响应命令中的命令索引
SDIO响应1..4寄存器(SDIO_RESPx):包含响应命令中的卡状态信息
SDIO数据定时器寄存器(SDIO_DTIMER)
SDIO数据长度寄存器(SDIO_DLEN):读或者写的长度,通常是是512的倍数
SDIO数据控制寄存器(SDIO_DCTRL):控制数据的读写方向、使能传输等信息
SDIO数据计数器寄存器(SDIO_DCOUNT):当DPSM状态机从Idle state切换到Wait_R或者Wait_S状态时,SDIO_LEN的数值加载到该寄存器中
SDIO状态寄存器(SDIO_STA)
SDIO清除中断寄存器(SDIO_ICR)
SDIO中断屏蔽寄存器(SDIO_MASK)
SDIO FIFO计数器寄存器(SDIO_FIFOCNT):当SDIO_DCTRL中的DTEN使能,并且DPSM处于Idle state时,SDIO_LEN/4的数值加载到该寄存器中
SDIO数据FIFO寄存器(SDIO_FIFO):读写数据缓冲FIFO

使用特权

评论回复
26
equivalent|  楼主 | 2019-7-22 15:40 | 只看该作者
七、SD卡编程

  SD卡的编程在STM32官方固件库中就有例程,而且野火开发板对该例程进行了中文注释,不必再把源码贴入。这里着重讲一下SD卡编程流程,主要包含SD卡初始化、SD卡读、SD卡写、SD卡擦除。

使用特权

评论回复
27
equivalent|  楼主 | 2019-7-22 15:41 | 只看该作者
1、SD卡编程的内容

  SD卡主要就是用来存储数据的,所以核心就是读写。为了实现这个目标,必须实现响应的驱动。

  配置过程中,不仅要设置好SD控制器,还需要将SD卡设置到合适的状态。在读取状态的时候,不仅涉及到SD控制器的状态,还涉及到SD卡的状态。

使用特权

评论回复
28
equivalent|  楼主 | 2019-7-22 15:41 | 只看该作者
2、SD卡初始化

① STM32外设SDIO初始化

端口配置、端口时钟、SDIO时钟、DMA2时钟使能
SDIO寄存器复位
设置时钟SDIO_CK为400KHz以下,设置数据线宽度,开启时钟、开启SDIO电源
② SD卡上电初始化



  上电初始化流程如上图所示,笔者认为官方库提供的例程没有完全按照这个流程图的指示去做。事实上,官方库的程序只做了如上图红色方框内的流程,之外的没涉及。

  CMD0命令复位所有的卡。

  SD协议规定:在初始化的时候,使用ACMD41之前,必须先使用CMD8命令。而且ACMD41命令属于应用命令,在使用之前需要先发送命令CMD55。

  CMD8命令是为了核查电源是否匹配。ACMD41命令不断询问SD卡是否支持主机提供的电压,并且询问SD卡是否上电完成进入准备状态。ACMD41命令还能询问SD卡的类型(SDSC、SDHC)。

③卡进一步核查、获取卡信息

  发送命令CMD2,以获取CID信息。

  发送命令CMD3,以获取RCA相对地址,可以通过多次发送CMD3获取不同的RCA值,但是只有最后一次的才是有效的RCA地址。

  发送命令CMD9,以获取CSD寄存器。

④ 设置SDIO工作在数据传输模式

  设置SDIO的时钟为24MHz、数据线宽度为4位。

  通过SD_GetCardInfo函数将之前得到CID、CSD处理成卡的信息。

  通过CMD7命令选择匹配地址的卡,而取消选择其他的卡。

  至此,初始化完成。

使用特权

评论回复
29
equivalent|  楼主 | 2019-7-22 15:41 | 只看该作者
3、读SD卡的一个块

 数据控制寄存器(SDIO_DCTRL)清零
 发送命令CMD16,设置SD卡的Block大小
 调用函数SDIO_DataConfig设置SDIO数据传输方式
 发送命令CMD17,读单个块
 SDIO数据传输结束中断使能
 SDIO的DMA传输功能使能
 DMA设置,并使能

使用特权

评论回复
30
equivalent|  楼主 | 2019-7-22 15:42 | 只看该作者
4、写SD卡的一个块

 数据控制寄存器(SDIO_DCTRL)清零
 发送命令CMD16,设置SD卡的Block大小
 发送命令CMD24,写单个块
 调用函数SDIO_DataConfig设置SDIO数据传输方式
 SDIO数据传输结束中断使能
 DMA设置,并使能
 使能SDIO的DMA传输功能

使用特权

评论回复
31
equivalent|  楼主 | 2019-7-22 15:42 | 只看该作者
八、SD卡疑惑

1、SD卡擦除后,其中的内容是0,还是1 ?

  The data at the card after an erase operation is either '0' or '1', depends on the card vendor.The SCR register bit DATA_STAT_AFTER_ERASE (bit 55) defines whether it is '0' or '1'.(摘自《SD Specifications_Part_1_Physical_Layer_Specification_Ver3.00_Final_090416.pdf》)

  也就是说这是芯片厂商生产工艺决定的,可以通过SCR寄存器的 DATA_STAT_AFTER_ERASE位得知。

使用特权

评论回复
32
equivalent|  楼主 | 2019-7-22 15:42 | 只看该作者
2、在SDIO_DCTRL中设置传输Block的要求

  Block大小决定了主机在发送数据时,发送到什么程度时开始发送CRC校验码;而在接收数据时,在接收到什么程度时开始把SD卡的数据作为CRC校验码并进行校验。Block还可能影响着其他的时序。在STM32的SDIO寄存器组中,SDIO_DCTRL中的位段DBLOCKSIZE决定主机Block大小。

  在摘自《Simplified_SD_Host_Controller_Spec.pdf》的引文中,提到这样的配置要求:主机的Block一定要与SD卡设置的Block一样大小,这显然是必要的。我们经常设置SD卡的Block大小是512Bytes,所以设置DBLOCKSIZE为9(2^9 = 512)。

使用特权

评论回复
33
equivalent|  楼主 | 2019-7-22 15:42 | 只看该作者
3、STM32固件库“stm32_eval_sdio_sd.c version v4.5.0”偶遇BUG

  参考网页:http://www.cprogramdevelop.com/3742318/

使用特权

评论回复
34
equivalent|  楼主 | 2019-7-22 15:43 | 只看该作者
4、SD卡写Block是怎样进行的?

  写SD卡的单位是Block(512Bytes),再写之前要先整块擦除,然后才能写。

  在多块写操作中,可以在发送多块写命令CMD25之前,有选择性的先发送命令ACMD23设置预擦除。怎样理解呢?

  既然是有选择性的,也可以不发送ACMD23命令。在多块写的过程中,由于SD卡事先不知道你要写入几个块(CMD25命令只告诉SD卡要写入的起始地址),所以写入的过程是:根据需要判断要写一个块时,先擦除然后再写,再判断是否要写入下一个块,如果是就再擦除再写。

  倘若发送ACMD23命令就不一样了,ADM23命令会在写命令CMD25生效之前,告诉SD卡准备写入的块数N。这样当CMD25命令生效的时候,SD卡会一次性先将这N个块都擦除,然后再一个块一个块写。由于擦除操作比较集中,所以整个多块写操作更节省时间。

使用特权

评论回复
35
equivalent|  楼主 | 2019-7-22 15:43 | 只看该作者
九、SD卡参数测试

  使用野火开发板配套例程做测试,笔者测试用的SD卡是金士顿的2G内存块,打印SD卡的参数信息如下:
Card Type is :1 
ManufacturerID is :2

Card device size is :3795  
Card Block Size is :1024  
Card device size multiplier is :7  
Card Capacity is :1990197248
  
the maximum read date block length is :1024  
partial blocks for write allowed is :0  
the maximum write date block length is :1024  
erase single block enable is :1  
erase sector size is :127  
write protect group size is :0  
RCA is :4660


Card Type:1         SDSC卡版本2.0

Card device size:  C_SIZE(CSD),为3795

Card Block Size:  max read data block length(READ_BL_LEN(CSD)) ,为1024 Bytes

Card device size multiplier is:  C_SIZE_MULT(CSD),为7

Card Capacity:  1990197248 Bytes

计算方法(摘自《Simplified_Physical_Layer_Spec.pdf》):

memory capacity = BLOCKNR * BLOCK_LEN

  BLOCKNR = (C_SIZE+1) * MULT  (C_SIZE <= 4096)
  MULT = 2^(C_SIZE_MULT+2)        (C_SIZE_MULT < 8)
  BLOCK_LEN = 2^READ_BL_LEN,    (READ_BL_LEN < 12)

注意:SDSC最大为2GB。

the maximum read date block length:READ_BL_LEN(CSD) ,为1024 Bytes

partial blocks for write allowed:WRITE_BL_PARTIAL(CSD),为不支持

the maximum write date block length:WRITE_BL_LEN(CSD) ,为1024 Bytes

erase single block enable:ERASE_BLK_EN(CSD),为1,支持单块擦除

erase sector size:SECTOR_SIZE(CSD),实际扇区擦除的block数为(SECTOR_SIZE+1),为128 Blocks

write protect group size:WP_GRP_SIZE(CSD),实际保护的扇区数为(WP_GRP_SIZE+1),为1 Sector

RCA: SD卡相对地址为4660

使用特权

评论回复
36
equivalent|  楼主 | 2019-7-22 15:44 | 只看该作者
参考资料:《Simplified_SDIO_Card_Spec.pdf》

     《Simplified_Physical_Layer_Spec.pdf》

       《Simplified_SD_Host_Controller_Spec.pdf》

     《STM32芯片手册》

使用特权

评论回复
37
xiaoqizi| | 2019-8-12 12:01 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
38
木木guainv| | 2019-8-12 12:06 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
39
磨砂| | 2019-8-12 14:00 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则