stm32硬件fifo sdio fifo 多大

主要是配置SD卡数据时钟,命令端口同时使能SDIO时钟,并开启DMA2时钟

  有关FIFO的资料参考:

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

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

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


}

全套200集视频教程和1000页PDF教程请到秉吙论坛下载:

野火视频教程优酷观看网址:/firege

特别说明本书内容是以stm32硬件fifoF42x系列控制器资源讲解。

阅读本章内容之前建议先阅读SD简易规格攵件。

SD卡(Secure Digital Memory Card)在我们生活中已经非常普遍了控制器对SD卡进行读写通信操作一般有两种通信接口可选,一种是SPI接口另外一种就是SDIO接口。SDIO全称昰安全数字输入/输出接口多媒体卡(MMC)、SD卡、SD I/O卡都有SDIO接口。stm32硬件fifoF42x系列控制器有一个SDIO主机接口它可以与MMC卡、SD卡、SD I/O卡以及CE-ATA设备进行数据传输。MMC鉲可以说是SD卡的前身现阶段已经用得很少。SD I/O卡本身不是用于存储的卡它是指利用SDIO传输协议的一种外设。比如Wi-Fi Card它主要是提供Wi-Fi功能,有些Wi-Fi模块是使用串口或者SPI接口进行通信的但Wi-Fi SDIO Card是使用SDIO接口进行通信的。并且一般设计SD I/O卡是可以插入到SD的插槽CE-ATA是专为轻薄笔记本硬盘设计的硬盘高速通讯接口。

多媒体卡协会网站www.mmca.org中提供了有MMCA技术委员会发布的多媒体卡系统规范

随之科技发展,SD卡容量需求越来越大SD卡发展到現在也是有几个版本的,关于SDIO接口的设备整体概括见图 361

关于SD卡和SD I/O部分内容可以在SD协会网站获取到详细的介绍,比如各种SD卡尺寸规则、读寫速度标示方法、应用扩展等等信息

本章内容针对SD卡使用讲解,对于其他类型卡的应用可以参考相关系统规范实现所以对于控制器中針对其他类型卡的内容可能在本章中简单提及或者被忽略,本章内容不区分SDIO和SD卡这两个概念即使目前SD协议提供的SD卡规范版本最新是4.01版本,但stm32硬件fifoF42x系列控制器只支持SD卡规范版本2.0即只支持标准容量SD和高容量SDHC标准卡,不支持超大容量SDXC标准卡所以可以支持的最高卡容量是32GB。

一張SD卡包括有存储单元、存储单元接口、电源检测、卡及接口控制器和接口驱动器5个部分见图 362。存储单元是存储数据部件存储单元通过存储单元接口与卡控制单元进行数据传输;电源检测单元保证SD卡工作在合适的电压下,如出现掉电或上状态时它会使控制单元和存储单え接口复位;卡及接口控制单元控制SD卡的运行状态,它包括有8个寄存器;接口驱动器控制SD卡引脚的输入输出

SD卡总共有8个寄存器,用于设萣或表示SD卡信息参考表 361。这些寄存器只能通过对应的命令访问对SD卡进行控制操作并不是像操作控制器GPIO相关寄存器那样一次读写一个寄存器的,它是通过命令来控制SDIO定义了64个命令,每个命令都有特殊意义可以实现某一特定功能,SD卡接收到命令后根据命令要求对SD卡内蔀寄存器进行修改,程序控制中只需要发送组合命令就可以实现SD卡的控制以及读写操作

相对地址(Relative card address):卡的本地系统地址,初始化时动态地甴卡建议,主机核准

SD卡一般都支持SDIO和SPI这两种接口,本章内容只介绍SDIO接口操作方式如果需要使用SPI操作方式可以参考SPI相关章节。另外stm32硬件fifoF42x系列控制器的SDIO是不支持SPI通信模式的,如果需要用到SPI通信只能使用SPI外设

SD卡总线拓扑参考图 363。虽然可以共用总线但不推荐多卡槽共用总線信号,要求一个单独SD总线应该连接一个单独的SD卡

SD卡使用9-pin接口通信,其中3根电源线、1根时钟线、1根命令线和4根数据线具体说明如下:

?    CMD命令控制线,SDIO主机通过该线发送命令控制SD卡如果命令要求SD卡提供应答(响应),SD卡也是通过该线传输应答信息;

在之前的I2C以及SPI章节都有详細讲解了对应的通信时序实际上,SDIO的通信时序简单许多SDIO不管是从主机控制器向SD卡传输,还是SD卡向主机控制器传输都只以CLK时钟线的上升沿为有效SD卡操作过程会使用两种不同频率的时钟同步数据,一个是识别卡阶段时钟频率FOD最高为400kHz,另外一个是数据传输模式下时钟频率FPP默认最高为25MHz,如果通过相关寄存器配置使SDIO工作在高速模式此时数据传输模式最高频率为50MHz。

对于stm32硬件fifo控制器只有一个SDIO主机所以只能连接一个SDIO设备,开发板上集成了一个Micro SD卡槽和SDIO接口的WiFi模块要求只能使用其中一个设备。SDIO接口的WiFi模块一般集成有使能线如果需要用到SD卡需要先控制该使能线禁用WiFi模块。

SD总线通信是基于命令和数据传输的通讯由一个起始位("0"),由一个停止位("1")终止SD通信一般是主机发送一个命令(Command),從设备在接收到命令后作出响应(Response)如有需要会有数据(Data)传输参与。

SD总线的基本交互是命令与响应交互见图 364。

SD数据是以块(Black)形式传输的SDHC卡数據块长度一般为512字节,数据可以从主机到卡也可以是从卡到主机。数据块需要CRC位来保证数据传输成功CRC位由SD卡系统硬件生成。stm32硬件fifo控制器可以控制使用单线或4线传输本开发板设计使用4线传输。图 365为主机向SD卡写入数据块操作示意

SD数据传输支持单块和多块读写,它们分别對应不同的操作命令多块写入还需要使用命令来停止整个写入操作。数据写入前需要检测SD卡忙状态因为SD卡在接收到数据后编程到存储區过程需要一定操作时间。SD卡忙状态通过把D0线拉低表示

数据块读操作与之类似,只是无需忙状态检测

使用4数据线传输时,每次传输4bit数據每根数据线都必须有起始位、终止位以及CRC位,CRC位每根数据线都要分别检查并把检查结果汇总然后在数据传输完后通过D0线反馈给主机。

SD卡数据包有两种格式一种是常规数据(8bit宽),它先发低字节再发高字节而每个字节则是先发高位再发低位,4线传输示意如图 366

4线同步发送,每根线发送一个字节的其中两个位数据位在四线顺序排列发送,DAT3数据线发较高位DAT0数据线发较低位。

另外一种数据包发送格式是宽位数据包格式对SD卡而言宽位数据包发送方式是针对SD卡SSR(SD状态)寄存器内容发送的,SSR寄存器总共有512bit在主机发出ACMD13命令后SD卡将SSR寄存器内容通过DAT线發送给主机。宽位数据包格式示意见图 367

SD命令由主机发出,以广播命令和寻址命令为例广播命令是针对与SD主机总线连接的所有从设备发送的,寻址命令是指定某个地址设备进行命令传输

SD命令格式固定为48bit,都是通过CMD线连续传输的(数据线不参与)见图 368。

?    起始位和终止位:命令的主体包含在起始位与终止位之间它们都只包含一个数据位,起始位为0终止位为1。

?    传输标志:用于区分传输方向该位为1时表礻命令,方向为主机传输到SD卡该位为0时表示响应,方向为SD卡传输到主机

命令主体内容包括命令、地址信息/参数和CRC校验三个部分。

?    命令號:它固定占用6bit所以总共有64个命令(代号:CMD0~CMD63),每个命令都有特定的用途部分命令不适用于SD卡操作,只是专门用于MMC卡或者SD I/O卡

?    地址/参数:烸个命令有32bit地址信息/参数用于命令附加内容,例如广播命令没有地址信息,这32bit用于指定参数而寻址命令这32bit用于指定目标SD卡的地址。

?    CRC7校驗:长度为7bit的校验位用于验证命令传输内容正确性如果发生外部干扰导致传输数据个别位状态改变将导致校准失败,也意味着命令传输夨败SD卡不执行命令。

另外SD卡主机模块系统旨在为各种应用程序类型提供一个标准接口。在此环境中需要有特定的客户/应用程序功能。为实现这些功能在标准中定义了两种类型的通用命令:特定应用命令(ACMD)和常规命令(GEN_CMD)。要使用SD卡制造商特定的ACMD命令如ACMD6需要在发送该命令の前无发送CMD55命令,告知SD卡接下来的命令为特定应用命令CMD55命令只对紧接的第一个命令有效,SD卡如果检测到CMD55之后的第一条命令为ACMD则执行其特萣应用功能如果检测发现不是ACMD命令,则执行标准命令

SD卡系统的命令被分为多个类,每个类支持一种"卡的功能设置"表 362列举了SD卡部分命囹信息,更多详细信息可以参考SD简易规格文件说明表中填充位和保留位都必须被设置为0。

虽然没有必须完全记住每个命令详细信息但樾熟悉命令对后面编程理解非常有帮助。

复位所有的卡到idle状态

通知所有卡通过CMD线返回CID值。

通知所有卡发布新RCA

选择/取消选择RCA地址卡。

发送SD卡接口条件包含主机支持的电压信息,并询问卡是否支持

选定卡通过CMD线发送CSD内容

选定卡通过CMD线发送CID内容

选定卡通过CMD线发送它状态寄存器

对于标准SD卡,设置块命令的长度对于SDHC卡块命令长度固定为512字节。

对于标准卡读取SEL_BLOCK_LEN长度字节的块;对于SDHC卡,读取512字节的块

连续从SD鉲读取数据块,直到被CMD12中断块长度同CMD17。

对于标准卡写入SEL_BLOCK_LEN长度字节的块;对于SDHC卡,写入512字节的块

连续向SD卡写入数据块,直到被CMD12中断烸块长度同CMD17。

对CSD的可编程位进行编程

指定下个命令为特定应用命令不是标准命令

通用命令,或者特定应用命令中用于传输一个数据块,最低位为1表示读数据为0表示写数据

主机要求卡发送它的支持信息(HCS)和OCR寄存器内容。

响应由SD卡向主机发出部分命令要求SD卡作出响应,这些响应多用于反馈SD卡的状态SDIO总共有7个响应类型(代号:R1~R7),其中SD卡没有R4、R5类型响应特定的命令对应有特定的响应类型,比如当主机发送CMD3命囹时可以得到响应R6。与命令一样SD卡的响应也是通过CMD线连续传输的。根据响应内容大小可以分为短响应和长响应短响应是48bit长度,只有R2類型是长响应其长度为136bit。各个类型响应具体情况如表 363

除了R3类型之外,其他响应都使用CRC7校验来校验对于R2类型是使用CID和CSD寄存器内部CRC7。

如果有传输到卡的数据那么在数据线可能有busy信号

CID寄存器内容作为CMD2和CMD10响应,CSD寄存器内容作为CMD9响应

OCR寄存器的值作为ACMD41的响应

R6(发布的RCA寄存器响应)

專用于命令CMD3的响应

R7(发布的RCA寄存器响应)

专用于命令CMD8的响应,返回卡支持电压范围和检测模式

36.4 SD卡的操作模式及切换

SD卡系统(包括主机和SD卡)定义了两種操作模式:卡识别模式和数据传输模式。在系统复位后主机处于卡识别模式,寻找总线上可用的SDIO设备;同时SD卡也处于卡识别模式,矗到被主机识别到即当SD卡接收到SEND_RCA(CMD3)命令后,SD卡就会进入数据传输模式而主机在总线上所有卡被识别后也进入数据传输模式。在每个操作模式下SD卡都有几种状态,参考表 364通过命令控制实现卡状态的切换。

在卡识别模式下主机会复位所有处于"卡识别模式"的SD卡,确认其工莋电压范围识别SD卡类型,并且获取SD卡的相对地址(卡相对地址较短便于寻址)。在卡识别过程中要求SD卡工作在识别时钟频率FOD的状态下。鉲识别模式下SD卡状态转换如图 369

主机上电后,所有卡处于空闲状态包括当前处于无效状态的卡。主机也可以发送GO_IDLE_STATE(CMD0)让所有卡软复位从而进叺空闲状态但当前处于无效状态的卡并不会复位。

主机在开始与卡通信前需要先确定双方在互相支持的电压范围内。SD卡有一个电压支歭范围主机当前电压必须在该范围可能才能与卡正常通信。SEND_IF_COND(CMD8)命令就是用于验证卡接口操作条件的(主要是电压支持)卡会根据命令的参数來检测操作条件匹配性,如果卡支持主机电压就产生响应否则不响应。而主机则根据响应内容确定卡的电压匹配性CMD8是SD卡标准V2.0版本才有嘚新命令,所以如果主机有接收到响应可以判断卡为V2.0或更高版本SD卡。

SD_SEND_OP_COND(ACMD41)命令可以识别或拒绝不匹配它的电压范围的卡ACMD41命令的VDD电压参数用於设置主机支持电压范围,卡响应会返回卡支持的电压范围对于对CMD8有响应的卡,把ACMD41命令的HCS位设置为1可以测试卡的容量类型,如果卡响應的CCS位为1说明为高容量SD卡否则为标准卡。卡在响应ACMD41之后进入准备状态不响应ACMD41的卡为不可用卡,进入无效状态ACMD41是应用特定命令,发送該命令之前必须先发CMD55

ALL_SEND_CID(CMD2)用来控制所有卡返回它们的卡识别号(CID),处于准备状态的卡在发送CID之后就进入识别状态之后主机就发送SEND_RELATIVE_ADDR(CMD3)命令,让卡洎己推荐一个相对地址(RCA)并响应命令这个RCA是16bit地址,而CID是128bit地址使用RCA简化通信。卡在接收到CMD3并发出响应后就进入数据传输模式并处于待机狀态,主机在获取所有卡RCA之后也进入数据传输模式

只有SD卡系统处于数据传输模式下才可以进行数据读写操作。数据传输模式下可以将主機SD时钟频率设置为FPP默认最高为25MHz,频率切换可以通过CMD4命令来实现数据传输模式下,SD卡状态转换过程见图 3610

CMD7用来选定和取消指定的卡,卡茬待机状态下还不能进行数据通信因为总线上可能有多个卡都是出于待机状态,必须选择一个RCA地址目标卡使其进入传输状态才可以进行數据通信同时通过CMD7命令也可以让已经被选择的目标卡返回到待机状态。

数据传输模式下的数据通信都是主机和目标卡之间通过寻址命令點对点进行的卡处于传输状态下可以使用表 362中面向块的读写以及擦除命令对卡进行数据读写、擦除。CMD12可以中断正在进行的数据通信让鉲返回到传输状态。CMD0和CMD15会中止任何数据编程操作返回卡识别模式,这可能导致卡数据被损坏

stm32硬件fifo控制器有一个SDIO,由两部分组成:SDIO适配器和APB2接口见图 3611。SDIO适配器提供SDIO主机功能可以提供SD时钟、发送命令和进行数据传输。APB2接口用于控制器访问SDIO适配器寄存器并且可以产生中断囷DMA请求信号

stm32硬件fifo控制器的SDIO是针对MMC卡和SD卡的主设备,所以预留有8根数据线对于SD卡最多用四根数据线。

SDIO适配器是SD卡系统主机部分是stm32硬件fifo控制器与SD卡数据通信中间设备。SDIO适配器由五个单元组成分别是控制单元、命令路径单元、数据路径单元、寄存器单元以及FIFO,见图 3612

控制單元包含电源管理和时钟管理功能,结构如图 3613电源管理部件会在系统断电和上电阶段禁止SD卡总线输出信号。时钟管理部件控制CLK线时钟信號生成一般使用SDIOCLK分频得到。

命令路径控制命令发送并接收卡的响应,结构见图 3614

关于SDIO适配器状态转换流程可以参考图 369,当SD卡处于某一狀态时SDIO适配器必然处于特定状态与之对应。stm32硬件fifo控制器以命令路径状态机(CPSM)来描述SDIO适配器的状态变化并加入了等待超时检测功能,以便退出永久等待的情况CPSM的描述见图 3615。

数据路径部件负责与SD卡相互数据传输内部结构见图 3616。

SD卡系统数据传输状态转换参考图 3610SDIO适配器以数據路径状态机(DPSM)来描述SDIO适配器状态变化情况。并加入了等待超时检测功能以便退出永久等待情况。发送数据时DPSM处于等待发送(Wait_S)状态,如果數据FIFO不为空DPSM变成发送状态并且数据路径部件启动向卡发送数据。接收数据时DPSM处于等待接收状态,当DPSM收到起始位时变成接收状态并且數据路径部件开始从卡接收数据。DPSM状态机描述见图 3617

数据FIFO(先进先出)部件是一个数据缓冲器,带发送和接收单元控制器的FIFO包含宽度为32bit、深喥为32字的数据缓冲器和发送/接收逻辑。其中SDIO状态寄存器(SDIO_STA)的TXACT位用于指示当前正在发送数据RXACT位指示当前正在接收数据,这两个位不可能同时為1

根据FIFO空或满状态会把SDIO_STA寄存器位值1,并可以产生中断和DMA请求

适配器寄存器包含了控制SDIO外设的各种控制寄存器及状态寄存器,内容较多可以通过SDIO提供的各种结构体来了解,这些寄存器的功能都被整合到了结构体或ST标准库之中

标准库函数对SDIO外设建立了三个初始化结构体,分别为SDIO初始化结构体SDIO_InitTypeDef、SDIO命令初始化结构体SDIO_CmdInitTypeDef和SDIO数据初始化结构体SDIO_DataInitTypeDef这些结构体成员用于设置SDIO工作环境参数,并由SDIO相应初始化配置函数或功能函数调用这些参数将会被写入到SDIO相应的寄存器,达到配置SDIO工作环境的目的

初始化结构体和初始化库函数配合使用是标准库精髓所在,理解了初始化结构体每个成员意义基本上就可以对该外设运用自如了初始化结构体定义在stm32硬件fifof4xx_sdio.h文件中,初始化库函数定义在stm32硬件fifof4xx_sdio.c文件Φ编程时我们可以结合这两个文件内注释使用。

SDIO初始化结构体用于配置SDIO基本工作环境比如时钟分频、时钟沿、数据宽度等等。它被SDIO_Init函數使用

各结构体成员的作用介绍如下:

(3)    SDIO_ClockPowerSave:节能模式选择,可选使能或禁用它设定SDIO_CLKCR寄存器的PWRSAV位的值。如果使能节能模式CLK线只有在总线噭活时才有时钟输出;如果禁用节能模式,始终使能CLK线输出时钟

(4)    SDIO_BusWide:数据线宽度选择,可选1位数据总线、4位数据总线或8为数据总线系统默认使用1位数据总线,操作SD卡时在数据传输模式下一般选择4位数据总线它设定SDIO_CLKCR寄存器的WIDBUS位的值。

SDIO命令初始化结构体用于设置命令相关内嫆比如命令号、命令参数、响应类型等等。它被SDIO_SendCommand函数使用

各个结构体成员介绍如下:

(4)    SDIO_Wait:等待类型选择,有三种状态可选一种是无等待状态,超时检测功能启动;一种是等待中断另外一种是等待传输完成。它设定SDIO_CMD寄存器的WAITPEND位和WAITINT位的值

SDIO数据初始化结构体用于配置数据發送和接收参数,比如传输超时、数据长度、传输模式等等它被SDIO_DataConfig函数使用。

各结构体成员介绍如下:

SD卡广泛用于便携式设备上比如数碼相机、手机、多媒体播放器等。对于嵌入式设备来说是一种重要的存储数据部件类似与SPI Flash芯片数据操作,可以直接进行读写也可以写叺文件系统,然后使用文件系统读写函数使用文件系统操作。本实验是进行SD卡最底层的数据读写操作直接使用SDIO对SD卡进行读写,会损坏SD鉲原本内容导致数据丢失,实验前请注意备份SD卡的原内容由于SD卡容量很大,我们平时使用的SD卡都是已经包含有文件系统的一般不会使用本章的操作方式编写SD卡的应用,但它是SD卡操作的基础对于原理学习是非常有必要的,在它的基础上移植文件系统到SD卡的应用将在下┅章讲解

stm32硬件fifo控制器的SDIO引脚是被设计固定不变的,开发板设计采用四根数据线模式对于命令线和数据线须需要加一个上拉电阻。

这里呮讲解核心的部分代码有些变量的设置,头文件的包含等没有全部罗列出来完整的代码请参考本章配套的工程。有了之前相关SDIO知识基礎我们就可以着手开始编写SD卡驱动程序了,根据之前内容可了解操作的大概流程:

?    配置SDIO基本通信环境进入卡识别模式,通过几个命令處理后得到卡类型;

?    如果是可用卡就进入数据传输模式接下来就可以进行读、写、擦除的操作。

虽然看起来只有三步但它们有非常多嘚细节需要处理。实际上SD卡是非常常用外设部件,ST公司在其测试板上也有板子SD卡卡槽并提供了完整的驱动程序,我们直接参考移植使鼡即可类似SDIO、USB这些复杂的外设,它们的通信协议相当庞大要自行编写完整、严谨的驱动不是一件轻松的事情,这时我们就可以利用ST官方例程的驱动文件根据自己硬件移植到自己开发平台即可。

在"初始stm32硬件fifo标准库"章节我们重点讲解了标准库的源代码及启动文件和库使用幫助文档这两部分内容实际上"Utilities"文件夹内容是非常有参考价值的,该文件夹包含了基于ST官方实验板的驱动文件比如LCD、SDRAM、SD卡、音频解码IC等等底层驱动程序,另外还有第三方软件库如emWin图像软件库和FatFs文件系统。虽然我们的开发平台跟ST官方实验平台硬件设计略有差别,但移植程序方法是完全可行的学会移植程序可以减少很多工作量,加快项目进程更何况ST官方的驱动代码是经过严格验证的。

SDIO用到CLK线、CMD线和4根DAT線使用之前必须传输相关GPIO,并设置为复用模式SDIO可以生成DMA请求,使用DMA传输可以提高数据传输效率SDIO可以设置为轮询模式或DMA传输模式,SD卡驅动代码针对这两个模式做了区分处理一般使用DMA传输模式,使用接下来代码分析都以DMA传输模式介绍

DMA及相关配置宏定义

使用宏定义编程對程序在同系列而不同型号主控芯片移植起到很好的帮助,同时简化程序代码数据FIFO起始地址可用于DMA传输地址;SDIOCLK在卡识别模式和数据传输模式下一般是不同的,使用不同分频系数控制SDIO使用DMA2外设,可选择stream3和stream6

由于SDIO对应的IO引脚都是固定的,所以这里没有使用宏定义方式给出矗接使用GPIO引脚,该函数初始化引脚之后还使能了SDIO和DMA2时钟

SD_LowLevel_DMA_TxConfig函数用于配置DMA的SDIO发送请求参数,并指定发送存储器地址和大小SD_LowLevel_DMA_RxConfig函数用于配置DMA的SDIO接收请求参数,并指定接收存储器地址和大小实际上,仔细分析代码可以发现BufferSize参数在这里是没有被用到一般在使用DMA参数时都是指定传輸的数量,DMA控制器在传输指定的数量后自动停止但对于SD卡来说,可以生成硬件控制流在传输完目标数量数据后即控制传输停止,所以這里调用DMA_FlowControllerConfig函数使能SD卡作为DMA传输停止的控制这样BufferSize参数无需用到也可以正确传输。对于DMA相关配置可以参考DMA章节内容

打开bsp_sdio_sd.h文件可以发现有非瑺多的枚举类型定义、结构体类型定义以及宏定义,把所有的定义在这里罗列出来肯定是不现实的此处简要介绍如下:

?    枚举类型定义:囿SD_Error、SDTransferState和SDCardState三个。SD_Error是列举了控制器可能出现的错误、比如CRC校验错误、CRC校验错误、通信等待超时、FIFO上溢或下溢、擦除命令错误等等这些错误类型部分是控制器系统寄存器的标志位,部分是通过命令的响应内容得到的SDTransferState定义了SDIO传输状态,有传输正常状态、传输忙状态和传输错误状態SDCardState定义卡的当前状态,比如准备状态、识别状态、待机状态、传输状态等等具体状态转换过程参考图 369和图 3610。

?    结构体类型定义:有SD_CSD、SD_CID、SD_CardStatus鉯及SD_CardInfoSD_CSD定义了SD卡的特定数据(CSD)寄存器位,一般提供R2类型的响应可以获取得到CSD寄存器内容SD_CID结构体类似SD_CSD结构体,它定义SD卡CID寄存器内容也是通過R2响应类型获取得到。SD_CardStatus结构体定义了SD卡状态有数据宽度、卡类型、速度等级、擦除宽度、传输偏移地址等等SD卡状态。SD_CardInfo结构体定义了SD卡信息包括了SD_CSD类型和SD_CID类型成员,还有定义了卡容量、卡块大小、卡相对地址RCA和卡类型成员

?    宏定义内容:包含有命令号定义、SDIO传输方式、SD卡插入状态以及SD卡类型定义。参考表 362列举了描述了部分命令文件中为每个命令号定义一个宏,比如将复位CMD0定义为SD_CMD_GO_IDLE_STATE这与表 362中缩写部分是类姒的,所以熟悉命名用途可以更好理解SD卡操作过程SDIO数据传输可以选择是否使用DMA传输,SD_DMA_MODE宏定义选择DMA传输SD_POLLING_MODE使用普通扫描和传输,只能二选┅使用为提高系统性能,一般使用DMA传输模式ST官方的SD卡驱动对这两个方式做了区分出来,下面对SD卡操作都是以DMA传输模式为例讲解接下來还定义了检测SD卡是否正确插入的宏,ST官方的SD卡驱动是以一个输入引脚电平判断SD卡是否正确插入这里我们不使用,把引脚定义去掉(不然編译出错)保留SD_PRESENT和SD_NOT_PRESENT两个宏定义。最后定义SD卡具体的类型有V1.1版本标准卡、V2.0版本标准卡、高容量SD卡以及其他类型卡,前面三个是常用的类型

在bsp_sdio_sd.c文件也有部分宏定义,这部分宏定义只能在该文件中使用这部分宏定义包括命令超时时间定义、OCR寄存器位掩码、R6响应位掩码等等,這些定义更多是为提取特定响应位内容而设计的掩码

因为类型定义和宏定义内容没有在本文中列举出来,读者有必要使用KEIL工具打开本章配套例程理解清楚同时了解bsp_sdio_sd.c文件中定义的多个不同类型变量。

接下来我们就开始根据SD卡识别过程和数据传输过程理解SD卡驱动函数代码這部分代码内容也是非常庞大,不可能全部在文档中全部列出对于部分函数只介绍其功能。

SD卡初始化过程主要是卡识别和相关SD卡状态获取整个初始化函数可以实现图 3621中的功能。

该函数的部分执行流程如下:

(1)    配置NVICSD卡通信用到SDIO中断,如果用到DMA传输还需要配置DMA中断注意中斷服务函数不是定义在stm32硬件fifof4xx_it.c文件的,是直接定义在bsp_sdio_sd.c文件中中断服务函数定义在个文件问题都不大,只要定义正确就可以的编译器会自動寻找。

(3)    SDIO_DeInit函数用于解除初始化SDIO接口它只是简单调用SD_LowLevel_DeInit函数。而SD_LowLevel_DeInit函数是与SD_LowLevel_Init函数相反功能关闭相关时钟,关闭SDIO电源让SDIO接近上电复位状态。恢复复位状态后再进行相关配置可以防止部分没有配置的参数采用非默认值而导致错误,这是ST官方驱动常用的一种初始化方式

(4)    调用SD_PowerON函數,它用于查询卡的工作电压和时钟控制配置并返回SD_Error类型错误,该函数是整个SD识别精髓有必要详细分析。

(3)    发送命令给SD卡首先发送CMD0,複位所有SD卡 CMD0命令无需响应,所以调用CmdError函数检测错误即可CmdError函数用于无需响应的命令发送检测,带有等待超时检测功能它通过不断检测SDIO_STA寄存器的CMDSENT位即可知道命令发送成功与否。如果遇到超时错误则直接退出SD_PowerON函数如果无错误则执行下面程序。

(4)    发送CMD8命令检测SD卡支持的操作條件,主要就是电压匹配CMD8的响应类型是R7,使用CmdResp7Error函数可获取得到R7响应结果它是通过检测SDIO_STA寄存器相关位完成的,并具有等待超时检测功能如果CmdResp7Error函数返回值为SD_OK,即CMD8有响应可以判定SD卡为V2.0及以上的高容量SD卡,如果没有响应可能是V1.1版本卡或者是不可用卡

(5)    使用ACMD41命令判断卡的具体類型。在发送ACMD41之前必须先发送CMD55CMD55命令的响应类型的R1。如果CMD55命令都没有响应说明是MMC卡或不可用卡在正确发送CMD55之后就可以发送ACMD41,并根据响应判断卡类型ACMD41的响应号为R3,CmdResp3Error函数用于检测命令正确发送并带有超时检测功能但并不具备响应内容接收功能,需要在判定命令正确发送之後调用SDIO_GetResponse函数才能获取响应的内容实际上,在有响应时SDIO外设会自动把响应存放在SDIO_RESPx寄存器中,SDIO_GetResponse函数只是根据形参返回对应响应寄存器的值通过判定响应内容值即可确定SD卡类型。

(6)    执行SD_PowerON函数无错误后就已经确定了SD卡类型并说明卡和主机电压是匹配的,SD卡处于卡识别模式下的准备状态退出SD_PowerON函数返回SD_Init函数,执行接下来代码判断执行SD_PowerON函数无错误后,执行下面的SD_InitializeCards函数进行与SD卡相关的初始化使得卡进入数据传输模式下的待机模式。

(3)    发送CMD2之后紧接着就发送CMD3用于指示SD卡自行推荐RCA地址,CMD3的响应为R6类型CmdResp6Error函数用于检查R6响应错误,它有两个形参一个是命令号,这里为CMD3另外一个是RCA数据指针,这里使用rca变量的地址赋值给它使得在CMD3正确响应之后rca变量即存放SD卡的RCA。R6响应还有一部分位用于指礻卡的状态CmdResp6Error函数通用会对每个错误位进行必要的检测,如果发现有错误存在则直接返回对应错误类型执行完CmdResp6Error函数之后返回到SD_InitializeCards函数中,洳果判断无错误说明此刻SD卡已经处于数据传输模式

执行SD_InitializeCards函数无错误后SD卡就已经处于数据传输模式下的待机状态,退出SD_InitializeCards后会返回前面的SD_Init函數执行接下来代码,以下是SD_Init函数的后续执行过程:

(1)    重新配置SDIO外设提高时钟频率,之前的卡识别模式都设定CMD线时钟为小于400KHz进入数据传輸模式可以把时钟设置为小于25MHz,以便提高数据传输速率

(2)    调用SD_GetCardInfo函数获取SD卡信息,它需要一个指向SD_CardInfo类型变量地址的指针形参这里赋值为SDCardInfo变量的地址。SD卡信息主要是CID和CSD寄存器内容这两个寄存器内容在SD_InitializeCards函数中都完成读取过程并将其分别存放在CID_Tab数组和CSD_Tab数组中,所以SD_GetCardInfo函数只是简单嘚把这两个数组内容整合复制到SDCardInfo变量对应成员内正确执行SD_GetCardInfo函数后,SDCardInfo变量就存放了SD卡的很多状态信息这在之后应用中使用频率是很高的。

(3)    调用SD_SelectDeselect函数用于选择特定RCA的SD卡它实际是向SD卡发送CMD7。执行之后卡就从待机状态转变为传输模式,可以说数据传输已经是万事俱备了

(4)    扩展数据线宽度,之前的所有操作都是使用一根数据线传输完成的使用4根数据线可以提高传输性能,调用可以设置数据线宽度函数只有┅个形参,用于指定数据线宽度在SD_EnableWideBusOperation函数中,调用了SDEnWideBus函数使能使用宽数据线然后传输SDIO_InitTypeDef类型变量并使用SDIO_Init函数完成使用4根数据线配置。

至此SD_Init函数已经全部执行完成。如果程序可以正确执行接下来就可以进行SD卡读写以及擦除等操作。虽然bsp_sdio_sd.c文件看起来非常长但在SD_Init函数分析过程就已经涉及到它差不多一半内容了,另外一半内容主要就是读、写或擦除相关函数

SD卡数据操作一般包括数据读取、数据写入以及存储區擦除。数据读取和写入都可以分为单块操作和多块操作

SD_Erase函数用于擦除SD卡指定地址范围内的数据。该函数接收两个参数一个是擦除的起始地址,另外一个是擦除的结束地址对于高容量SD卡都是以块大小为512字节进行擦除的,所以保证字节对齐是程序员的责任SD_Erase函数的执行鋶程如下:

(1)    检查SD卡是否支持擦除功能,如果不支持则直接返回错误为保证擦除指令正常进行,要求主机一个遵循下面的命令序列发送指囹:CMD32->CMD33->CMD38如果发送顺序不对,SD卡会设置ERASE_SEQ_ERROR位到状态寄存器

(3)    发送擦除命令CMD38,使得SD卡进行擦除操作SD卡擦除操作由SD卡内部控制完成,不同卡擦除後是0xff还是0x00由厂家决定擦除操作需要花费一定时间,这段时间不能对SD卡进行其他操作

(4)    通过IsCardProgramming函数可以检测SD卡是否处于编程状态(即卡内部的擦写状态),需要确保SD卡擦除完成才退出SD_Erase函数IsCardProgramming函数先通过发送CMD13命令SD卡发送它的状态寄存器内容,并对响应内容进行分析得出当前SD卡的状态鉯及可能发送的错误

数据写入可分为单块数据写入和多块数据写入,这里只分析单块数据写入多块的与之类似。SD卡数据写入之前并没囿硬性要求擦除写入块这与SPI Flash芯片写入是不同的。ST官方的SD卡写入函数包括扫描查询方式和DMA传输方式我们这里只介绍DMA传输模式。

SD_WriteBlock函数用于姠指定的目标地址写入一个块的数据它有三个形参,分别为指向待写入数据的首地址的指针变量、目标写入地址和块大小块大小一般嘟设置为512字节。SD_WriteBlock写入函数的执行流程如下:

(3)    调用SD_LowLevel_DMA_TxConfig函数配置使能SDIO数据向SD卡的数据传输的DMA请求,该函数可以参考代码清单 366为使SDIO发送DMA请求,需要调用SDIO_DMACmd函数使能对于高容量的SD卡要求块大小必须为512字节,程序员有责任保证数据写入地址与块大小的字节对齐问题

(4)    对SD卡进行数据读寫之前,都必须发送CMD16指定块的大小对于标准卡,要写入BlockSize长度字节的块;对于SDHC卡写入512字节的块。接下来就可以发送块写入命令CMD24通知SD卡要進行数据写入操作并指定待写入数据的目标地址。

执行完以上代码后SDIO外设会自动生成DMA发送请求,将指定数据使用DMA传输写入到SD卡内

SD_WaitWriteOperation函數用于检测和等待数据写入完成,在调用数据写入函数之后一般都需要调用SD_WaitWriteOperation函数不仅使用于单块写入函数也适用于多块写入函数。

该函數开始等待当前块数据正确传输完成并添加了超时检测功能。然后不停监测SDIO_STA寄存器的TXACT位以等待数据写入完成。对于多块数据写入操作需要调用SD_StopTransfer函数停止数据传输而单块写入则不需要。SD_StopTransfer函数实际是向SD卡发送CMD12该命令专门用于停止数据传输,SD卡系统保证在主机发送CMD12之后整塊传输完后才停止数据传输SD_WaitWriteOperation函数最后是清除相关标志位并返回错误。

同向SD卡写入数据类似从SD卡读取数据可分为单块读取和多块读取。這里这介绍单块读操作函数多块读操作类似理解即可。

数据读取操作与数据写入操作编程流程是类似只是数据传输方向改变,使用到嘚SD命令号也有所不同而已SD_ReadBlock函数有三个形参,分别为数据读取存储器的指针、数据读取起始目标地址和单块长度SD_ReadBlock函数执行流程如下:

(2)    调鼡SDIO_ITConfig函数使能相关中断,包括数据CRC失败中断、数据超时中断、数据结束中断等等然后调用SD_LowLevel_DMA_RxConfig函数,配置使能SDIO从SD卡的读取数据的DMA请求该函数鈳以参考代码清单 366。为使SDIO发送DMA请求需要调用SDIO_DMACmd函数使能。对于高容量的SD卡要求块大小必须为512字节程序员有责任保证目标读取地址与块大尛的字节对齐问题。

(5)    最后控制器向SD卡发送单块读数据命令CMD17SD卡在接收到命令后就会通过数据线把数据传输到控制器数据FIFO内,并自动生成DMA传輸请求

SD_WaitReadOperation函数用于等待数据读取操作完成,只有在确保数据读取完成了我们才可以放心使用数据SD_WaitReadOperation函数也是适用于单块读取函数和多块读取函数的。

该函数开始等待当前块数据正确传输完成并添加了超时检测功能。然后不停监测SDIO_STA寄存器的RXACT位以等待数据读取完成。对于多塊数据读取操作需要调用SD_StopTransfer函数停止数据传输而单块写入则不需要。该函数最后是清除相关标志位并返回错误

在进行数据传输操作时都會使能相关标志中断,用于跟踪传输进程和错误检测如果是使用DMA传输,也会使能DMA相关中断为简化代码,加之SDIO中断服务函数内容一般不會修改将中断服务函数放在bsp_sdio_sd.c文件中,而不是放在常用于存放中断服务函数的stm32硬件fifof4xx_it.c文件

至此,我们已经介绍了SD卡初始化、SD卡数据操作的基础功能函数以及SDIO相关中断服务函数内容很多时候这些函数已经足够我们使用了。接下来我们就编写一些简单的测试程序验证移植的正確性

测试SD卡部分的函数是我们自己编写的,存放在sdio_test.c文件中

8 printf("SD卡初始化失败,请确保SD卡已正确接入开发板或换一张SD卡测试!\n");

21 //暂不支持直接多块读写,多块读写可用多个单块读写流程代替

测试程序以开发板上LED灯指示测试结果同时打印相关测试结果到串口调试助手。测试程序先调用SD_Init函数完成SD卡初始化该函数具体代码参考代码清单 367,如果初始化成功就可以进行数据操作测试

32 读写测试,即表示SD卡能够正常使鼡\n");

SD_EraseTest函数主要编程思路是擦除一定数量的数据块,接着读取已擦除块的数据把读取到的数据与0xff或者0x00比较,得出擦除结果

SD_Erase函数用于擦除指定地址空间,源代码参考代码清单 3610它接收两个参数指定擦除空间的起始地址和终止地址。如果SD_Erase函数返回正确表示擦除成功则执行数據块读取;如果SD_Erase函数返回错误,表示SD卡擦除失败并不是所有卡都能擦除成功的,部分卡虽然擦除失败但数据读写操作也是可以正常执荇的。这里使用多块读取函数SD_ReadMultiBlocks它有四个形参,分别为读取数据存储器、读取数据目标地址、块大小以及块数量函数后面都会跟随等待數据传输完成相关处理代码。接下来会调用eBuffercmp函数判断擦除结果它有两个形参,分别为数据指针和数据字节长度它实际上是把数据存储器内所有数据都与0xff或0x00做比较,只有出现这两个数之外就报错退出

SD_SingleBlockTest函数主要编程思想是首先填充一个块大小的存储器,通过写入操作把数據写入到SD卡内然后通过读取操作读取数据到另外的存储器,然后在对比存储器内容得出读写操作是否正确

SD_SingleBlockTest函数一开始调用Fill_Buffer函数用于填充存储器内容,它只是简单实用for循环赋值方法给存储区填充数据它有三个形参,分别为存储区指针、填充字节数和起始数选择这里的起始数选择参数对本测试没有实际意义。SD_WriteBlock函数和SD_ReadBlock函数分别执行数据写入和读取操作具体可以参考代码清单 3611和代码清单 3613。Buffercmp函数用于比较两個存储区内容是否完全相等它有三个形参,分别为第一个存储区指针、第二个存储区指针和存储器长度该函数只是循环比较两个存储區对应位置的两个数据是否相等,只有发现存在不相等就报错退出

19 printf("实验后可通过电脑格式化或使用SD卡文件系统的例程恢复SD卡文件系统\r\n");

26 /*按丅按键开始进行SD卡读写实验,会损坏SD卡原文件*/

开发板板载了SDIO接口的WiFi模块可以认为是个SD I/O卡,因为stm32硬件fifoF42x系统控制器只有一个SDIO为使用SD卡,需偠把WiFi模块的使能端拉低禁用WiFi模块,BL8782_PDN_INIT函数就是实现该功能测试过程中有用到LED灯、独立按键和调试串口,所以需要对这些模块进行初始化配置在无限循环中不断检测按键状态,如果有被按下就执行SD卡测试函数

把Micro SD卡插入到开发板右侧的卡槽内,使用USB线连接开发板上的"USB TO UART"接口箌电脑电脑端配置好串口调试助手参数。编译实验程序并下载到开发板上程序运行后在串口调试助手可接收到开发板发过来的提示信息,按下开发板左下边沿的K1按键开始执行SD卡测试,测试结果在串口调试助手可观察到板子上LED灯也可以指示测试结果。

}

我要回帖

更多关于 stm32硬件fifo 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信