SD nand与SD卡 SPI模式驱动

本文详细介绍了如何通过SPI接口驱动SDnand(SD卡),包括SPI与SD接口的区别、初始化流程、模式切换、数据传输等步骤,并提供了相应的代码示例。内容涵盖了SDnand的结构、SD接口协议、SPI时序以及识别和数据读写过程,旨在帮助读者理解并实现SDnand的SPI模式通讯。

SD nand 与 SD卡的SPI模式驱动

1. 概述

首先简单介绍下SD卡和SD nand:

  • SD卡,也称之为内存卡,在早些年间的手机上出现过,主要用来存储数据;在这里插入图片描述

  • SD nand,贴片式SD卡,使用起来和SD卡一致,不同的是采用,通常采用LGA-8封装,尺寸为8mm x 6mm x 0.75mm,重点是采用贴片封装,可以直接贴在板卡上,直接解决了SD卡固定问题,再也不用为SD卡的接触稳定性操心!
    在这里插入图片描述

SD nand 与 SD卡除了封装上的区别,使用起来基本没什么不一样,因此下文中不再做区分,统一以SD nand作为描述。

SD nand 和 SD 卡、SPI Nor flash、 nand flash、eeprom一样,都是嵌入式系统中常见的用来存储数据所使用的存储芯片,这几种存储芯片主要的区别在于存储数据容量不一样、操作的大小不一样,价格不一样,因此在实际产品设计中,往往需要根据自身产品的需求来选择对应的存储芯片。

SD nand存储空间大小在上述存储系列芯片中属于偏大的,其存储空间小到 1Gb(256MB) 起步,大到可以到32G,最小读写单元通常是 512 Byte,与SD卡一样,均支持SD接口模式以及SPI接口模式(后文会详细描述其区别)。

关于采用SPI接口模式完成于SD nand和SD卡的通讯,网上也有相关资料,但描述均不是很清楚或完整,因此特整理此博客,以作记录及分享。

本博文以 CS 创世 CSNPGCR01-AOW 这颗IC为例,着重描述如何通过SPI接口完成SD nand(SD卡)的读写驱动。

2. SPI接口模式与SD接口模式区别

2.1 接口模式区别

SD nand同时支持SPI接口和SD接口,接下来主要从以下几个维度分析二者的区别:

  • 硬件资源角度:
    • SD接口需要控制器具有SDIO外设硬件支持
    • SPI接口如果控制器具有SPI硬件外设那就最好了,没有也可以使用软件模式SPI
  • 传输效率:
    • SD接口支持四线同时传输
    • SPI只有MOSI一根总线
    • 且接口速度上SD接口速度通常要大于SPI接口,因此SD效率远高于SPI接口
  • 控制难度:
    • SPI协议比较简单,也是嵌入式开发中最常使用的协议之一,只有MISO和MOSI两根数据总线,因此控制难度简单;
    • SD协议相对SPI要复杂,且需要控制的引脚多,内部还存在状态机,相比SPI较为复杂

综上分析,SD接口效率更高,但是需要芯片有对应外设支持,而SPI接口虽然效率比不上SD接口,但是控制起来简单,且对芯片外设硬件依赖不高,对于低端的控制器,亦可使用软件模式SPI来驱动SD nand。

2.2 硬件引脚

SD nand以及SD 卡在SPI接口以及SD接口模式下,硬件引脚如下图所示:

  • SD nand SPI接口及SD接口模式IO定义
    在这里插入图片描述

  • SD卡 SPI接口及SD接口模式IO定义在这里插入图片描述

2.3 注意事项

此外对于使用SPI接口需要注意的是,SPI接口只是定义了物理传输层,并没有定义完整的数据传输协议,因此上层软件还是需要遵循SD接口协议!

3. SD接口协议

在2.3中我们重点强调了,SPI接口只是定义了物理层,也即硬件链路层,关于协议层并没有定义,写一次依旧遵循SD接口协议,因此我们需要首先了解下SD总线协议的内容。

SD 总线协议由SD卡协议定义,是一个通用的标准协议。首先说明的是,SD总线协议不仅仅只适用于SD卡,还支持IO卡,MMC卡等等,而且对这些不同类型的设备均能做出区分的!有点像USB一样牛逼!
在这里插入图片描述

我们首先来了解下SD总线协议中的命令及响应。

3.1 命令

命令由主机发出,分为广播命令和寻址命令

  • 广播命令是针对与SD主机连接的所有设备发出的

  • 寻址命令是指定某个地址的设备进行命令传输

3.1.1 命令格式

命令由48bit位(6字节)组成,格式如下:
在这里插入图片描述

  • 起始位:1bit 固定为0
  • 传输位:1bit 主要用于区分传输方向,1代表主机发送给从机的命令,0代表从机响应的主机命令
  • 命令号:6bit 命令号索引,总共能表示2^6=64个命令
  • 命令参数:32bit 命令所包含的参数信息
  • CRC7:7bit CRC校验位,用于保证数据传输的正确性,生成器多项式为:G(x) = x^7 + x^3 + 1
3.1.2 命令类型

命令主要有4种类型:

  • bc:无响应广播命令
  • bcr:有响应广播命令
  • ac:寻址命令,发送到选定卡,DAT线没有数据传输
  • adtc:寻址数据传输命令,发送到选定的卡,且DAT线有数据传输

在SD总线协议中,经常见到的CMDx,代表的就是命令号,后面的x代表命令索引,在3.1.1中命令格式组成中描述了命令号总共占6bit,所以CMDx的范围是CMD0 - CMD63,CMD后面的数字代表的就是命令号command index的值。

对于SD这么复杂的协议,64种命令类型通常还不能涵盖所有类型的数据,因此SD协会在制定此协议的时候将命令继续细化,分了两种类型的命令:CMD和ACMD,CMD代表常规命令,ACMD代表特定应用的命令,ACMD通常为制造商特定使用的。

那么SD协议又是如何区分CMD和ACMD命令的呢?

在发送ACMD命令之前必须发送特定的CMD命令(APP_CMD)表明接下来的一帧命令是ACMD命令,在SD协议种规定此特定命令名称叫APP_CMD,也就是CMD55

需要注意的是,CMD命令类型这么多,但实际上并没有都使用,针对SD nand(SD卡)的命令也就那么几条(注意SD模式命令的响应和SPI模式命令的响应有些许不同,SD模式请自行查阅手册)
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

上图中,命令序号对应3.1.1节命令格式中的命令号 command index,参数对应3.1.1节命令格式中的命令参数argument。

3.2 响应

针对需要响应的命令(bcr),SD nand(SD卡)在接收到命令之后会做出响应,根据命令的不同,响应的类型也不相同,其中命令中已规定哪个命令需要响应,并且返回什么类型的响应。

响应总共分为7中类型,分别是R1~R7,需要注意的是,SD nand(SD卡)没有R4、R5类型的响应。

响应的数据长度也并非完全一样,响应根据内容长度分为短响应和长响应,短响应长度为48bit(6Byte),长响应长度为136bit(17Byte),其中只有R2属于长响应,其他均属于短响应。

3.2.1 响应格式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
其中重点讲下R1响应,在上图中我们可以看到R1返回的内容为卡的状态,关于卡状态的描述如下,每个bit均代表着对应的含义,如下图中所示:在这里插入图片描述

4. SD nand(SD卡)结构描述

在这里插入图片描述
上图是SD nand的内部结构,与SD卡完全类似,主要有五个部分组成,这里就不细述了,不然此篇文章会过于臃长,关于这块大家可以上网查找,需要重点注意的是内部有7个寄存器,主要用来对卡片进行配置和读取卡片有关的信息,描述如下,其中SD接口有些命令就指定了读取哪个寄存器的内容!在这里插入图片描述

5. SD nand SPI通讯

主要参考资料:官方文档《Part_1_Pjysical_Layer_Specification_Ver2.0.0pdf》
建议大家有时间的话也可以读一读,还是有收获的,如果没时间的话也可以先参考本博文

5.1 SD nand SPI 通讯概述

SD nand SPI通讯接口完成驱动主要可以分为三大部分:

  1. 上电初始化以及模式切换
  2. SD nand(SD卡)识别
  3. 数据传输两大步

在以上三大部分中,每个部分均有命令传输,从3.1.1中我们可以知道发送给SD nand的命令为48bit,也就是8字节,那么SPI模式下与SD nand通讯,发送命令其实就是采用SPI总线往SD nand传输8个字节的数据,大家把握这这个思路去理解下文的通讯过程也就简单多了。

需要注意的是:

  • SD nand或SD卡上电默认均为SD模式,需要对齐完成初始化以及模式切换后才能切换到SPI模式。
  • SD 模式,所有命令默认开启CRC校验,因此没有切换到SPI模式之前,所有命令都必须携带正确的CRC校验值
  • 进入SPI模式后,默认关闭CRC校验,此时CRC校验字段默认填充1即可,当然也可以通过命令配置打开SPI模式的CRC校验

5.2 SPI 时序

在开始进行通讯读写前,我们先来看下SPI时序,使用SPI完成于SD nand(SD卡)的通讯与我们平常使用SPI与其他设备通讯会有一点点小小的区别,主要在于往SD nand写了数据之后,回复不是马上的,以及在必要的数据之间需要增加间隔,我们挑几个重点看下,在实际开发中有需要注意的在后文对应处有描述,不用过于担心。

  1. 主机发送命令给卡,卡响应,注意图中的NCR,NCR最小不是0,因此主机发送了命令之后,SD nand不是马上就响应的在这里插入图片描述
  2. 卡连续响应两个指令之间需要有间隔,如图中的NRC在这里插入图片描述

5.3 上电初始化及模式切换

5.3.1 初始化及模式切换流程说明
  1. 首先配置控制器SPI外设
  2. SD nand(SD卡)电源应该在250ms内到大VCC,这是硬件电路要求
  3. 同时保持CS引脚为高电平状态,CLK时钟引脚至少发送74个时钟给SD nand已启动SD nand
  4. 之后SD nand进入空闲状态,发送CMD0命令至SD卡切换进入SPI模式
    • 注意务必保证CMD0是第一包命令
    • SD卡选择了对应的模式之后不可切换,如果需要重新切换,需要重新上电
      在这里插入图片描述
5.3.2 代码实现
  1. SPI外设配置代码如下:
#ifndef __BSP_SPI_H__
#define __BSP_SPI_H__

#include "stm32f10x.h"

#define PIN_HIGH    1
#define PIN_LOW     0

int sd_spi_config(void);
void set_sd_spi_cs_pin(uint8_t state);

#endif /* __BSP_SPI_H__ */
#include "./spi/bsp_spi.h"

/**
 * @brief spi gpio configuration
 * 
 * @note CLK:PA5 MISO:PA6 MOSI:PA7 CS:PA8
 * 
 */
static void _spi_gpio_init(void)
{
   
   
    GPIO_InitTypeDef GPIO_InitStructure = {
   
   0};
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  
    /* Configure SD_SPI pins: SCK */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Configure SD_SPI pins: MOSI */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Configure SD_SPI pins: MISO */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
    GPIO_Init(GPIOA, &GPIO_InitStructure);
  
    /*!< Configure SD_SPI_CS_PIN pin: SD Card CS pin */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

/**
 * @brief configer spi1 peripher.
 * 
 * @note Data rising edge acquisition.
 */
static void _spi_config(void)
{
   
   
    SPI_InitTypeDef SPI_InitStructure  = {
   
   0};
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

    /*!< SD_SPI Config */
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode      = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize  = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL      = SPI_CPOL_High;
    SPI_InitStructure.SPI_CPHA      = SPI_CPHA_2Edge;
    SPI_InitStructure.SPI_NSS       = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
    SPI_InitStructure.SPI_FirstBit  = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 0;
    SPI_Init(SPI1, &SPI_InitStructure);
  
    SPI_Cmd(SPI1, ENABLE);
}

int sd_spi_config(void)
{
   
   
    _spi_gpio_init();
    _spi_config();
    
    return 0;
}

void set_sd_spi_cs_pin(
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱出名的狗腿子

你的鼓励就是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值