花了几天写了SD卡裸机驱动,现在还不完善,只支持4G以内的卡,以后再加上;现在经过修改可以写入数据了,亲测没问题.
S3C6410_SDIO.C
#include "s3c6410_system.h" #include "s3c6410_sdio.h" /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //配置 //块大小寄存器(0通道)BLKSIZE0 #define BLKSIZE0_BLKSIZE 0x0200 //块大小为512字节 //传输模式寄存器(0通道)TRNMOD0 #define TRNMOD0_CCSCON 0 //正常模式 #define TRNMOD0_MUL1SIN0 (0 << 5) //默认为单区段操作模式 #define TRNMOD0_RD1WT0 (1 << 4) //默认为读操作模式 #define TRNMOD0_ENACMD12 (0 << 2) //自动CMD12禁止,多区段操作完成后主机自动发出停止命令 #define TRNMOD0_ENBLKCNT (0 << 1) //块计数器无效 #define TRNMOD0_ENDMA (0 << 0) //DMA无效 //主机控制寄存器(0通道)HOSTCTL0 #define HOSTCTL0_WIDE8 (0 << 5) //这个为宽度被位1指定 (数据传输宽度) #define HOSTCTL0_DMASEL (0 << 3) //SDMA #define HOSTCTL0_OUTEDGEINV (0 << 2) //时钟上升沿沿数据有效 //这个寄存器有歧义,不知道到底是干啥用的 #define HOSTCTL0_WIDE4 (0 << 4) //数据传输宽度。1BIT模式 //电源控制寄存器(0通道)PWRCON0 #define PWRCON0_SELPWRLVL (7 << 1) //3.3V电源模式 #define PWRCON0_PWRON (1 << 0) //电源打开 //容限寄存器(0 通道)CAPAREG0 #define CAPAREG0_V18 (1 << 26) //电压支持1.8V #define CAPAREG0_V30 (0 << 25) //电压不支持3v #define CAPAREG0_V33 (1 << 24) //电压支持3.3V #define CAPAREG0_SUSRES (1 << 23) //支持暂停/恢复操作 #define CAPAREG0_DMA (1 << 22) //支持DMA #define CAPAREG0_HSPD (1 << 21) //支持高速模式 #define CAPAREG0_ADMA2 (0 << 19) //不支持DMA2 #define CAPAREG0_MAXBLKLEN (0 << 16) //最大块大小为512B #define CAPAREG0_BASECLK (25 << 8) //SD基础始终25MHz #define CAPAREG0_TOUTUNIT (0 << 7) //超时时钟单位KHZ #define CAPAREG0_TOUTCLK (10 << 0) //超时时钟频率为10KHZ //最大电流容限寄存器(0 通道)MAXCURR0 #define MAXCURR0_MAXCURR18 (10 << 16) //对于1.8V,最大电流为40MA #define MAXCURR0_MAXCURR30 (10 << 8) //对于3.0V,最大电流为40MA #define MAXCURR0_MAXCURR33 (10 << 0) //对于3.3V,最大电流为40MA //控制寄存器2 CONTROL2_0 #define CONTROL2_0_ENSTAASYNCCLR (0 << 31) //该位可以使正常和错误中断的异步明确启用状态位 #define CONTROL2_0_ENCMDCNFMSK (0 << 30) //不屏蔽指令冲突 #define CONTROL2_0_CDINVRXD3 (0 << 29) //卡检测信号倒置对于RX_DAT[3]。禁止 #define CONTROL2_0_SELCARDOUT (0 << 28) //卡移除条件是“无卡插入” 状态。 #define CONTROL2_0_FLTCLKSEL (8 << 24) //滤波器时钟 (iFLTCLK) 选择。 #define CONTROL2_0_ENFBCLKTX (0 << 15) //反馈时钟禁止,对于发送数据时钟 #define CONTROL2_0_ENFBCLKRX (0 << 14) //反馈时钟禁止,对于接收数据时钟 #define CONTROL2_0_SDCDSEL (0 << 13) //nSDCD 用于SD 卡检测信号 #define CONTROL2_0_SDSIGPC (0 << 12) //同步控制输出有效信号 #define CONTROL2_0_ENBUSYCHKTXSTART (0 << 11) //发送数据启动状态前忙碌状态检测。 #define CONTROL2_0_DFCNT (0 << 9) //反跳滤波器计数16 iSDCLK #define CONTROL2_0_ENCLKOUTHOLD (1 << 8) //SDCLK 操作有效。 #define CONTROL2_0_RWAITMODE (0 << 7) //主机控制器释放读等待状态(自动) #define CONTROL2_0_DISBUFRD (0 << 6) //正常模式,用0x20 寄存器使用者可以读缓冲区(FIFO)数据 //HCLK = 128MHZ EPLL = 24MHZ #define CONTROL2_0_SELBASECLK (2 << 4) //基础时钟源选择。00 或01 = HCLK,10 = EPLL 输出时钟(来自系统)11 = 外部时钟源(XTI 或XEXTCLk) #define CONTROL2_0_PWRSYNC (0 << 3) //不同步,控制输入有效信号(指令,数据) #define CONTROL2_0_ENCLKOUTMSKCON (0 << 1) //当卡插入被清除时,SDCLK 输出时钟屏蔽。当处于无卡状态时,设置该区域为高位来停止SDCLK。 #define CONTROL2_0_HWINITFIN (1 << 0) //SD 主机控制器硬件初始化完成。 //时钟控制寄存器(0 通道)CLKCON0 #define CLKCON0_SELFREQ (0x80 << 8) //SDCLK频率最低 #define CLKCON0_ENSDCLK (1 << 2) //SD 时钟启动。 #define CLKCON0_ENINTCLK (1 << 0) //中断时钟启动。 //超时控制寄存器(0 通道)TIMEOUTCON0 /******************************************************************************* * Function Name : SDIO_DeInit * Description : Deinitializes the SDIO peripheral registers to their default * reset values. * Input : None * Output : None * Return : None *******************************************************************************/ void SDIO_DeInit(void) { //初始化硬件IO rGPGCON = 0x2222222; //初始化IO为SDIO模式 rGPGPUD = 0; //禁止上下拉 //时钟控制寄存器配置 SDIO0->CLKCON = CLKCON0_SELFREQ + CLKCON0_ENSDCLK + CLKCON0_ENINTCLK; //主机控制寄存器配置 SDIO0->HOSTCTL = HOSTCTL0_WIDE8 + HOSTCTL0_DMASEL + HOSTCTL0_OUTEDGEINV + HOSTCTL0_WIDE4; //容限寄存器配置 SDIO0->CAPAREG = CAPAREG0_V18 + CAPAREG0_V30 + CAPAREG0_V33 + CAPAREG0_SUSRES + CAPAREG0_DMA + CAPAREG0_HSPD + CAPAREG0_ADMA2 +\ CAPAREG0_MAXBLKLEN + CAPAREG0_BASECLK + CAPAREG0_TOUTUNIT + CAPAREG0_TOUTCLK; //控制寄存器2配置 SDIO0->CONTROL2 = CONTROL2_0_ENSTAASYNCCLR + CONTROL2_0_ENCMDCNFMSK + CONTROL2_0_CDINVRXD3 + CONTROL2_0_SELCARDOUT + CONTROL2_0_FLTCLKSEL + \ CONTROL2_0_ENFBCLKTX + CONTROL2_0_ENFBCLKRX + CONTROL2_0_SDCDSEL + CONTROL2_0_SDSIGPC + CONTROL2_0_ENBUSYCHKTXSTART + \ CONTROL2_0_DFCNT + CONTROL2_0_ENCLKOUTHOLD + CONTROL2_0_RWAITMODE + CONTROL2_0_DISBUFRD + CONTROL2_0_SELBASECLK + \ CONTROL2_0_PWRSYNC + CONTROL2_0_ENCLKOUTMSKCON + CONTROL2_0_HWINITFIN; //传输模式寄存器配置 SDIO0->TRNMOD = TRNMOD0_CCSCON + TRNMOD0_MUL1SIN0 + TRNMOD0_RD1WT0 + TRNMOD0_ENACMD12 + TRNMOD0_ENBLKCNT + TRNMOD0_ENDMA; //超时控制寄存器(0 通道) SDIO0->TIMEOUTCON = 0x0e; //超时设置最大 //电源控制寄存器配置 SDIO0->PWRCON = PWRCON0_SELPWRLVL + PWRCON0_PWRON; //块间隔寄存器 SDIO0->BLKGAP = 0; //开启卡插入+卡移除+传输完成+指令完成中断状态+数据超时错误+命令索引错误+指令最后位错误+指令超时错误+指令CRC + 缓冲区读就绪 + 写缓冲区就绪 SDIO_FlagConfig(SDIO_FLAG_CARDREMOVAL | SDIO_FLAG_CARDINSERTION | SDIO_FLAG_TRANSFER | SDIO_FLAG_COMMANDEND | SDIO_FLAG_DATACRC | SDIO_FLAG_DATATIMEOUT | SDIO_FLAG_COMMANDINDEX | SDIO_FLAG_COMMANDCRC | SDIO_FLAG_COMMANDTIMEOUT | SDIO_FLAG_BUFFREAD | SDIO_FLAG_BUFFWRITE,Enable); //使能卡插入拔出中断 SDIO_FlagITConfig(SDIO_FLAG_CARDREMOVAL | SDIO_FLAG_CARDINSERTION,Enable); SDIO_ClearFlag(SDIO_FLAG_ALL); //清除所有中断标志 } void SDIO_FlagITConfig(u32 SDIO_FLAG, u8 EN) { if(EN) //中断使能 SDIO0->INTSEGEN |= SDIO_FLAG; else SDIO0->INTSEGEN &= ~SDIO_FLAG; } void SDIO_FlagConfig(u32 SDIO_FLAG, u8 EN) { if(EN) //状态使能 SDIO0->INTSTSEN |= SDIO_FLAG; else SDIO0->INTSTSEN &= ~SDIO_FLAG; } /************************************************************************************************************************* *函数 : void SD_SendCommand(vu8 CmdIdx,vu32 CmdArg,vu8 CmdTyp,vu8 Misc) *功能 : 向SD卡发送一个命令 *参数 : CmdIdx:指令索引;CmdArg:命令参数;CmdMisc:其它杂项设置,详见说明 *返回 : 无 *依赖 : 底层宏定义 *作者 : 陈鹏 *时间 : 20120507 *最后修改时间: 20120507 *说明 : 写SD命令寄存器; 指令索引:这些位设置为SD存储卡物理层规范中指令格式的第40到45位和SDIO卡规范中指定的指令数(CMD0-63, ACMD0-63)。 杂项: SDIO_Type_Default 一般为0 SDIO_Type_Pend 写总线暂停 SDIO_Type_FS 功能选择 SDIO_Type_IT 中断模式 SDIO_CMDIndexEn SDIO指令索引使能 SDIO_CMDCrcEn SDIO指令CRC校验使能 SDIO_Response_No 无应答 SDIO_Response_Short 短应答 48 SDIO_Response_Long 长应答 136 SDIO_Response_ShortBusy 短应答+检测繁忙情况 *************************************************************************************************************************/ void SDIO_SendCommand(vu8 CmdIdx,vu32 CmdArg,vu8 CmdMisc) {<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>u16 temreg = 0; <span style="white-space:pre"> </span>SDIO_ClearFlag(SDIO_FLAG_ALL);<span style="white-space:pre"> </span>//清除所有状态寄存 <span style="white-space:pre"> </span>temreg = CmdIdx; <span style="white-space:pre"> </span>temreg <<= 8; <span style="white-space:pre"> </span>temreg |= CmdMisc; <span style="white-space:pre"> </span>SDIO0->ARGUMENT = CmdArg;<span style="white-space:pre"> </span>//先写入命令参数 <span style="white-space:pre"> </span>SDIO0->CMDREG = temreg;<span style="white-space:pre"> </span>//再写入命令索引以及类型等参数 <span style="white-space:pre"> </span>while(!(SDIO0->PRNSTS & BIT0));<span style="white-space:pre"> </span>//等待命令线空忙,也就是开始执行命令 <span style="white-space:pre"> </span>while(SDIO0->PRNSTS & BIT0);<span style="white-space:pre"> </span>//等待命令线空闲,也就是命令执行完毕 } /************************************************************************************************************************* *函数 : u32 SD_GetResponse(u8 SDIO_RESP) *功能 : 获取SD卡的应答 *参数 : Rep:应答数据存放的位置 SDIO_RESP1: Response Register 1 * SDIO_RESP2: Response Register 2 * SDIO_RESP3: Response Register 3 * SDIO_RESP4: Response Register 4 *返回 : 返回应答 *依赖 : 底层宏定义 *作者 : 陈鹏 *时间 : 20120507 *最后修改时间: 20120507 *说明 : 存放应答数据的缓冲区为128BIT;4个32bit; 指令应答。下表27-4为每一个应答描述了从SD总线到寄存器的指令映射。在这个表中,在表中 R[]指出在SD总线上传输的应答数据的范围, REP[]指出应答寄存器中位的范围。128位应答位的顺序: {RSPREG3, RSPREG2, RSPREG1, RSPREG0} *************************************************************************************************************************/ u32 SDIO_GetResponse(u8 SDIO_RESP) { return (SDIO0->RSPREG[SDIO_RESP]); } u32 SDIO_ReadData(void) { return SDIO0->BDATA; //从缓冲区读数据 } void SDIO_WriteData(u32 Data) { SDIO0->BDATA = Data; } u8 SDIO_GetFlagStatus(u32 SDIO_FLAG) { return ((SDIO_STATUS & SDIO_FLAG) ? 1 : 0); } void SDIO_ClearFlag(u32 SDIO_FLAG) { SDIO_STATUS |= SDIO_FLAG; } /************************************************************************************************************************* * 函数 : void SDIO_SetFIFOInterruptAddress(u8 FIFOxAdd,u8 WordAdd) * 功能 : 设置FIFO中断触发位置 * 参数 : FIFOxAdd:FIFO地址选择 WordAdd:触发位置选择,单位为字,共512B,也就是1-128字 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : 无 *************************************************************************************************************************/ void SDIO_SetFIFOInterruptAddress(u8 FIFOxAdd,u8 WordAdd) { if(WordAdd > 128) WordAdd = 128; switch (FIFOxAdd) { case FIFO_A0: { SDIO0->CONTROL3 &= ~(0x1f); SDIO0->CONTROL3 |= WordAdd; }break; case FIFO_A1: { SDIO0->CONTROL3 &= ~(0x1f << 8); SDIO0->CONTROL3 |= WordAdd << 8; }break; case FIFO_A2: { SDIO0->CONTROL3 &= ~(0x1f << 16); SDIO0->CONTROL3 |= WordAdd << 16; }break; case FIFO_A3: { SDIO0->CONTROL3 &= ~(0x1f << 24); SDIO0->CONTROL3 |= WordAdd << 24; }break; default : break; } } /************************************************************************************************************************* * 函数 : void SDIO_CLKFrequencySelect(u8 SDCLK) * 功能 : 设置SDIO时钟分频系数 * 参数 : SDCLK:设置SDIO时钟分频系数 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : 高速基础时钟为50MHz 低速基础时钟为25MHz *************************************************************************************************************************/ void SDIO_CLKFrequencySelect(u8 SDCLK) { SDIO_SDClkDisable(); //时钟停止 SDIO0->CAPAREG &= ~(0x3f << 8); //清除设置 SDIO0->CAPAREG |= (50 << 8); //这一位设置其实没作用 SDIO0->CLKCON &= ~(0xff << 8); //清除 SDIO0->CLKCON |= (SDCLK << 8); //设置基础时钟分频系数 SDIO_SDClkEnable(); //时钟使能 while(!(SDIO0->CLKCON & BIT0)); //等待时钟稳定 } /************************************************************************************************************************* * 函数 : void SDIO_SoftwareReset(u32 SDIO_RST) * 功能 : 设置SDIO软件复位 * 参数 : SDIO_RST: SDIO_RSTDAT //复位DAT线 SDIO_RSTCMD //复位CMD线 SDIO_RSTALL //复位所有 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : 无 *************************************************************************************************************************/ void SDIO_SoftwareReset(u32 SDIO_RST) { SDIO0->SWRST |= SDIO_RST; //复位 while(SDIO0->SWRST & SDIO_RST); //等待复位完成 } /************************************************************************************************************************* *函数 : void SDIO_SetTimeOutClock(u8 Unit,u8 Frequency) *功能 : 超时时钟设置 *参数 : Unit:超时时钟单位选择 TIME_OUT_UNIT_KHZ(0):超时时钟单位为KHZ TIME_OUT_UNIT_MHZ(1):超时时钟单位为MHZ Frequency:时钟频率:1~63 *返回 : 返回应答 *依赖 : 底层宏定义 *作者 : 陈鹏 *时间 : 20120521 *最后修改时间: 20120521 *说明 : 配置指令超时时间 *************************************************************************************************************************/ void SDIO_SetTimeOutClock(u8 Unit,u8 Frequency) { SDIO0->CAPAREG &= ~(0xff); //清除原先设置 if(Unit) //配置超时时钟单位:MHZ SDIO0->CAPAREG |= (1 << 7); if(Frequency > 63) //最大只能设置为63 Frequency = 63; SDIO0->CAPAREG |= Frequency; }
#ifndef _S3C6410_SDIO_H_ #define _S3C6410_SDIO_H_ #include "s3c6410_system.h" #define FIFO_A0 0 //FIFO中断地址0 #define FIFO_A1 1 //FIFO中断地址1 #define FIFO_A2 2 //FIFO中断地址2 #define FIFO_A3 3 //FIFO中断地址3 //SDIO总线宽度设置 #define SDIO_BusWide_1b ((u8)0) #define SDIO_BusWide_4b ((u8)1) #define SDIO_BusWide_8b ((u8)2) //SDIO 命令杂项设置 //SDIO响应类型 #define SDIO_Response_No ((u8)0) //无应答 #define SDIO_Response_Long ((u8)1) //长应答 136 #define SDIO_Response_Short ((u8)2) //短应答 48 #define SDIO_Response_ShortBusy ((u8)3) //短应答+检测繁忙情况 //其它设置 #define SDIO_CMDIndexEn ((u8)1 << 4)//SDIO指令索引使能 #define SDIO_CMDCrcEn ((u8)1 << 3)//SDIO指令CRC校验使能 #define SDIO_DataSelect ((u8)1 << 5)//SDIO当前数据选择 //SDIO指令类型CmdTyp #define SDIO_Type_Default ((u8)0 << 6)//一般为0 #define SDIO_Type_Pend ((u8)1 << 6)//写总线暂停 #define SDIO_Type_FS ((u8)2 << 6)//功能选择 #define SDIO_Type_IT ((u8)3 << 6)//中断模式 //SDIO响应寄存器选择 #define SDIO_RESP1 ((u8)0) #define SDIO_RESP2 ((u8)1) #define SDIO_RESP3 ((u8)2) #define SDIO_RESP4 ((u8)3) /* SDIO Data Block Size ------------------------------------------------------*/ #define SDIO_DataBlockSize_1b ((u16)1) #define SDIO_DataBlockSize_2b ((u16)2) #define SDIO_DataBlockSize_4b ((u16)3) #define SDIO_DataBlockSize_8b ((u16)4) #define SDIO_DataBlockSize_16b ((u16)16) #define SDIO_DataBlockSize_32b ((u16)32) #define SDIO_DataBlockSize_64b ((u16)64) #define SDIO_DataBlockSize_128b ((u16)128) #define SDIO_DataBlockSize_256b ((u16)256) #define SDIO_DataBlockSize_512b ((u16)512) #define SDIO_DataBlockSize_1024b ((u16)1024) #define SDIO_DataBlockSize_2048b ((u16)2048) #define SDIO_DataBlockSize_4096b ((u16)4096) #define SDIO_DataBlockSize_8192b ((u16)8192) #define SDIO_DataBlockSize_16384b ((u16)16384) /* SDIO Flags ----------------------------------------------------------------*/ //SDIO中断状态 #define SDIO_STATUS (SDIO0->INTSTS) #define SDIO_FLAG_FIFOADDERR3 ((u32)1 << 14) //FIFO SD 地址指示器中断3 状态 (RW1C) #define SDIO_FLAG_FIFOADDERR2 ((u32)1 << 13) //FIFO SD 地址指示器中断2 状态 (RW1C) #define SDIO_FLAG_FIFOADDERR1 ((u32)1 << 12) //FIFO SD 地址指示器中断1 状态 (RW1C) #define SDIO_FLAG_FIFOADDERR0 ((u32)1 << 11) //FIFO SD 地址指示器中断0 状态 (RW1C) #define SDIO_FLAG_READWAIT ((u32)1 << 10) //读等待中断状态 (RW1C)。 #define SDIO_FLAG_CCS ((u32)1 << 9) //CCS 中断状态 (RW1C)。 #define SDIO_FLAG_CARD ((u32)1 << 8) //卡 中断。 #define SDIO_FLAG_CARDREMOVAL ((u32)1 << 7) //卡移除 #define SDIO_FLAG_CARDINSERTION ((u32)1 << 6) //卡插入 #define SDIO_FLAG_BUFFREAD ((u32)1 << 5) //读缓冲区就绪 #define SDIO_FLAG_BUFFWRITE ((u32)1 << 4) //写缓冲区就绪 #define SDIO_FLAG_DMA ((u32)1 << 3) //DMA #define SDIO_FLAG_BLOCKGAP ((u32)1 << 2) //块间隔事件。 #define SDIO_FLAG_TRANSFER ((u32)1 << 1) //传输完成。超时错误优先 #define SDIO_FLAG_COMMANDEND ((u32)1 << 0) //指令完成。超时错误优先 #define SDIO_FLAG_ADMA ((u32)1 << 25) //DMA错误 #define SDIO_FLAG_AUTOCMD12 ((u32)1 << 24) //自动CMD12错误 #define SDIO_FLAG_DATAENDBIT ((u32)1 << 22) //数据最后位错误 #define SDIO_FLAG_DATACRC ((u32)1 << 21) //数据CRC错误 #define SDIO_FLAG_DATATIMEOUT ((u32)1 << 20) //数据超时错误 #define SDIO_FLAG_COMMANDINDEX ((u32)1 << 19) //命令索引错误 #define SDIO_FLAG_COMMANDENDBIT ((u32)1 << 18) //指令最后位错误 #define SDIO_FLAG_COMMANDCRC ((u32)1 << 17) //指令CRC错误 #define SDIO_FLAG_COMMANDTIMEOUT ((u32)1 << 16) //指令超时错误 #define SDIO_FLAG_ALL ((u32)0xffffffff) //所有标志 void SDIO_DeInit(void); void SDIO_ClockCmd(u8 EN); void SDIO_SetPowerState(u32 SDIO_PowerState); void SDIO_FlagITConfig(u32 SDIO_FLAG, u8 EN); void SDIO_FlagConfig(u32 SDIO_FLAG, u8 EN); void SDIO_SendCommand(vu8 CmdIdx,vu32 CmdArg,vu8 CmdMisc); u32 SDIO_GetResponse(u8 SDIO_RESP); u32 SDIO_ReadData(void); void SDIO_WriteData(u32 Data); u8 SDIO_GetFlagStatus(u32 SDIO_FLAG); void SDIO_ClearFlag(u32 SDIO_FLAG); void SDIO_SetFIFOInterruptAddress(u8 FIFOxAdd,u8 WordAdd); void SDIO_SetTimeOutClock(u8 Unit,u8 Frequency); void SDIO_CLKFrequencySelect(u8 SDCLK); void SDIO_SoftwareReset(u32 SDIO_RST);//软件复位 //设置需要传输的块数量 #define SDIO_SetTransferBlockCnt(x) (SDIO0->BLKCNT = x) //获取剩余传输的块的数量 #define SDIO_GetTransferBlockCnt() (SDIO0->BLKCNT) //设置单次传输的块的大小 #define SDIO_SetTransferBlockSize(x) (SDIO0->BLKSIZE = (x & 0xfff)) //设置为单块传输模式 #define SDIO_SingleBlockMode() (SDIO0->TRNMOD &= ~(BIT5)) //设置为多区段传输模式 #define SDIO_MultipleBlockMode() (SDIO0->TRNMOD |= BIT5) //自动CMD12命令启动 #define SDIO_AutoCMD12Enable() (SDIO0->TRNMOD |= BIT2) //自动CMD12命令禁止 #define SDIO_AuotCMD12Disable() (SDIO0->TRNMOD &= ~(BIT2)) //设置SDIO为写数据模式 #define SDIO_WriteMode() (SDIO0->TRNMOD &= ~(BIT4)) //设置SDIO为读数据模式 #define SDIO_ReadMode() (SDIO0->TRNMOD |= BIT4) //块计数器启动 #define SDIO_BlockCountEnable() (SDIO0->TRNMOD |= BIT1) //禁止块计数器启动 #define SDIO_BlockCountDisable() (SDIO0->TRNMOD &= ~(BIT1)) //DMA启动 #define SDIO_DMAEnable() (SDIO0->TRNMOD |= BIT0) //DMA禁止 #define SDIO_DMADisable() (SDIO0->TRNMOD &= ~(BIT0)) //数据线忙 #define SDIO_DATLineActive() (SDIO0->PRNSTS & BIT2) //指令禁止 #define SDIO_CommandInhibit() (SDIO0->PRNSTS & BIT0) //高速时钟模式使能 #define SDIO_HighSpeedEnable() (SDIO0->CAPAREG |= BIT21) //取消高速时钟模式 #define SDIO_HighSpeedDisable() (SDIO0->CAPAREG &= ~BIT21) //数据线宽度设置为4bit #define SDIO_SetDataDataWidth_4b() (SDIO0->HOSTCTL |= BIT1) //数据线宽设置为1bit #define SDIO_SetDataDataWidth_1b() (SDIO0->HOSTCTL &= ~BIT1) //总线电压选择3.3V #define SDIO_SetBusVoltage_3_3V() (SDIO0->PWRCON &= ~(0x7 << 1); SDIO0->PWRCON |= (7 << 1)) //总线电源开启 #define SDIO_BusPowerON() (SDIO0->PWRCON |= BIT0) //总线电压关闭 #define SDIO_BusPowerOFF() (SDIO0->PWRCON &= ~BIT0) //唤醒发生在SD卡插入 #define SDIO_WakeupOnSDInsertion() (SDIO0->WAKCON |= BIT1 //使能SD时钟 #define SDIO_SDClkEnable() (SDIO0->CLKCON |= BIT2) //SD时钟停止 #define SDIO_SDClkDisable() (SDIO0->CLKCON &= ~BIT2) //超时时钟单位设置 #define TIME_OUT_UNIT_KHZ 0 //超时时钟单位为KHZ #define TIME_OUT_UNIT_MHZ 1 //超时时钟单位为MHZ //时钟分频系数 #define SDCLK_1_256 ((u8)0x80) //基础时钟256分频 #define SDCLK_1_128 ((u8)0x40) //基础时钟128分频 #define SDCLK_1_64 ((u8)0x20) //基础时钟64分频 #define SDCLK_1_32 ((u8)0x10) //基础时钟32分频 #define SDCLK_1_16 ((u8)0x08) //基础时钟16分频 #define SDCLK_1_8 ((u8)0x04) //基础时钟8分频 #define SDCLK_1_4 ((u8)0x02) //基础时钟4分频 #define SDCLK_1_2 ((u8)0x01) //基础时钟2分频 #define SDCLK_1_1 ((u8)0x00) //基础时钟1分频 //软件复位选择 #define SDIO_RSTDAT BIT2 //复位DAT线 #define SDIO_RSTCMD BIT1 //复位CMD线 #define SDIO_RSTALL BIT0 //复位所有 #endif
sdcard_sdio.c,
/******************************************************************************* //功能:SDCARD 驱动,SDIO 模式 //作者:陈鹏 //创建时间:2012-05-16 10:32 //修改时间:2012-05-16 10:32 //修订说明: //声明:源程序借鉴了意法STM32F103X库函数 ********************************************************************************/ #include "sdcard_sdio.h" #include "s3c6410_sdio.h" #include "s3c6410_system.h" u8 SDMMC0_MOV_Flag = 0; //sdmmc0卡移除信号有 /* 1.3 寄存器 名称 宽度 描述 CID 128 卡标识号 RCA 16 相对卡地址(Relative card address):本地系统中卡的地 址,动态变化,在主机初始化的时候确定 *SPI 模式中没有 CSD 128 卡描述数据:卡操作条件相关的信息数据 SCR 64 SD 配置寄存器:SD 卡特定信息数据 OCR 32 操作条件寄存器*/ //容量 = BLOCKNR * BLOCK_LEN = (C_SIZE+1)*2^(C_SIZE_MULT+2)*2^(READ_BL_LEN) #define SD_BlockSize 512 //SD卡块大小 #define SDIO_CMD0TIMEOUT 1000000 //超时计数器大小 #define SDIO_READTIMEOUT 1000000 //读等待超时 #define SDIO_WRITETIMEOUT 2000000 //写等待超时 // SD卡指令表 #define CMD0 0 //卡复位 #define CMD1 1 #define CMD9 9 //命令9 ,读CSD数据 #define CMD10 10 //命令10,读CID数据 #define CMD12 12 //命令12,停止数据传输 #define CMD16 16 //命令16,设置SectorSize 应返回0x00 #define CMD17 17 //命令17,读sector #define CMD18 18 //命令18,读Multi sector #define ACMD23 23 //命令23,设置多sector写入前预先擦除N个block #define CMD24 24 //命令24,写sector #define CMD25 25 //命令25,写Multi sector #define ACMD41 41 //命令41,应返回0x00 #define CMD55 55 //命令55,应返回0x01 #define CMD58 58 //命令58,读OCR信息 #define CMD59 59 //命令59,使能/禁止CRC,应返回0x0 /* Mask for errors Card Status R1 (OCR Register) */ #define SD_OCR_ADDR_OUT_OF_RANGE ((u32)0x80000000) #define SD_OCR_ADDR_MISALIGNED ((u32)0x40000000) #define SD_OCR_BLOCK_LEN_ERR ((u32)0x20000000) #define SD_OCR_ERASE_SEQ_ERR ((u32)0x10000000) #define SD_OCR_BAD_ERASE_PARAM ((u32)0x08000000) #define SD_OCR_WRITE_PROT_VIOLATION ((u32)0x04000000) #define SD_OCR_LOCK_UNLOCK_FAILED ((u32)0x01000000) #define SD_OCR_COM_CRC_FAILED ((u32)0x00800000) #define SD_OCR_ILLEGAL_CMD ((u32)0x00400000) #define SD_OCR_CARD_ECC_FAILED ((u32)0x00200000) #define SD_OCR_CC_ERROR ((u32)0x00100000) #define SD_OCR_GENERAL_UNKNOWN_ERROR ((u32)0x00080000) #define SD_OCR_STREAM_READ_UNDERRUN ((u32)0x00040000) #define SD_OCR_STREAM_WRITE_OVERRUN ((u32)0x00020000) #define SD_OCR_CID_CSD_OVERWRIETE ((u32)0x00010000) #define SD_OCR_WP_ERASE_SKIP ((u32)0x00008000) #define SD_OCR_CARD_ECC_DISABLED ((u32)0x00004000) #define SD_OCR_ERASE_RESET ((u32)0x00002000) #define SD_OCR_AKE_SEQ_ERROR ((u32)0x00000008) #define SD_OCR_ERRORBITS ((u32)0xFDFFE008) /* Masks for R6 Response */ #define SD_R6_GENERAL_UNKNOWN_ERROR ((u32)0x00002000) #define SD_R6_ILLEGAL_CMD ((u32)0x00004000) #define SD_R6_COM_CRC_FAILED ((u32)0x00008000) #define SD_VOLTAGE_WINDOW_SD ((u32)0x80100000) #define SD_HIGH_CAPACITY ((u32)0x40000000) #define SD_STD_CAPACITY ((u32)0x00000000) #define SD_CHECK_PATTERN ((u32)0x000001AA) #define SD_MAX_VOLT_TRIAL ((u32)0x0000FFFF) #define SD_ALLZERO ((u32)0x00000000) #define SD_WIDE_BUS_SUPPORT ((u32)0x00040000) #define SD_SINGLE_BUS_SUPPORT ((u32)0x00010000) #define SD_CARD_LOCKED ((u32)0x02000000) #define SD_CARD_PROGRAMMING ((u32)0x00000007) #define SD_CARD_RECEIVING ((u32)0x00000006) #define SD_DATATIMEOUT ((u32)0x000FFFFF) #define SD_0TO7BITS ((u32)0x000000FF) #define SD_8TO15BITS ((u32)0x0000FF00) #define SD_16TO23BITS ((u32)0x00FF0000) #define SD_24TO31BITS ((u32)0xFF000000) #define SD_MAX_DATA_LENGTH ((u32)0x01FFFFFF) #define SD_HALFFIFO ((u32)0x00000008) #define SD_HALFFIFOBYTES ((u32)0x00000020) /* Command Class Supported */ #define SD_CCCC_LOCK_UNLOCK ((u32)0x00000080) #define SD_CCCC_WRITE_PROT ((u32)0x00000040) #define SD_CCCC_ERASE ((u32)0x00000020) /* Following commands are SD Card Specific commands. SDIO_APP_CMD should be sent before sending these commands. */ #define SDIO_SEND_IF_COND ((u32)0x00000008) //#define SDIO_MULTIMEDIA_CARD ((u32)0x0) #define SDIO_SECURE_DIGITAL_CARD ((u32)0x1) //#define SDIO_SECURE_DIGITAL_IO_CARD ((u32)0x2) //#define SDIO_HIGH_SPEED_MULTIMEDIA_CARD ((u32)0x3) //#define SDIO_SECURE_DIGITAL_IO_COMBO_CARD ((u32)0x4) //#define SDIO_HIGH_CAPACITY_SD_CARD ((u32)0x5) //#define SDIO_HIGH_CAPACITY_MMC_CARD ((u32)0x6) #define SDIO_INIT_CLK_DIV ((u8)0xB2) #define SDIO_TRANSFER_CLK_DIV ((u8)0x01) //时钟分频 /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ static u32 CardType = SDIO_SECURE_DIGITAL_CARD; static u32 CSD_Tab[4], CID_Tab[4], RCA = 0; //static u32 DeviceMode = SD_POLLING_MODE; //static u32 TotalNumberOfBytes = 0, StopCondition = 0; u32 *SrcBuffer, *DestBuffer; volatile SD_Error TransferError = SD_OK; vu32 TransferEnd = 0; vu32 NumberOfBytes = 0; //SD卡中断服务程序,用来检测卡的插入与移除的 static void __irq Isr_SDMMC_Card(void); /* Private function prototypes -----------------------------------------------*/ static SD_Error CmdError(void); static SD_Error CmdResp1Error(void); static SD_Error CmdResp7Error(void); static SD_Error CmdResp3Error(void); static SD_Error CmdResp2Error(void); static SD_Error CmdResp6Error(u16 *prca); static SD_Error SDEnWideBus(u8 EN); static SD_Error IsCardProgramming(u8 *pstatus); static SD_Error FindSCR(u16 rca, u32 *pscr); #define DebugPrintf printf /************************************************************************************************************************* * 函数 : SD_Error SD_Init(void) * 功能 : SD卡初始化 * 参数 : 无 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120524 * 说明 : 初始化SD卡 *************************************************************************************************************************/ SD_Error SD_Init(void) { SD_Error errorstatus = SD_OK; SDIO_SoftwareReset(SDIO_RSTALL); //软件复位所有寄存器 SDIO_DeInit(); //初始化SDIO硬件 SDIO_FlagITConfig(SDIO_FLAG_CARDREMOVAL | SDIO_FLAG_CARDINSERTION,Enable);//使能卡插入拔出中断 Set_IsrAddr(INT_HSMMC0,(vu32)Isr_SDMMC_Card); //设置中断矢量入口 Set_IntEnable(INT_HSMMC0,Enable); //开启SDMMC0中断 errorstatus = SD_SetIdleSta(); //SD卡上电 if (errorstatus != SD_OK) //卡上电发送错误 { DebugPrintf("SD power up error:(%d)!\n",errorstatus); //调试,打印错误 return(errorstatus); //返回错误 } errorstatus = SD_InitializeCards(); if (errorstatus != SD_OK) { DebugPrintf("SD initialize error(%d)!\n",errorstatus); //调试,打印错误 return(errorstatus); } return(errorstatus); } /************************************************************************************************************************* * 函数 : SD_Error SD_SetIdleSta(void) * 功能 : SD卡上电进入空闲模式,并识别卡 * 参数 : 无 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : SD卡上电进入空闲模式 *************************************************************************************************************************/ SD_Error SD_SetIdleSta(void) { SD_Error errorstatus = SD_OK; u32 response = 0, count = 0; bool validvoltage = FALSE; u32 SDType = SD_STD_CAPACITY; u16 i; SDIO_CLKFrequencySelect(SDCLK_1_64); //设置时钟400KHZ SDIO_SetTimeOutClock(TIME_OUT_UNIT_KHZ,1); //设置超时时钟频率最低 //发送至少74个时钟,等待SD卡上电成功并同步 for(response = 0;response < 1000;response ++); //循环发生发送CMD0,无响应,无返回,让SD卡进入空闲模式 for(i = 0;i < 50;i ++) { SDIO_SendCommand(CMD0,0,0); errorstatus = CmdError(); //判断命令是否执行成功,此命令只要初始化了SDIO就会执行成功 if(errorstatus == SD_OK) break; } if(errorstatus != SD_OK) { DEBUG("error!(%d)\n",errorstatus); //调试,打印信息 return(errorstatus); } //发送CMD8:SEND_IF_COND;短响应,命令参数:SD_CHECK_PATTERN;返回响应R7 //识别卡版本 SDIO_SendCommand(SDIO_SEND_IF_COND,SD_CHECK_PATTERN,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp7Error(); if (errorstatus == SD_OK) //返回成功;说明卡为SD Card 2.0 V2.0 { CardType = SDIO_STD_CAPACITY_SD_CARD_V2_0; /* SD Card 2.0 */ SDType = SD_HIGH_CAPACITY; DEBUG("SDIO_STD_CAPACITY_SD_CARD_V2_0!\n"); //调试,打印错误信息 } else //V1.0 V1.1 { DEBUG("SD Card V1.1!\n"); //调试,打印信息 CardType = SDIO_STD_CAPACITY_SD_CARD_V1_1; //V1.0 V1.1 SDIO_SendCommand(CMD55,0,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); CmdResp1Error(); } do { //发送CMD55 SDIO_APP_CMD;命令参数:0;返回响应R1,设置RCA为0,短响应 SDIO_SendCommand(SDIO_APP_CMD,0,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); if (errorstatus != SD_OK) { DEBUG("CMD55 error(%d)!\n",errorstatus); //调试,打印错误信息 return(errorstatus); } //发送ACM41命令;命令参数:SD_APP_OP_COND(0x80100000);短响应.响应为R3,返回操作条件寄存器RCA SDIO_SendCommand(SDIO_SD_APP_OP_COND,SD_VOLTAGE_WINDOW_SD | SDType,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp3Error(); if (errorstatus != SD_OK) { DEBUG("ACM41 error(%d)!\n",errorstatus); //调试,打印错误信息 return(errorstatus); } response = SDIO_GetResponse(SDIO_RESP1); //获取响应,RESE1 validvoltage = (bool) (((response >> 31) == 1) ? 1 : 0); count++; } while((!validvoltage) && (count < SD_MAX_VOLT_TRIAL));//循环初始化,直到返回成功或者超时 if (count >= SD_MAX_VOLT_TRIAL) //重试次数超出 { errorstatus = SD_INVALID_VOLTRANGE; return(errorstatus); } if (response &= SD_HIGH_CAPACITY) { CardType = SDIO_HIGH_CAPACITY_SD_CARD; } return(errorstatus); } /************************************************************************************************************************* * 函数 : SD_Error SD_PowerOFF(void) * 功能 : SD卡掉电 * 参数 : 无 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : SD卡掉电 *************************************************************************************************************************/ SD_Error SD_PowerOFF(void) { SD_Error errorstatus = SD_OK; SDIO_BusPowerOFF(); //关闭总线电源 return(errorstatus); } /************************************************************************************************************************* * 函数 : SD_Error SD_PowerON(void) * 功能 : SD卡电源开启 * 参数 : 无 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120524 * 说明 : SD卡电源开启 *************************************************************************************************************************/ SD_Error SD_PowerON(void) { SD_Error errorstatus = SD_OK; SDIO_BusPowerON(); //打开总线电源 return(errorstatus); } /************************************************************************************************************************* * 函数 : SD_Error SD_InitializeCards(void) * 功能 : 将所有的卡进行初始化配置 * 参数 : 无 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : 将所有的卡进行初始化配置 *************************************************************************************************************************/ SD_Error SD_InitializeCards(void) { SD_Error errorstatus = SD_OK; u16 rca = 0x01; //发送CMD2 SDIO_ALL_SEND_CID命令,命令参数:0;长回复,R2 //发送CMD用来获取CID信息的 SDIO_SendCommand(SDIO_ALL_SEND_CID,0,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Long); errorstatus = CmdResp2Error(); //获取响应R2 if (errorstatus != SD_OK) { DEBUG("error!(%d)\n",errorstatus); //调试,打印错误信息 return(errorstatus); } //到每个卡以获取每个卡的唯一标识CID CID_Tab[0] = SDIO_GetResponse(SDIO_RESP1); CID_Tab[1] = SDIO_GetResponse(SDIO_RESP2); CID_Tab[2] = SDIO_GetResponse(SDIO_RESP3); CID_Tab[3] = SDIO_GetResponse(SDIO_RESP4); //发送CMD3,SET_REL_ADDR命令,参数0,响应,短响应,R6 //用来获取卡地址 //主机发送CMD3(SEND_RELATIVE_ADDR)要求卡发布一个新的相对卡地址RCA,地址比CID短,在以后的数据传输模式中用来寻址卡。一旦获得RCA后,卡状态变成就绪状态(Stand-by state) SDIO_SendCommand(SDIO_SET_REL_ADDR,0,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp6Error(&rca); //获取卡地址 if (errorstatus != SD_OK) { DEBUG("error!(%d)!\n",errorstatus); //调试,打印错误信息 return(errorstatus); } RCA = rca;//存储卡地址 //发送CMD9 SDIO_SEND_CSD命令,参数:rca地址;长响应,R2; //给卡发送一个新的RCA,主要是用来设置卡地址的 SDIO_SendCommand(SDIO_SEND_CSD,(u32)rca << 16,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Long); errorstatus = CmdResp2Error(); if (errorstatus != SD_OK) { DEBUG("error!(%d)!\n",errorstatus); //调试,打印错误信息 return(errorstatus); } //获取CSD CSD_Tab[0] = SDIO_GetResponse(SDIO_RESP1); CSD_Tab[1] = SDIO_GetResponse(SDIO_RESP2); CSD_Tab[2] = SDIO_GetResponse(SDIO_RESP3); CSD_Tab[3] = SDIO_GetResponse(SDIO_RESP4); //选中卡,并激活 errorstatus = SD_SelectDeselect((u32)RCA << 16); if(errorstatus != SD_OK) { DEBUG("SelectDeselect error!(%d)!\n",errorstatus); //调试,打印错误信息 return(errorstatus); } errorstatus = SD_OK; /* All cards get intialized */ SDIO_CLKFrequencySelect(SDCLK_1_2); //设置时钟 SDIO_SetTimeOutClock(TIME_OUT_UNIT_KHZ,63); //设置超时时钟频率最高 errorstatus = SD_EnableWideBusMode(Enable); if(errorstatus == SD_OK) //配置SD卡为4线模式 { DEBUG("SD SDIO 4BIT OK\n"); } else { errorstatus = SD_EnableWideBusMode(Disable); DEBUG("SD SDIO 4BIT ERROR (%d)\n",errorstatus); } SDIO_SetTransferBlockSize(SD_BlockSize);//设置传输块大小为512字节 errorstatus = SD_SetBlockSize(SD_BlockSize);//配置SD卡块大小 if (errorstatus != SD_OK) { DEBUG("SD SetBlockSize error(%d)!\n",errorstatus); return(errorstatus); } return(errorstatus); } /************************************************************************************************************************* * 函数 : SD_Error SD_SelectDeselect(u32 addr) * 功能 : 选中一个卡,并处于传输状态 * 参数 : addr:卡地址 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : 选择一个卡并将它置于传输状态(Transfer state) *************************************************************************************************************************/ SD_Error SD_SelectDeselect(u32 addr) { SD_Error errorstatus = SD_OK; //CMD7用来选择一个卡并将它置于传输状态(Transfer state),在任何时间只能有一个卡处于传输状态 SDIO_SendCommand(SDIO_SEL_DESEL_CARD,addr,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); return(errorstatus); } /************************************************************************************************************************* * 函数 : SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo) * 功能 : 获取卡的细节信息 * 参数 : cardinfo:卡信息结构指针,指向信息存放缓冲区地址 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : 获取卡的信息,通过CSD信息得到 *************************************************************************************************************************/ SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo) { SD_Error errorstatus = SD_OK; u8 tmp = 0; cardinfo->CardType = (u8)CardType; cardinfo->RCA = (u16)RCA; /* Byte 0 */ tmp = (u8)((CSD_Tab[0] & 0xFF000000) >> 24); cardinfo->SD_csd.CSDStruct = (tmp & 0xC0) >> 6; cardinfo->SD_csd.SysSpecVersion = (tmp & 0x3C) >> 2; cardinfo->SD_csd.Reserved1 = tmp & 0x03; /* Byte 1 */ tmp = (u8)((CSD_Tab[0] & 0x00FF0000) >> 16); cardinfo->SD_csd.TAAC = tmp; /* Byte 2 */ tmp = (u8)((CSD_Tab[0] & 0x0000FF00) >> 8); cardinfo->SD_csd.NSAC = tmp; /* Byte 3 */ tmp = (u8)(CSD_Tab[0] & 0x000000FF); cardinfo->SD_csd.MaxBusClkFrec = tmp; /* Byte 4 */ tmp = (u8)((CSD_Tab[1] & 0xFF000000) >> 24); cardinfo->SD_csd.CardComdClasses = tmp << 4; /* Byte 5 */ tmp = (u8)((CSD_Tab[1] & 0x00FF0000) >> 16); cardinfo->SD_csd.CardComdClasses |= (tmp & 0xF0) >> 4; cardinfo->SD_csd.RdBlockLen = tmp & 0x0F; /* Byte 6 */ tmp = (u8)((CSD_Tab[1] & 0x0000FF00) >> 8); cardinfo->SD_csd.PartBlockRead = (tmp & 0x80) >> 7; cardinfo->SD_csd.WrBlockMisalign = (tmp & 0x40) >> 6; cardinfo->SD_csd.RdBlockMisalign = (tmp & 0x20) >> 5; cardinfo->SD_csd.DSRImpl = (tmp & 0x10) >> 4; cardinfo->SD_csd.Reserved2 = 0; /* Reserved */ cardinfo->SD_csd.DeviceSize = (tmp & 0x03) << 10; /* Byte 7 */ tmp = (u8)(CSD_Tab[1] & 0x000000FF); cardinfo->SD_csd.DeviceSize |= (tmp) << 2; /* Byte 8 */ tmp = (u8)((CSD_Tab[2] & 0xFF000000) >> 24); cardinfo->SD_csd.DeviceSize |= (tmp & 0xC0) >> 6; cardinfo->SD_csd.MaxRdCurrentVDDMin = (tmp & 0x38) >> 3; cardinfo->SD_csd.MaxRdCurrentVDDMax = (tmp & 0x07); /* Byte 9 */ tmp = (u8)((CSD_Tab[2] & 0x00FF0000) >> 16); cardinfo->SD_csd.MaxWrCurrentVDDMin = (tmp & 0xE0) >> 5; cardinfo->SD_csd.MaxWrCurrentVDDMax = (tmp & 0x1C) >> 2; cardinfo->SD_csd.DeviceSizeMul = (tmp & 0x03) << 1; /* Byte 10 */ tmp = (u8)((CSD_Tab[2] & 0x0000FF00) >> 8); cardinfo->SD_csd.DeviceSizeMul |= (tmp & 0x80) >> 7; cardinfo->SD_csd.EraseGrSize = (tmp & 0x40) >> 6; cardinfo->SD_csd.EraseGrMul = (tmp & 0x3F) << 1; /* Byte 11 */ tmp = (u8)(CSD_Tab[2] & 0x000000FF); cardinfo->SD_csd.EraseGrMul |= (tmp & 0x80) >> 7; cardinfo->SD_csd.WrProtectGrSize = (tmp & 0x7F); /* Byte 12 */ tmp = (u8)((CSD_Tab[3] & 0xFF000000) >> 24); cardinfo->SD_csd.WrProtectGrEnable = (tmp & 0x80) >> 7; cardinfo->SD_csd.ManDeflECC = (tmp & 0x60) >> 5; cardinfo->SD_csd.WrSpeedFact = (tmp & 0x1C) >> 2; cardinfo->SD_csd.MaxWrBlockLen = (tmp & 0x03) << 2; /* Byte 13 */ tmp = (u8)((CSD_Tab[3] & 0x00FF0000) >> 16); cardinfo->SD_csd.MaxWrBlockLen |= (tmp & 0xC0) >> 6; cardinfo->SD_csd.WriteBlockPaPartial = (tmp & 0x20) >> 5; cardinfo->SD_csd.Reserved3 = 0; cardinfo->SD_csd.ContentProtectAppli = (tmp & 0x01); /* Byte 14 */ tmp = (u8)((CSD_Tab[3] & 0x0000FF00) >> 8); cardinfo->SD_csd.FileFormatGrouop = (tmp & 0x80) >> 7; cardinfo->SD_csd.CopyFlag = (tmp & 0x40) >> 6; cardinfo->SD_csd.PermWrProtect = (tmp & 0x20) >> 5; cardinfo->SD_csd.TempWrProtect = (tmp & 0x10) >> 4; cardinfo->SD_csd.FileFormat = (tmp & 0x0C) >> 2; cardinfo->SD_csd.ECC = (tmp & 0x03); /* Byte 15 */ tmp = (u8)(CSD_Tab[3] & 0x000000FF); cardinfo->SD_csd.CSD_CRC = (tmp & 0xFE) >> 1; cardinfo->SD_csd.Reserved4 = 1; /* Byte 0 */ tmp = (u8)((CID_Tab[0] & 0xFF000000) >> 24); cardinfo->SD_cid.ManufacturerID = tmp; /* Byte 1 */ tmp = (u8)((CID_Tab[0] & 0x00FF0000) >> 16); cardinfo->SD_cid.OEM_AppliID = tmp << 8; /* Byte 2 */ tmp = (u8)((CID_Tab[0] & 0x000000FF00) >> 8); cardinfo->SD_cid.OEM_AppliID |= tmp; /* Byte 3 */ tmp = (u8)(CID_Tab[0] & 0x000000FF); cardinfo->SD_cid.ProdName1 = tmp << 24; /* Byte 4 */ tmp = (u8)((CID_Tab[1] & 0xFF000000) >> 24); cardinfo->SD_cid.ProdName1 |= tmp << 16; /* Byte 5 */ tmp = (u8)((CID_Tab[1] & 0x00FF0000) >> 16); cardinfo->SD_cid.ProdName1 |= tmp << 8; /* Byte 6 */ tmp = (u8)((CID_Tab[1] & 0x0000FF00) >> 8); cardinfo->SD_cid.ProdName1 |= tmp; /* Byte 7 */ tmp = (u8)(CID_Tab[1] & 0x000000FF); cardinfo->SD_cid.ProdName2 = tmp; /* Byte 8 */ tmp = (u8)((CID_Tab[2] & 0xFF000000) >> 24); cardinfo->SD_cid.ProdRev = tmp; /* Byte 9 */ tmp = (u8)((CID_Tab[2] & 0x00FF0000) >> 16); cardinfo->SD_cid.ProdSN = tmp << 24; /* Byte 10 */ tmp = (u8)((CID_Tab[2] & 0x0000FF00) >> 8); cardinfo->SD_cid.ProdSN |= tmp << 16; /* Byte 11 */ tmp = (u8)(CID_Tab[2] & 0x000000FF); cardinfo->SD_cid.ProdSN |= tmp << 8; /* Byte 12 */ tmp = (u8)((CID_Tab[3] & 0xFF000000) >> 24); cardinfo->SD_cid.ProdSN |= tmp; /* Byte 13 */ tmp = (u8)((CID_Tab[3] & 0x00FF0000) >> 16); cardinfo->SD_cid.Reserved1 |= (tmp & 0xF0) >> 4; cardinfo->SD_cid.ManufactDate = (tmp & 0x0F) << 8; /* Byte 14 */ tmp = (u8)((CID_Tab[3] & 0x0000FF00) >> 8); cardinfo->SD_cid.ManufactDate |= tmp; /* Byte 15 */ tmp = (u8)(CID_Tab[3] & 0x000000FF); cardinfo->SD_cid.CID_CRC = (tmp & 0xFE) >> 1; cardinfo->SD_cid.Reserved2 = 1; return(errorstatus); } /************************************************************************************************************************* * 函数 : SD_Error SD_EnableWideBusMode(u8 EN) * 功能 : 使能4bit DAT线模式,如果失败将保持原来模式 * 参数 : Enable:4bit模式;Disable:1bit模式 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120524 * 说明 : 设置卡和控制器为4bit总线模式 *************************************************************************************************************************/ SD_Error SD_EnableWideBusMode(u8 EN) { SD_Error errorstatus = SD_OK; u8 IntFlag; //SD卡不支持设置 if (CardType == SDIO_MULTIMEDIA_CARD) { errorstatus = SD_UNSUPPORTED_FEATURE; return(errorstatus); } else if ((CardType == SDIO_SECURE_DIGITAL_CARD) || (CardType == SDIO_HIGH_CAPACITY_SD_CARD)) //SD卡 { if (EN) //4BIT模式 { errorstatus = SDEnWideBus(Enable); //设置SD卡为4bit总线模式 if (errorstatus == SD_OK) //设置SD卡成功 { IntFlag = Get_IntEnable(INT_HSMMC0); if(IntFlag) //如果开启了卡全局中断 { Set_IntEnable(INT_HSMMC0,Disable); //先关闭中断,防止误触发 } SDIO_SetDataDataWidth_4b(); //设置SDIO为4bit模式 SDIO_ClearFlag(SDIO_FLAG_ALL); //清除所有标志 if(IntFlag) //如果开启了卡全局中断 { Set_IntEnable(INT_HSMMC0,Enable); //开启 } } } else { errorstatus = SDEnWideBus(Disable); //设置SD卡为1bit总线模式 if (errorstatus == SD_OK) //设置SD卡成功 { IntFlag = Get_IntEnable(INT_HSMMC0); if(IntFlag) //如果开启了卡全局中断 { Set_IntEnable(INT_HSMMC0,Disable); //先关闭中断,防止误触发 } SDIO_SetDataDataWidth_1b(); //设置SDIO为1bit模式 SDIO_ClearFlag(SDIO_FLAG_ALL); //清除所有标志 if(IntFlag) //如果开启了卡全局中断 { Set_IntEnable(INT_HSMMC0,Enable); //开启 } } } } return(errorstatus); } /************************************************************************************************************************* * 函数 : static SD_Error SDEnWideBus(u8 EN) * 功能 : 设置SD卡宽总线模式 * 参数 : Enable:4bit模式;Disable:1bit模式 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120524 * 说明 : 设置SD卡宽总线模式 *************************************************************************************************************************/ static SD_Error SDEnWideBus(u8 EN) { SD_Error errorstatus = SD_OK; u32 scr[2] = {0, 0}; if (SDIO_GetResponse(SDIO_RESP1) & SD_CARD_LOCKED) { errorstatus = SD_LOCK_UNLOCK_FAILED; return(errorstatus); } //获取RCA errorstatus = FindSCR(RCA, scr); if (errorstatus != SD_OK) { DEBUG("Get SCR error(%d)!\n",errorstatus); return(errorstatus); } if (EN) //使能4bit dat { //如果请求的卡支持宽数据线模式 if ((scr[1] & SD_WIDE_BUS_SUPPORT) != SD_ALLZERO) { //发送CMD55,SDIO_APP_CMD,激活卡 //发送CMD55 SDIO_APP_CMD;命令参数:RCA;返回响应R1,设置RCA为0,短响应 SDIO_SendCommand(SDIO_APP_CMD,(u32)RCA << 16,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); if (errorstatus != SD_OK) { DEBUG("CMD55 error(%d)!\n",errorstatus); //调试,打印错误信息 return(errorstatus); } //发送ACMD6,SDIO_APP_SD_SET_BUSWIDTH,设置宽总线模式,参数0x2,短响应,R1 SDIO_SendCommand(SDIO_APP_SD_SET_BUSWIDTH,0x2,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); if (errorstatus != SD_OK) { DEBUG("ACMD6 error(%d)!\n",errorstatus); //调试,打印错误信息 return(errorstatus); } return(errorstatus); } else //请求的卡不支持宽总线模式 { errorstatus = SD_REQUEST_NOT_APPLICABLE; return(errorstatus); } } else //失能宽总线模式 { //如果请求的卡支持1bit总线模式 if ((scr[1] & SD_SINGLE_BUS_SUPPORT) != SD_ALLZERO) { //发送CMD55 SDIO_APP_CMD;命令参数:RCA;返回响应R1,设置RCA为0,短响应 SDIO_SendCommand(SDIO_APP_CMD,(u32)RCA << 16,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); if (errorstatus != SD_OK) { DEBUG("CMD55 error(%d)!\n",errorstatus); //调试,打印错误信息 return(errorstatus); } //发送ACMD6,SDIO_APP_SD_SET_BUSWIDTH,设置宽总线模式,参数0x0,短响应,R1 SDIO_SendCommand(SDIO_APP_SD_SET_BUSWIDTH,0x0,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); if (errorstatus != SD_OK) { DEBUG("ACMD6 error(%d)!\n",errorstatus); //调试,打印错误信息 return(errorstatus); } return(errorstatus); } else //不支持1bit总线模式 { errorstatus = SD_REQUEST_NOT_APPLICABLE; return(errorstatus); } } } /************************************************************************************************************************* * 函数 : SD_Error SD_SetDeviceMode(u32 Mode) * 功能 : 配置SDIO操作模式 * 参数 : SD_DMA_MODE: DMA模式 * SD_INTERRUPT_MODE: 中断模式 * SD_POLLING_MODE: 查询模式(普通模式) * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : 配置SDIO操作模式 *************************************************************************************************************************/ SD_Error SD_SetDeviceMode(u32 Mode) { SD_Error errorstatus = SD_OK; /* if ((Mode == SD_DMA_MODE) || (Mode == SD_INTERRUPT_MODE) || (Mode == SD_POLLING_MODE)) { DeviceMode = Mode; } else { errorstatus = SD_INVALID_PARAMETER; //模式设置错误 }*/ return(errorstatus); } /************************************************************************************************************************* * 函数 : SD_Error SD_SetBlockSize(u16 BlockSize) * 功能 : 设置SD卡块大小 * 参数 : 块大小,512,1024,等等 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : 通常取512B *************************************************************************************************************************/ SD_Error SD_SetBlockSize(u16 BlockSize) { SD_Error errorstatus = SD_OK; //如果卡锁定了则返回 if (SDIO_GetResponse(SDIO_RESP1) & SD_CARD_LOCKED) { errorstatus = SD_LOCK_UNLOCK_FAILED; DEBUG("%d\r\n",errorstatus); return(errorstatus); } //判断块大小是否合理 if ((BlockSize > 0) && (BlockSize <= 2048) && ((BlockSize & (BlockSize - 1)) == 0)) { //Set Block Size for Card SDIO_SendCommand(SDIO_SET_BLOCKLEN,BlockSize,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); if (errorstatus != SD_OK) { DEBUG("%d\r\n",errorstatus); return(errorstatus); } } else //块大小设置错误 { errorstatus = SD_INVALID_PARAMETER; return(errorstatus); } return(errorstatus); } /************************************************************************************************************************* * 函数 : SD_Error SD_ReadBlock(u32 BlockAddr, u32 *BlockBuff) * 功能 : 读SD卡一个块 * 参数 : BlockAddr:块地址; BlockBuff:块缓冲区地址 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120728 * 说明 : 读SD卡一个扇区 *************************************************************************************************************************/ SD_Error SD_ReadBlock(u32 BlockAddr, u32 *BlockBuff) { SD_Error errorstatus = SD_OK; u32 timeout = SDIO_READTIMEOUT; //读等待超时计数器 u16 cnt = 0; if (BlockBuff == NULL) //没有分配接收缓冲区,返回 { errorstatus = SD_INVALID_PARAMETER; return(errorstatus); } SDIO_SoftwareReset(SDIO_RSTDAT); //软件复位DAT,主要用来清空FIFO SDIO_SoftwareReset(SDIO_RSTCMD); //软件复位DAT,主要用来清除状态以及命令 SDIO_ReadMode(); //设置主机控制器为读模式 SDIO_SetTransferBlockSize(SD_BlockSize); //设置单次传输的块大小为SD_BlockSize SDIO_SingleBlockMode(); //设置为单块传输模式 //发送CMD17 READ_SINGLE_BLOCK,块读取指令,参数:块地址,短回复,R1 //此处花了我几天的时间调试,最终发现竟然是少了一条命令:SDIO_DataSelect;当前数据选择,少了这条命令DAT线上没有数据回来 SDIO_SendCommand(SDIO_READ_SINGLE_BLOCK,(BlockAddr << 9),SDIO_DataSelect | SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); //获取回复 if (errorstatus != SD_OK) //命令发送错误,返回 { DEBUG("CMD17 error (%d)!\n",errorstatus); return(errorstatus); } while(((SDIO0->PRNSTS & BIT11) == 0) && timeout && (SDIO_GetFlagStatus(SDIO_FLAG_DATATIMEOUT) == 0)) //等待读缓冲区有效,或者等待超时 { timeout --; } if (SDIO_GetFlagStatus(SDIO_FLAG_DATATIMEOUT) || (timeout == 0)) //超时 { SDIO_ClearFlag(SDIO_FLAG_DATATIMEOUT); //清除标志 errorstatus = SD_DATA_TIMEOUT; DEBUG("%d\r\n",errorstatus); return(errorstatus); } //缓冲区大小SD_BlockSize字节,共SD_BlockSize/4字 for(cnt = 0;cnt < SD_BlockSize / 4;cnt ++) { *(BlockBuff ++) = SDIO_ReadData(); } //清除所有标志 SDIO_ClearFlag(SDIO_FLAG_ALL); return(errorstatus); } /************************************************************************************************************************* * 函数 : SD_Error SD_ReadMultiBlocks(u32 BlockAddr, u32 *BlockBuff, u32 NumberOfBlocks) * 功能 : 读SD卡多个块 * 参数 : BlockAddr:块地址; BlockBuff:块缓冲区地址 NumberOfBlocks:块数量 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120728 * 说明 : 读SD卡多个(大于1个)扇区 *************************************************************************************************************************/ SD_Error SD_ReadMultiBlocks(u32 BlockAddr, u32 *BlockBuff, u16 NumberOfBlocks) { SD_Error errorstatus = SD_OK; u32 timeout = SDIO_READTIMEOUT;//读等待超时计数器 u16 BlockCnt = NumberOfBlocks; //需要传输的块计数 u16 cnt = 0; if (BlockBuff == NULL) //没有分配接收缓冲区,返回 { errorstatus = SD_INVALID_PARAMETER; DEBUG("%d\r\n",errorstatus); return(errorstatus); } if (NumberOfBlocks > 1) { if (NumberOfBlocks * SD_BlockSize > SD_MAX_DATA_LENGTH)//判定地址是否超出范围 { errorstatus = SD_INVALID_PARAMETER; DEBUG("%d\r\n",errorstatus); return(errorstatus); } SDIO_SoftwareReset(SDIO_RSTDAT); //软件复位DAT,主要用来清空FIFO SDIO_SoftwareReset(SDIO_RSTCMD); //软件复位DAT,主要用来清除状态以及命令 SDIO_MultipleBlockMode(); //设置为多区段传输模式 SDIO_SetTransferBlockCnt(NumberOfBlocks); //设置传输块数量 SDIO_SetTransferBlockSize(SD_BlockSize); //设置单次传输的块大小为SD_BlockSize SDIO_ReadMode(); //设置为读数据模式 SDIO_BlockCountEnable(); //块计数启动 //发送CMD18 SDIO_READ_MULT_BLOCK;多区段读命令,参数:开始地址,短返回,R1 SDIO_SendCommand(SDIO_READ_MULT_BLOCK,(BlockAddr << 9),SDIO_DataSelect | SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); if (errorstatus != SD_OK) { DEBUG("%d\r\n",errorstatus); return(errorstatus); } do { if(SDIO0->PRNSTS & BIT11) //读缓冲区有效 { SDIO_ClearFlag(SDIO_FLAG_BUFFREAD); //清除读缓冲区有效标志 //缓冲区大小SD_BlockSize字节,共SD_BlockSize/4字 for(cnt = 0;cnt < SD_BlockSize / 4;cnt ++) { *(BlockBuff ++) = SDIO_ReadData(); } BlockCnt --; //读完了一块 timeout = SDIO_READTIMEOUT; //读完了一块,超时计数器重新开始计数 } timeout --; }while(BlockCnt && (timeout != 0) && (SDIO_GetFlagStatus(SDIO_FLAG_DATATIMEOUT) == 0)); //剩余块数量不为0,没超时 //发送CMD12 SDIO_STOP_TRANSMISSION命令,终止读取;参数:0,短响应,R1 SDIO_SendCommand(SDIO_STOP_TRANSMISSION,0,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); if (errorstatus != SD_OK) { DEBUG("%d\r\n",errorstatus); return(errorstatus); } if(timeout == 0) //超时 { errorstatus = SD_DATA_TIMEOUT; DEBUG("%d\r\n",errorstatus); return(errorstatus); } SDIO_ClearFlag(SDIO_FLAG_ALL); //清除所有中断标志 } return(errorstatus); } /************************************************************************************************************************* * 函数 : SD_Error SD_WriteBlock(u32 BlockAddr, u32 *BlockBuff) * 功能 : 写SD卡一个块 * 参数 : BlockAddr:块地址; writebuff:写缓冲区地址 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120525 * 最后修改时间 : 20120728 * 说明 : 写SD卡一个扇区 * 20120728:修改了写入函数,现在可以成功写入数据 *************************************************************************************************************************/ SD_Error SD_WriteBlock(u32 BlockAddr, u32 *BlockBuff) { SD_Error errorstatus = SD_OK; u32 timeout = SDIO_WRITETIMEOUT; //写等待超时计数器 u32 cardstatus = 0; u8 cardstate = 0; u16 cnt = 0; if (BlockBuff == NULL) { errorstatus = SD_INVALID_PARAMETER; DEBUG("%d\r\n",errorstatus); return(errorstatus); } SDIO_SoftwareReset(SDIO_RSTDAT); //软件复位DAT,主要用来清空FIFO SDIO_SoftwareReset(SDIO_RSTCMD); //软件复位DAT,主要用来清除状态以及命令 SDIO_WriteMode(); //设置主机控制器为写模式 SDIO_SetTransferBlockSize(SD_BlockSize); //设置单次传输的块大小为SD_BlockSize SDIO_SingleBlockMode(); //设置为单块传输模式 do { timeout --; //发送CMD13,SDIO_SEND_STATUS,读 Card_Status 寄存器,参数,RCA地址,短返回,R1; SDIO_SendCommand(SDIO_SEND_STATUS,(u32) RCA << 16,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); if (errorstatus != SD_OK) { DEBUG("%d\r\n",errorstatus); return(errorstatus); } cardstatus = SDIO_GetResponse(SDIO_RESP1); } while (((cardstatus & 0x00000100) == 0) && (timeout > 0)); if (timeout == 0) { DEBUG("%d\r\n",errorstatus); return(SD_ERROR); } //发送CMD24,SDIO_WRITE_SINGLE_BLOCK,写命令,参数:地址,短响应,R1 SDIO_SendCommand(SDIO_WRITE_SINGLE_BLOCK,(BlockAddr << 9),SDIO_DataSelect | SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); if (errorstatus != SD_OK) { DEBUG("%d\r\n",errorstatus); return(errorstatus); } timeout = SDIO_WRITETIMEOUT; //写等待超时计数器 //写缓冲区是否有效应该判断PRNSTS这个寄存器 while(((SDIO0->PRNSTS & BIT10) == 0) && (SDIO_GetFlagStatus(SDIO_FLAG_BUFFWRITE) == 0) && timeout && (SDIO_GetFlagStatus(SDIO_FLAG_DATATIMEOUT) == 0)) //等待写缓冲区有效,或者等待超时 { timeout --; } if (SDIO_GetFlagStatus(SDIO_FLAG_DATATIMEOUT) || (timeout == 0)) //超时 { SDIO_ClearFlag(SDIO_FLAG_DATATIMEOUT); //清除标志 errorstatus = SD_DATA_TIMEOUT; DEBUG("%d\r\n",errorstatus); return(errorstatus); } //缓冲区大小SD_BlockSize字节,共SD_BlockSize / 4字 for(cnt = 0;cnt < SD_BlockSize / 4;cnt ++) { SDIO_WriteData(BlockBuff[cnt]); } //清除所有标志 SDIO_ClearFlag(SDIO_FLAG_ALL); //读取卡状态,等待写入完成 do { errorstatus = IsCardProgramming(&cardstate); }while ((errorstatus == SD_OK) && ((cardstate == SD_CARD_PROGRAMMING) || (cardstate == SD_CARD_RECEIVING))); return(errorstatus); } /************************************************************************************************************************* * 函数 : SD_Error SD_WriteMultiBlocks(u32 BlockAddr, u32 *BlockBuff, u16 NumberOfBlocks) * 功能 : 写SD卡多个块 * 参数 : BlockAddr:块地址; BlockBuff:块缓冲区地址 NumberOfBlocks:块数量 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120525 * 最后修改时间 : 20120728 * 说明 : 写SD卡多个(大于1个)扇区 * 20120728:修改了写入函数,现在可以成功写入数据 *************************************************************************************************************************/ SD_Error SD_WriteMultiBlocks(u32 BlockAddr, u32 *BlockBuff, u16 NumberOfBlocks) { SD_Error errorstatus = SD_OK; u32 timeout = SDIO_WRITETIMEOUT; //写等待超时计数器 u16 BlockCnt = NumberOfBlocks; //传输的块数量计数 u8 cardstate = 0; u32 cardstatus = 0; u16 cnt = 0; if (BlockBuff == NULL) { errorstatus = SD_INVALID_PARAMETER; DEBUG("%d\r\n",errorstatus); return(errorstatus); } if (NumberOfBlocks > 1) { if (NumberOfBlocks * SD_BlockSize > SD_MAX_DATA_LENGTH) //判断地址 { errorstatus = SD_INVALID_PARAMETER; DEBUG("%d\r\n",errorstatus); return(errorstatus); } SDIO_SoftwareReset(SDIO_RSTDAT); //软件复位DAT,主要用来清空FIFO SDIO_SoftwareReset(SDIO_RSTCMD); //软件复位DAT,主要用来清除状态以及命令 SDIO_MultipleBlockMode(); //设置为多区段传输模式 SDIO_SetTransferBlockCnt(NumberOfBlocks); //设置传输块数量 SDIO_SetTransferBlockSize(SD_BlockSize); //设置单次传输的块大小为SD_BlockSize SDIO_WriteMode(); //设置为写数据模式 SDIO_BlockCountEnable(); //块计数启动 do { timeout --; //发送CMD13,SDIO_SEND_STATUS,读 Card_Status 寄存器,参数,RCA地址,短返回,R1; SDIO_SendCommand(SDIO_SEND_STATUS,(u32) RCA << 16,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); if (errorstatus != SD_OK) { DEBUG("%d\r\n",errorstatus); return(errorstatus); } cardstatus = SDIO_GetResponse(SDIO_RESP1); } while (((cardstatus & 0x00000100) == 0) && (timeout > 0)); if (timeout == 0) { DEBUG("%d\r\n",errorstatus); return(SD_ERROR); } timeout = SDIO_WRITETIMEOUT; //发送CMD25,SDIO_WRITE_MULT_BLOCK,参数:字节地址,短返回,R1 SDIO_SendCommand(SDIO_WRITE_MULT_BLOCK,(BlockAddr << 9),SDIO_DataSelect | SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); if (errorstatus != SD_OK) { DEBUG("%d\r\n",errorstatus); return(errorstatus); } do { if(SDIO0->PRNSTS & BIT10) //写缓冲区有效 { SDIO_ClearFlag(SDIO_FLAG_BUFFWRITE); //清除写缓冲区有效标志 //缓冲区大小SD_BlockSize字节,共SD_BlockSize / 4字 for(cnt = 0;cnt < SD_BlockSize / 4;cnt ++) { SDIO_WriteData(*BlockBuff ++); } BlockCnt --; //读完了一块 timeout = SDIO_READTIMEOUT; //读完了一块,超时计数器重新开始计数 } timeout --; }while(BlockCnt && (timeout != 0) && (SDIO_GetFlagStatus(SDIO_FLAG_DATATIMEOUT) == 0)); //剩余块数量不为0,没超时 //发送CMD12 SDIO_STOP_TRANSMISSION命令,终止读取;参数:0,短响应,R1 SDIO_SendCommand(SDIO_STOP_TRANSMISSION,0,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); if (errorstatus != SD_OK) { DEBUG("%d\r\n",errorstatus); return(errorstatus); } if(timeout == 0) //超时 { errorstatus = SD_DATA_TIMEOUT; DEBUG("%d\r\n",errorstatus); return(errorstatus); } SDIO_ClearFlag(SDIO_FLAG_ALL); //清除所有中断标志 } //读取卡状态,等待写入完成 do { errorstatus = IsCardProgramming(&cardstate); }while ((errorstatus == SD_OK) && ((cardstate == SD_CARD_PROGRAMMING) || (cardstate == SD_CARD_RECEIVING))); return(errorstatus); } /************************************************************************************************************************* * 函数 : static SD_Error CmdError(void) * 功能 : 指令执行状态(无响应) * 参数 : 无 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : 返回指令执行结果(内部函数) *************************************************************************************************************************/ static SD_Error CmdError(void) { SD_Error errorstatus = SD_OK; u32 timeout; timeout = SDIO_CMD0TIMEOUT; while ((timeout > 0) && (SDIO_GetFlagStatus(SDIO_FLAG_COMMANDEND) == 0)) { timeout--; } if (timeout == 0) { errorstatus = SD_CMD_RSP_TIMEOUT; return(errorstatus); } //清除所有标志 SDIO_ClearFlag(SDIO_FLAG_ALL); return(errorstatus); } /************************************************************************************************************************* * 函数 : static SD_Error CmdResp7Error(void) * 功能 : 指令执行状态(R7) * 参数 : 无 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : 返回指令执行结果(内部函数) *************************************************************************************************************************/ static SD_Error CmdResp7Error(void) { SD_Error errorstatus = SD_OK; // u32 status; u32 timeout = SDIO_CMD0TIMEOUT; do { timeout--; } while (!(SDIO_STATUS & (SDIO_FLAG_COMMANDCRC | SDIO_FLAG_COMMANDEND | SDIO_FLAG_COMMANDTIMEOUT)) && (timeout > 0)); if ((timeout == 0) || (SDIO_STATUS & SDIO_FLAG_COMMANDTIMEOUT)) { /* Card is not V2.0 complient or card does not support the set voltage range */ errorstatus = SD_CMD_RSP_TIMEOUT; SDIO_ClearFlag(SDIO_FLAG_COMMANDTIMEOUT); return(errorstatus); } if (SDIO_STATUS & SDIO_FLAG_COMMANDEND) { /* Card is SD V2.0 compliant */ errorstatus = SD_OK; SDIO_ClearFlag(SDIO_FLAG_COMMANDEND); return(errorstatus); } //清除所有标志 SDIO_ClearFlag(SDIO_FLAG_ALL); return(errorstatus); } /************************************************************************************************************************* * 函数 : static SD_Error CmdResp1Error(void) * 功能 : 指令执行状态(R1) * 参数 : 无 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : 返回指令执行结果(内部函数) *************************************************************************************************************************/ static SD_Error CmdResp1Error(void) { SD_Error errorstatus = SD_OK; u32 response_r1; while (!(SDIO_STATUS & (SDIO_FLAG_COMMANDCRC | SDIO_FLAG_COMMANDEND | SDIO_FLAG_COMMANDTIMEOUT | SDIO_FLAG_COMMANDINDEX))); if (SDIO_STATUS & SDIO_FLAG_COMMANDTIMEOUT) { errorstatus = SD_CMD_RSP_TIMEOUT; SDIO_ClearFlag(SDIO_FLAG_COMMANDTIMEOUT); return(errorstatus); } else if (SDIO_STATUS & SDIO_FLAG_COMMANDCRC) { errorstatus = SD_CMD_CRC_FAIL; SDIO_ClearFlag(SDIO_FLAG_COMMANDCRC); return(errorstatus); } else if (SDIO_STATUS & SDIO_FLAG_COMMANDINDEX) { errorstatus = SD_ILLEGAL_CMD; SDIO_ClearFlag(SDIO_FLAG_COMMANDINDEX); return(errorstatus); } //清除所有标志 SDIO_ClearFlag(SDIO_FLAG_ALL); /* We have received response, retrieve it for analysis */ response_r1 = SDIO_GetResponse(SDIO_RESP1); if ((response_r1 & SD_OCR_ERRORBITS) == SD_ALLZERO) { return(errorstatus); } if (response_r1 & SD_OCR_ADDR_OUT_OF_RANGE) { return(SD_ADDR_OUT_OF_RANGE); } if (response_r1 & SD_OCR_ADDR_MISALIGNED) { return(SD_ADDR_MISALIGNED); } if (response_r1 & SD_OCR_BLOCK_LEN_ERR) { return(SD_BLOCK_LEN_ERR); } if (response_r1 & SD_OCR_ERASE_SEQ_ERR) { return(SD_ERASE_SEQ_ERR); } if (response_r1 & SD_OCR_BAD_ERASE_PARAM) { return(SD_BAD_ERASE_PARAM); } if (response_r1 & SD_OCR_WRITE_PROT_VIOLATION) { return(SD_WRITE_PROT_VIOLATION); } if (response_r1 & SD_OCR_LOCK_UNLOCK_FAILED) { return(SD_LOCK_UNLOCK_FAILED); } if (response_r1 & SD_OCR_COM_CRC_FAILED) { return(SD_COM_CRC_FAILED); } if (response_r1 & SD_OCR_ILLEGAL_CMD) { return(SD_ILLEGAL_CMD); } if (response_r1 & SD_OCR_CARD_ECC_FAILED) { return(SD_CARD_ECC_FAILED); } if (response_r1 & SD_OCR_CC_ERROR) { return(SD_CC_ERROR); } if (response_r1 & SD_OCR_GENERAL_UNKNOWN_ERROR) { return(SD_GENERAL_UNKNOWN_ERROR); } if (response_r1 & SD_OCR_STREAM_READ_UNDERRUN) { return(SD_STREAM_READ_UNDERRUN); } if (response_r1 & SD_OCR_STREAM_WRITE_OVERRUN) { return(SD_STREAM_WRITE_OVERRUN); } if (response_r1 & SD_OCR_CID_CSD_OVERWRIETE) { return(SD_CID_CSD_OVERWRITE); } if (response_r1 & SD_OCR_WP_ERASE_SKIP) { return(SD_WP_ERASE_SKIP); } if (response_r1 & SD_OCR_CARD_ECC_DISABLED) { return(SD_CARD_ECC_DISABLED); } if (response_r1 & SD_OCR_ERASE_RESET) { return(SD_ERASE_RESET); } if (response_r1 & SD_OCR_AKE_SEQ_ERROR) { return(SD_AKE_SEQ_ERROR); } return(errorstatus); } /************************************************************************************************************************* * 函数 : static SD_Error CmdResp3Error(void) * 功能 : 指令执行状态(R3,OCR) * 参数 : 无 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : 返回指令执行结果(内部函数) *************************************************************************************************************************/ static SD_Error CmdResp3Error(void) { SD_Error errorstatus = SD_OK; // u32 status; while (!(SDIO_STATUS & (SDIO_FLAG_COMMANDCRC | SDIO_FLAG_COMMANDEND | SDIO_FLAG_COMMANDTIMEOUT))); if (SDIO_STATUS & SDIO_FLAG_COMMANDTIMEOUT) { errorstatus = SD_CMD_RSP_TIMEOUT; SDIO_ClearFlag(SDIO_FLAG_COMMANDTIMEOUT); return(errorstatus); } //清除所有标志 SDIO_ClearFlag(SDIO_FLAG_ALL); return(errorstatus); } /************************************************************************************************************************* * 函数 : static SD_Error CmdResp2Error(void) * 功能 : 指令执行状态(R2,CID or CSD) * 参数 : 无 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : 返回指令执行结果(内部函数) *************************************************************************************************************************/ static SD_Error CmdResp2Error(void) { SD_Error errorstatus = SD_OK; // u32 status; while (!(SDIO_STATUS & (SDIO_FLAG_COMMANDCRC | SDIO_FLAG_COMMANDEND | SDIO_FLAG_COMMANDTIMEOUT))); if (SDIO_STATUS & SDIO_FLAG_COMMANDTIMEOUT) { errorstatus = SD_CMD_RSP_TIMEOUT; SDIO_ClearFlag(SDIO_FLAG_COMMANDTIMEOUT); return(errorstatus); } else if (SDIO_STATUS & SDIO_FLAG_COMMANDCRC) { errorstatus = SD_CMD_CRC_FAIL; SDIO_ClearFlag(SDIO_FLAG_COMMANDCRC); return(errorstatus); } //清除所有标志 SDIO_ClearFlag(SDIO_FLAG_ALL); return(errorstatus); } /************************************************************************************************************************* * 函数 : static SD_Error CmdResp6Error(u16 *prca) * 功能 : 指令执行状态(R6,RCA) * 参数 : prca:RCA缓冲区指针 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : 返回指令执行结果(内部函数) *************************************************************************************************************************/ static SD_Error CmdResp6Error(u16 *prca) { SD_Error errorstatus = SD_OK; // u32 status; u32 response_r1; while (!(SDIO_STATUS & (SDIO_FLAG_COMMANDCRC | SDIO_FLAG_COMMANDEND | SDIO_FLAG_COMMANDTIMEOUT | SDIO_FLAG_COMMANDINDEX))); if (SDIO_STATUS & SDIO_FLAG_COMMANDTIMEOUT) { errorstatus = SD_CMD_RSP_TIMEOUT; SDIO_ClearFlag(SDIO_FLAG_COMMANDTIMEOUT); return(errorstatus); } else if (SDIO_STATUS & SDIO_FLAG_COMMANDCRC) { errorstatus = SD_CMD_CRC_FAIL; SDIO_ClearFlag(SDIO_FLAG_COMMANDCRC); return(errorstatus); } else if (SDIO_STATUS & SDIO_FLAG_COMMANDINDEX) { errorstatus = SD_ILLEGAL_CMD; SDIO_ClearFlag(SDIO_FLAG_COMMANDINDEX); return(errorstatus); } //清除所有标志 SDIO_ClearFlag(SDIO_FLAG_ALL); /* We have received response, retrieve it. */ response_r1 = SDIO_GetResponse(SDIO_RESP1); if (SD_ALLZERO == (response_r1 & (SD_R6_GENERAL_UNKNOWN_ERROR | SD_R6_ILLEGAL_CMD | SD_R6_COM_CRC_FAILED))) { *prca = (u16) (response_r1 >> 16); return(errorstatus); } if (response_r1 & SD_R6_GENERAL_UNKNOWN_ERROR) { return(SD_GENERAL_UNKNOWN_ERROR); } if (response_r1 & SD_R6_ILLEGAL_CMD) { return(SD_ILLEGAL_CMD); } if (response_r1 & SD_R6_COM_CRC_FAILED) { return(SD_COM_CRC_FAILED); } return(errorstatus); } /************************************************************************************************************************* * 函数 : static SD_Error FindSCR(u16 rca, u32 *pscr) * 功能 : 获取SCR信息 * 参数 : rca:卡地址,prca:RCA缓冲区指针 * 返回 : SD_OK:成功,其它见SD Card Error code. * 依赖 : 底层寄存器操作函数 * 作者 : 陈鹏 * 时间 : 20120516 * 最后修改时间 : 20120516 * 说明 : 返回指令执行结果(内部函数) *************************************************************************************************************************/ static SD_Error FindSCR(u16 rca, u32 *pscr) { SD_Error errorstatus = SD_OK; u32 tempscr[2] = {0, 0}; u32 timeout = SDIO_READTIMEOUT;//读等待超时计数器 //设置块大小为8字节 //发送SDIO_SET_BLOCKLEN,参数8,短响应 SDIO_SendCommand(SDIO_SET_BLOCKLEN,8,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); if (errorstatus != SD_OK) { DEBUG("SDIO_SET_BLOCKLEN error(%d)!\n",errorstatus); //调试,打印错误信息 goto _error; } //发送CMD55 SDIO_APP_CMD;命令参数:RCA;返回响应R1,设置RCA为0,短响应 SDIO_SendCommand(SDIO_APP_CMD,(u32)rca << 16,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); if (errorstatus != SD_OK) { DEBUG("CMD55 error(%d)!\n",errorstatus); //调试,打印错误信息 goto _error; } SDIO_SoftwareReset(SDIO_RSTDAT); //软件复位DAT,主要用来清空FIFO SDIO_ReadMode(); //设置主机控制器为读模式 SDIO_SetTransferBlockSize(8); //设置单次传输的块大小为8b SDIO_SingleBlockMode(); //设置为单块传输模式 //发送ACMD51 SD_APP_SEND_SCR,参数0,短响应,R1 SDIO_SendCommand(SDIO_SD_APP_SEND_SCR,0,SDIO_DataSelect | SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); errorstatus = CmdResp1Error(); if (errorstatus != SD_OK) { DEBUG("ACMD51 error(%d)!\n",errorstatus); //调试,打印错误信息 goto _error; } while((SDIO_GetFlagStatus(SDIO_FLAG_BUFFREAD) == 0) && timeout && (SDIO_GetFlagStatus(SDIO_FLAG_DATATIMEOUT) == 0)) //等待读缓冲区有效,或者等待超时 { timeout --; } if (SDIO_GetFlagStatus(SDIO_FLAG_DATATIMEOUT) || (timeout == 0)) //超时 { SDIO_ClearFlag(SDIO_FLAG_DATATIMEOUT); //清除标志 errorstatus = SD_DATA_TIMEOUT; goto _error; } //缓冲区大小8字节,共2字 tempscr[0] = SDIO_ReadData(); tempscr[1] = SDIO_ReadData(); //清除所有标志 SDIO_ClearFlag(SDIO_FLAG_ALL); *(pscr + 1) = ((tempscr[0] & SD_0TO7BITS) << 24) | ((tempscr[0] & SD_8TO15BITS) << 8) | ((tempscr[0] & SD_16TO23BITS) >> 8) | ((tempscr[0] & SD_24TO31BITS) >> 24); *(pscr) = ((tempscr[1] & SD_0TO7BITS) << 24) | ((tempscr[1] & SD_8TO15BITS) << 8) | ((tempscr[1] & SD_16TO23BITS) >> 8) | ((tempscr[1] & SD_24TO31BITS) >> 24); _error: //恢复块大小为 SD_BlockSize SDIO_SetTransferBlockSize(SD_BlockSize);//设置传输块大小为512字节 errorstatus = SD_SetBlockSize(SD_BlockSize);//配置SD卡块大小 if (errorstatus != SD_OK) { DEBUG("SD SetBlockSize error(%d)!\n",errorstatus); return(errorstatus); } return(errorstatus); } /******************************************************************************* * Function Name : IsCardProgramming * Description : Checks if the SD card is in programming state. * Input : pstatus: pointer to the variable that will contain the SD * card state. * Output : None * Return : SD_Error: SD Card Error code. *******************************************************************************/ static SD_Error IsCardProgramming(u8 *pstatus) { SD_Error errorstatus = SD_OK; vu32 respR1 = 0, status = 0; //发送SDIO_SEND_STATUS,返回状态 SDIO_SendCommand(SDIO_SEND_STATUS,(u32) RCA << 16,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short); while (!(SDIO_STATUS & (SDIO_FLAG_COMMANDCRC | SDIO_FLAG_COMMANDEND | SDIO_FLAG_COMMANDTIMEOUT | SDIO_FLAG_COMMANDINDEX))); if (SDIO_STATUS & SDIO_FLAG_COMMANDTIMEOUT) { errorstatus = SD_CMD_RSP_TIMEOUT; SDIO_ClearFlag(SDIO_FLAG_COMMANDTIMEOUT); return(errorstatus); } else if (SDIO_STATUS & SDIO_FLAG_COMMANDCRC) { errorstatus = SD_CMD_CRC_FAIL; SDIO_ClearFlag(SDIO_FLAG_COMMANDCRC); return(errorstatus); } else if (SDIO_STATUS & SDIO_FLAG_COMMANDINDEX) { errorstatus = SD_ILLEGAL_CMD; SDIO_ClearFlag(SDIO_FLAG_COMMANDINDEX); return(errorstatus); } //清除所有标志 SDIO_ClearFlag(SDIO_FLAG_ALL); /* We have received response, retrieve it for analysis */ respR1 = SDIO_GetResponse(SDIO_RESP1); /* Find out card status */ *pstatus = (u8) ((respR1 >> 9) & 0x0000000F); if ((respR1 & SD_OCR_ERRORBITS) == SD_ALLZERO) { return(errorstatus); } if (respR1 & SD_OCR_ADDR_OUT_OF_RANGE) { return(SD_ADDR_OUT_OF_RANGE); } if (respR1 & SD_OCR_ADDR_MISALIGNED) { return(SD_ADDR_MISALIGNED); } if (respR1 & SD_OCR_BLOCK_LEN_ERR) { return(SD_BLOCK_LEN_ERR); } if (respR1 & SD_OCR_ERASE_SEQ_ERR) { return(SD_ERASE_SEQ_ERR); } if (respR1 & SD_OCR_BAD_ERASE_PARAM) { return(SD_BAD_ERASE_PARAM); } if (respR1 & SD_OCR_WRITE_PROT_VIOLATION) { return(SD_WRITE_PROT_VIOLATION); } if (respR1 & SD_OCR_LOCK_UNLOCK_FAILED) { return(SD_LOCK_UNLOCK_FAILED); } if (respR1 & SD_OCR_COM_CRC_FAILED) { return(SD_COM_CRC_FAILED); } if (respR1 & SD_OCR_ILLEGAL_CMD) { return(SD_ILLEGAL_CMD); } if (respR1 & SD_OCR_CARD_ECC_FAILED) { return(SD_CARD_ECC_FAILED); } if (respR1 & SD_OCR_CC_ERROR) { return(SD_CC_ERROR); } if (respR1 & SD_OCR_GENERAL_UNKNOWN_ERROR) { return(SD_GENERAL_UNKNOWN_ERROR); } if (respR1 & SD_OCR_STREAM_READ_UNDERRUN) { return(SD_STREAM_READ_UNDERRUN); } if (respR1 & SD_OCR_STREAM_WRITE_OVERRUN) { return(SD_STREAM_WRITE_OVERRUN); } if (respR1 & SD_OCR_CID_CSD_OVERWRIETE) { return(SD_CID_CSD_OVERWRITE); } if (respR1 & SD_OCR_WP_ERASE_SKIP) { return(SD_WP_ERASE_SKIP); } if (respR1 & SD_OCR_CARD_ECC_DISABLED) { return(SD_CARD_ECC_DISABLED); } if (respR1 & SD_OCR_ERASE_RESET) { return(SD_ERASE_RESET); } if (respR1 & SD_OCR_AKE_SEQ_ERROR) { return(SD_AKE_SEQ_ERROR); } return(errorstatus); } //SD卡中断服务程序,用来检测卡的插入与移除的 static void __irq Isr_SDMMC_Card(void) { if(SDIO_GetFlagStatus(SDIO_FLAG_CARDREMOVAL)) //卡移除了 { // DEBUG("SDMMC Card MOVAL!\n"); //调试,打印错误信息 SDIO_ClearFlag(SDIO_FLAG_CARDREMOVAL); //清除卡移除中断 SDMMC0_MOV_Flag = 1; //卡移除了 } if(SDIO_GetFlagStatus(SDIO_FLAG_CARDINSERTION)) //卡插入了 { // DEBUG("SDMMC Card IN!\n"); //调试,打印错误信息 SDIO_ClearFlag(SDIO_FLAG_CARDINSERTION); //清除卡插入中断 } VICInterruptEnd(); //中断结束 }
</pre>sdcard_sdio.h<pre name="code" class="cpp">#ifndef _SDCARD_SDIO_H_ #define _SDCARD_SDIO_H_ #include "s3c6410_system.h" extern u8 SDMMC0_MOV_Flag; //卡移除信号 /* Exported types ------------------------------------------------------------*/ typedef enum { /* SDIO specific error defines */ SD_CMD_CRC_FAIL = (1), /* Command response received (but CRC check failed) */ SD_DATA_CRC_FAIL = (2), /* Data bock sent/received (CRC check Failed) */ SD_CMD_RSP_TIMEOUT = (3), /* Command response timeout */ SD_DATA_TIMEOUT = (4), /* Data time out */ SD_TX_UNDERRUN = (5), /* Transmit FIFO under-run */ SD_RX_OVERRUN = (6), /* Receive FIFO over-run */ SD_START_BIT_ERR = (7), /* Start bit not detected on all data signals in widE bus mode */ SD_CMD_OUT_OF_RANGE = (8), /* CMD's argument was out of range.*/ SD_ADDR_MISALIGNED = (9), /* Misaligned address */ SD_BLOCK_LEN_ERR = (10), /* Transferred block length is not allowed for the card or the number of transferred bytes does not match the block length */ SD_ERASE_SEQ_ERR = (11), /* An error in the sequence of erase command occurs.*/ SD_BAD_ERASE_PARAM = (12), /* An Invalid selection for erase groups */ SD_WRITE_PROT_VIOLATION = (13), /* Attempt to program a write protect block */ SD_LOCK_UNLOCK_FAILED = (14), /* Sequence or password error has been detected in unlock command or if there was an attempt to access a locked card */ SD_COM_CRC_FAILED = (15), /* CRC check of the previous command failed */ SD_ILLEGAL_CMD = (16), /* Command is not legal for the card state */ SD_CARD_ECC_FAILED = (17), /* Card internal ECC was applied but failed to correct the data */ SD_CC_ERROR = (18), /* Internal card controller error */ SD_GENERAL_UNKNOWN_ERROR = (19), /* General or Unknown error */ SD_STREAM_READ_UNDERRUN = (20), /* The card could not sustain data transfer in stream read operation. */ SD_STREAM_WRITE_OVERRUN = (21), /* The card could not sustain data programming in stream mode */ SD_CID_CSD_OVERWRITE = (22), /* CID/CSD overwrite error */ SD_WP_ERASE_SKIP = (23), /* only partial address space was erased */ SD_CARD_ECC_DISABLED = (24), /* Command has been executed without using internal ECC */ SD_ERASE_RESET = (25), /* Erase sequence was cleared before executing because an out of erase sequence command was received */ SD_AKE_SEQ_ERROR = (26), /* Error in sequence of authentication. */ SD_INVALID_VOLTRANGE = (27), SD_ADDR_OUT_OF_RANGE = (28), SD_SWITCH_ERROR = (29), SD_SDIO_DISABLED = (30), SD_SDIO_FUNCTION_BUSY = (31), SD_SDIO_FUNCTION_FAILED = (32), SD_SDIO_UNKNOWN_FUNCTION = (33), /* Standard error defines */ SD_INTERNAL_ERROR, SD_NOT_CONFIGURED, SD_REQUEST_PENDING, SD_REQUEST_NOT_APPLICABLE, SD_INVALID_PARAMETER, SD_UNSUPPORTED_FEATURE, SD_UNSUPPORTED_HW, SD_ERROR, SD_OK, } SD_Error; /* SDIO Commands Index */ #define SDIO_GO_IDLE_STATE ((u8)0) #define SDIO_SEND_OP_COND ((u8)1) #define SDIO_ALL_SEND_CID ((u8)2) #define SDIO_SET_REL_ADDR ((u8)3) /* SDIO_SEND_REL_ADDR for SD Card */ #define SDIO_SET_DSR ((u8)4) #define SDIO_SDIO_SEN_OP_COND ((u8)5) #define SDIO_HS_SWITCH ((u8)6) #define SDIO_SEL_DESEL_CARD ((u8)7) #define SDIO_HS_SEND_EXT_CSD ((u8)8) #define SDIO_SEND_CSD ((u8)9) #define SDIO_SEND_CID ((u8)10) #define SDIO_READ_DAT_UNTIL_STOP ((u8)11) /* SD Card doesn't support it */ #define SDIO_STOP_TRANSMISSION ((u8)12) #define SDIO_SEND_STATUS ((u8)13) #define SDIO_HS_BUSTEST_READ ((u8)14) #define SDIO_GO_INACTIVE_STATE ((u8)15) #define SDIO_SET_BLOCKLEN ((u8)16) #define SDIO_READ_SINGLE_BLOCK ((u8)17) #define SDIO_READ_MULT_BLOCK ((u8)18) #define SDIO_HS_BUSTEST_WRITE ((u8)19) #define SDIO_WRITE_DAT_UNTIL_STOP ((u8)20) /* SD Card doesn't support it */ #define SDIO_SET_BLOCK_COUNT ((u8)23) /* SD Card doesn't support it */ #define SDIO_WRITE_SINGLE_BLOCK ((u8)24) #define SDIO_WRITE_MULT_BLOCK ((u8)25) #define SDIO_PROG_CID ((u8)26) /* reserved for manufacturers */ #define SDIO_PROG_CSD ((u8)27) #define SDIO_SET_WRITE_PROT ((u8)28) #define SDIO_CLR_WRITE_PROT ((u8)29) #define SDIO_SEND_WRITE_PROT ((u8)30) #define SDIO_SD_ERASE_GRP_START ((u8)32) /* To set the address of the first write block to be erased. (For SD card only) */ #define SDIO_SD_ERASE_GRP_END ((u8)33) /* To set the address of the last write block of the continuous range to be erased. (For SD card only) */ #define SDIO_ERASE_GRP_START ((u8)35) /* To set the address of the first write block to be erased. (For MMC card only spec 3.31) */ #define SDIO_ERASE_GRP_END ((u8)36) /* To set the address of the last write block of the continuous range to be erased. (For MMC card only spec 3.31) */ #define SDIO_ERASE ((u8)38) #define SDIO_FAST_IO ((u8)39) /* SD Card doesn't support it */ #define SDIO_GO_IRQ_STATE ((u8)40) /* SD Card doesn't support it */ #define SDIO_LOCK_UNLOCK ((u8)42) #define SDIO_APP_CMD ((u8)55) #define SDIO_GEN_CMD ((u8)56) #define SDIO_NO_CMD ((u8)64) /* Following commands are SD Card Specific commands. SDIO_APP_CMD should be sent before sending these commands. */ #define SDIO_APP_SD_SET_BUSWIDTH ((u8)6) /* For SD Card only */ #define SDIO_SD_APP_STAUS ((u8)13) /* For SD Card only */ #define SDIO_SD_APP_SEND_NUM_WRITE_BLOCKS ((u8)22) /* For SD Card only */ #define SDIO_SD_APP_OP_COND ((u8)41) /* For SD Card only */ #define SDIO_SD_APP_SET_CLR_CARD_DETECT ((u8)42) /* For SD Card only */ #define SDIO_SD_APP_SEND_SCR ((u8)51) /* For SD Card only */ #define SDIO_SDIO_RW_DIRECT ((u8)52) /* For SD I/O Card only */ #define SDIO_SDIO_RW_EXTENDED ((u8)53) /* For SD I/O Card only */ /* Following commands are SD Card Specific security commands. SDIO_APP_CMD should be sent before sending these commands. */ #define SDIO_SD_APP_GET_MKB ((u8)43) /* For SD Card only */ #define SDIO_SD_APP_GET_MID ((u8)44) /* For SD Card only */ #define SDIO_SD_APP_SET_CER_RN1 ((u8)45) /* For SD Card only */ #define SDIO_SD_APP_GET_CER_RN2 ((u8)46) /* For SD Card only */ #define SDIO_SD_APP_SET_CER_RES2 ((u8)47) /* For SD Card only */ #define SDIO_SD_APP_GET_CER_RES1 ((u8)48) /* For SD Card only */ #define SDIO_SD_APP_SECURE_READ_MULTIPLE_BLOCK ((u8)18) /* For SD Card only */ #define SDIO_SD_APP_SECURE_WRITE_MULTIPLE_BLOCK ((u8)25) /* For SD Card only */ #define SDIO_SD_APP_SECURE_ERASE ((u8)38) /* For SD Card only */ #define SDIO_SD_APP_CHANGE_SECURE_AREA ((u8)49) /* For SD Card only */ #define SDIO_SD_APP_SECURE_WRITE_MKB ((u8)48) /* For SD Card only */ typedef enum { SD_NO_TRANSFER = 0, SD_TRANSFER_IN_PROGRESS } SDTransferState; typedef struct { u16 TransferredBytes; SD_Error TransferError; u8 padding; } SDLastTransferInfo; typedef struct /* Card Specific Data */ { vu8 CSDStruct; /* CSD structure */ vu8 SysSpecVersion; /* System specification version */ vu8 Reserved1; /* Reserved */ vu8 TAAC; /* Data read access-time 1 */ vu8 NSAC; /* Data read access-time 2 in CLK cycles */ vu8 MaxBusClkFrec; /* Max. bus clock frequency */ vu16 CardComdClasses; /* Card command classes */ vu8 RdBlockLen; /* Max. read data block length */ vu8 PartBlockRead; /* Partial blocks for read allowed */ vu8 WrBlockMisalign; /* Write block misalignment */ vu8 RdBlockMisalign; /* Read block misalignment */ vu8 DSRImpl; /* DSR implemented */ vu8 Reserved2; /* Reserved */ vu16 DeviceSize; /* Device Size */ vu8 MaxRdCurrentVDDMin; /* Max. read current @ VDD min */ vu8 MaxRdCurrentVDDMax; /* Max. read current @ VDD max */ vu8 MaxWrCurrentVDDMin; /* Max. write current @ VDD min */ vu8 MaxWrCurrentVDDMax; /* Max. write current @ VDD max */ vu8 DeviceSizeMul; /* Device size multiplier */ vu8 EraseGrSize; /* Erase group size */ vu8 EraseGrMul; /* Erase group size multiplier */ vu8 WrProtectGrSize; /* Write protect group size */ vu8 WrProtectGrEnable; /* Write protect group enable */ vu8 ManDeflECC; /* Manufacturer default ECC */ vu8 WrSpeedFact; /* Write speed factor */ vu8 MaxWrBlockLen; /* Max. write data block length */ vu8 WriteBlockPaPartial; /* Partial blocks for write allowed */ vu8 Reserved3; /* Reserded */ vu8 ContentProtectAppli; /* Content protection application */ vu8 FileFormatGrouop; /* File format group */ vu8 CopyFlag; /* Copy flag (OTP) */ vu8 PermWrProtect; /* Permanent write protection */ vu8 TempWrProtect; /* Temporary write protection */ vu8 FileFormat; /* File Format */ vu8 ECC; /* ECC code */ vu8 CSD_CRC; /* CSD CRC */ vu8 Reserved4; /* always 1*/ } SD_CSD; typedef struct /*Card Identification Data*/ { vu8 ManufacturerID; /* ManufacturerID */ vu16 OEM_AppliID; /* OEM/Application ID */ vu32 ProdName1; /* Product Name part1 */ vu8 ProdName2; /* Product Name part2*/ vu8 ProdRev; /* Product Revision */ vu32 ProdSN; /* Product Serial Number */ vu8 Reserved1; /* Reserved1 */ vu16 ManufactDate; /* Manufacturing Date */ vu8 CID_CRC; /* CID CRC */ vu8 Reserved2; /* always 1 */ } SD_CID; typedef struct { SD_CSD SD_csd; SD_CID SD_cid; u8 CardType; u16 RCA; } SD_CardInfo; /* Exported constants --------------------------------------------------------*/ #define SD_DMA_MODE ((u32)0x00000000) #define SD_INTERRUPT_MODE ((u32)0x00000001) #define SD_POLLING_MODE ((u32)0x00000002) /* Supported Memory Cards */ #define SDIO_STD_CAPACITY_SD_CARD_V1_1 ((u32)0x0) //SD V1.1版 #define SDIO_STD_CAPACITY_SD_CARD_V2_0 ((u32)0x1) //SD V2.0版 #define SDIO_HIGH_CAPACITY_SD_CARD ((u32)0x2) //大容量SD卡 #define SDIO_MULTIMEDIA_CARD ((u32)0x3) //MMC卡 #define SDIO_SECURE_DIGITAL_IO_CARD ((u32)0x4) //普通SD卡 #define SDIO_HIGH_SPEED_MULTIMEDIA_CARD ((u32)0x5) //高速SD卡 #define SDIO_SECURE_DIGITAL_IO_COMBO_CARD ((u32)0x6) #define SDIO_HIGH_CAPACITY_MMC_CARD ((u32)0x7) //大容量MMC卡 SD_Error SD_Init(void); SD_Error SD_SetIdleSta(void); SD_Error SD_PowerOFF(void); SD_Error SD_PowerON(void); SD_Error SD_InitializeCards(void); SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo); SD_Error SD_EnableWideBusOperation(u32 WideMode); SD_Error SD_SetDeviceMode(u32 Mode); SD_Error SD_SelectDeselect(u32 addr); SD_Error SD_SetBlockSize(u16 BlockSize); SD_Error SD_ReadBlock(u32 addr, u32 *readbuff); SD_Error SD_ReadMultiBlocks(u32 addr, u32 *readbuff, u16 NumberOfBlocks); SD_Error SD_SelectDeselect(u32 addr); SD_Error SD_EnableWideBusMode(u8 EN); //使能4bit DAT线模式,如果失败将保持原来模式 SD_Error SD_WriteBlock(u32 BlockAddr, u32 *BlockBuff); SD_Error SD_WriteMultiBlocks(u32 BlockAddr, u32 *BlockBuff, u32 NumberOfBlocks); #endif