obj_sdmmc_sdcard.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970
  1. #ifdef USE_SDIO_SD
  2. #include "obj_sdmmc_sdcard.h"
  3. #include "string.h"
  4. #include "usart.h"
  5. //////////////////////////////////////////////////////////////////////////////////
  6. //本程序只供学习使用,未经作者许可,不得用于其它任何用途
  7. //ALIENTEK STM32H7开发板
  8. //SDMMC 驱动代码 (仅提供查询模式驱动代码)
  9. //正点原子@ALIENTEK
  10. //技术论坛:www.openedv.com
  11. //创建日期:2018/7/31
  12. //版本:V1.0
  13. //版权所有,盗版必究。
  14. //Copyright(C) 广州市星翼电子科技有限公司 2014-2024
  15. //All rights reserved
  16. //********************************************************************************
  17. //升级说明
  18. //无
  19. //////////////////////////////////////////////////////////////////////////////////
  20. static u8 CardType=STD_CAPACITY_SD_CARD_V1_1; //SD卡类型(默认为1.x卡)
  21. static u32 CSD_Tab[4],CID_Tab[4],RCA=0; //SD卡CSD,CID以及相对地址(RCA)数据
  22. SD_CardInfo SDCardInfo; //SD卡信息
  23. //SD_ReadDisk/SD_WriteDisk函数专用buf,当这两个函数的数据缓存区地址不是4字节对齐的时候,
  24. //需要用到该数组,确保数据缓存区地址是4字节对齐的.
  25. __align(4) u8 SDMMC_DATA_BUFFER[512];
  26. //初始化SD卡
  27. //返回值:错误代码;(0,无错误)
  28. SD_Error SD_Init(void)
  29. {
  30. SD_Error errorstatus=SD_OK;
  31. u8 clkdiv=0;
  32. //SDMMC1 IO口初始化
  33. GPIO_InitTypeDef GPIO_Initure;
  34. __HAL_RCC_SDMMC1_CLK_ENABLE(); //使能SDMMC1时钟
  35. __HAL_RCC_GPIOC_CLK_ENABLE(); //使能GPIOC时钟
  36. __HAL_RCC_GPIOD_CLK_ENABLE(); //使能GPIOD时钟
  37. /*
  38. //PC8,9,10,11,12
  39. GPIO_Initure.Pin=GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
  40. GPIO_Initure.Mode=GPIO_MODE_AF_PP; //推挽复用
  41. GPIO_Initure.Pull=GPIO_NOPULL; //无上下拉
  42. GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //高速
  43. GPIO_Initure.Alternate=GPIO_AF12_SDIO; //复用为SDIO
  44. HAL_GPIO_Init(GPIOC,&GPIO_Initure); //初始化
  45. //PD2
  46. GPIO_Initure.Pin=GPIO_PIN_2;
  47. HAL_GPIO_Init(GPIOD,&GPIO_Initure); //初始化
  48. */
  49. //SDIO_DAT0 PB14
  50. //RMII_TXD1&SDIO_CLK PB13
  51. //SDIO_CMD PB15
  52. //RMII_TXD0&SDIO_CD/DAT3 PB12
  53. GPIO_Initure.Pin=GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
  54. GPIO_Initure.Mode=GPIO_MODE_AF_PP; //推挽复用
  55. GPIO_Initure.Pull=GPIO_NOPULL; //无上下拉
  56. GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //高速
  57. GPIO_Initure.Alternate=GPIO_AF12_SDIO; //复用为SDIO
  58. HAL_GPIO_Init(GPIOC,&GPIO_Initure); //初始化
  59. //SDIO-nCD PD8
  60. GPIO_Initure.Pin=GPIO_PIN_8;
  61. HAL_GPIO_Init(GPIOD,&GPIO_Initure); //初始化
  62. //SDMMC外设寄存器设置为默认值
  63. SDMMC1->POWER=0x00000000;
  64. SDMMC1->CLKCR=0x00000000;
  65. SDMMC1->ARG=0x00000000;
  66. SDMMC1->CMD=0x00000000;
  67. SDMMC1->DTIMER=0x00000000;
  68. SDMMC1->DLEN=0x00000000;
  69. SDMMC1->DCTRL=0x00000000;
  70. SDMMC1->ICR=0X1FE00FFF;
  71. SDMMC1->MASK=0x00000000;
  72. HAL_NVIC_SetPriority(SDMMC1_IRQn,2,0); //配置SDMMC1中断,抢占优先级2,子优先级0
  73. HAL_NVIC_EnableIRQ(SDMMC1_IRQn); //使能SDMMC1中断
  74. errorstatus=SD_PowerON(); //SD卡上电
  75. if(errorstatus==SD_OK)errorstatus=SD_InitializeCards(); //初始化SD卡
  76. if(errorstatus==SD_OK)errorstatus=SD_GetCardInfo(&SDCardInfo); //获取卡信息
  77. if(errorstatus==SD_OK)errorstatus=SD_SelectDeselect((u32)(SDCardInfo.RCA<<16));//选中SD卡
  78. if(errorstatus==SD_OK)errorstatus=SD_EnableWideBusOperation(1); //4位宽度,如果是MMC卡,则不能用4位模式
  79. if((errorstatus==SD_OK)||(MULTIMEDIA_CARD==CardType))
  80. {
  81. if(SDCardInfo.CardType==STD_CAPACITY_SD_CARD_V1_1||SDCardInfo.CardType==STD_CAPACITY_SD_CARD_V2_0)
  82. {
  83. clkdiv=SDMMC_TRANSFER_CLK_DIV+2; //V1.1/V2.0卡,设置最高48/4=12Mhz
  84. }else clkdiv=SDMMC_TRANSFER_CLK_DIV; //SDHC等其他卡,设置最高48/2=24Mhz
  85. SDMMC_Clock_Set(clkdiv); //设置时钟频率,SDMMC时钟计算公式:SDMMC_CK时钟=SDMMCCLK/[clkdiv+2];其中,SDMMCCLK固定为48Mhz
  86. }
  87. return errorstatus;
  88. }
  89. //SDMMC时钟初始化设置
  90. //clkdiv:时钟分频系数
  91. //CK时钟=sdmmc_ker_ck/[2*clkdiv];(sdmmc_ker_ck钟固定为400Mhz)
  92. void SDMMC_Clock_Set(u16 clkdiv)
  93. {
  94. u32 tmpreg=SDMMC1->CLKCR;
  95. tmpreg&=0XFFFFFC00;
  96. tmpreg|=clkdiv;
  97. SDMMC1->CLKCR=tmpreg;
  98. }
  99. //SDMMC发送命令函数
  100. //cmdindex:命令索引,低六位有效
  101. //waitrsp:期待的相应.00/10,无响应;01,短响应;11,长响应
  102. //arg:参数
  103. void SDMMC_Send_Cmd(u8 cmdindex,u8 waitrsp,u32 arg)
  104. {
  105. u32 tmpreg=0;
  106. SDMMC1->ARG=arg;
  107. tmpreg|=cmdindex&0X3F; //设置新的index
  108. tmpreg|=(u32)waitrsp<<8;//设置新的wait rsp
  109. tmpreg|=0<<10; //无等待
  110. tmpreg|=1<<12; //命令通道状态机使能
  111. SDMMC1->CMD=tmpreg;
  112. }
  113. //SDMMC发送数据配置函数
  114. //datatimeout:超时时间设置
  115. //datalen:传输数据长度,低25位有效,必须为块大小的整数倍
  116. //blksize:块大小.实际大小为:2^blksize字节
  117. //dir:数据传输方向:0,控制器到卡;1,卡到控制器;
  118. void SDMMC_Send_Data_Cfg(u32 datatimeout,u32 datalen,u8 blksize,u8 dir)
  119. {
  120. u32 tmpreg;
  121. SDMMC1->DTIMER=datatimeout;
  122. SDMMC1->DLEN=datalen&0X1FFFFFF; //低25位有效
  123. tmpreg=SDMMC1->DCTRL;
  124. tmpreg&=0xFFFFFF00; //清除之前的设置.
  125. tmpreg|=blksize<<4; //设置块大小
  126. tmpreg|=0<<2; //块数据传输
  127. tmpreg|=(dir&0X01)<<1; //方向控制
  128. tmpreg|=1<<0; //数据传输使能,DPSM状态机
  129. SDMMC1->DCTRL=tmpreg;
  130. }
  131. //卡上电
  132. //查询所有SDMMC接口上的卡设备,并查询其电压和配置时钟
  133. //返回值:错误代码;(0,无错误)
  134. SD_Error SD_PowerON(void)
  135. {
  136. u8 i=0;
  137. u32 tempreg=0;
  138. SD_Error errorstatus=SD_OK;
  139. u32 response=0,count=0,validvoltage=0;
  140. u32 SDType=SD_STD_CAPACITY;
  141. //配置CLKCR寄存器
  142. tempreg|=0<<12; //PWRSAV=0,非省电模式
  143. tempreg|=0<<14; //WIDBUS[1:0]=0,1位数据宽度
  144. tempreg|=0<<16; //NEGEDGE=0,SDMMCCK下降沿更改命令和数据
  145. tempreg|=0<<17; //HWFC_EN=0,关闭硬件流控制
  146. SDMMC1->CLKCR=tempreg;
  147. SDMMC_Clock_Set(SDMMC_INIT_CLK_DIV);//设置时钟频率(初始化的时候,不能超过400Khz)
  148. SDMMC1->POWER=0X03; //上电状态,开启卡时钟
  149. for(i=0;i<74;i++)
  150. {
  151. SDMMC_Send_Cmd(SD_CMD_GO_IDLE_STATE,0,0);//发送CMD0进入IDLE STAGE模式命令.
  152. errorstatus=CmdError();
  153. if(errorstatus==SD_OK)break;
  154. }
  155. if(errorstatus)return errorstatus;//返回错误状态
  156. SDMMC_Send_Cmd(SD_SDMMC_SEND_IF_COND,1,SD_CHECK_PATTERN);//发送CMD8,短响应,检查SD卡接口特性.
  157. //arg[11:8]:01,支持电压范围,2.7~3.6V
  158. //arg[7:0]:默认0XAA
  159. //返回响应7
  160. errorstatus=CmdResp7Error(); //等待R7响应
  161. if(errorstatus==SD_OK) //R7响应正常
  162. {
  163. CardType=STD_CAPACITY_SD_CARD_V2_0; //SD 2.0卡
  164. SDType=SD_HIGH_CAPACITY; //高容量卡
  165. }
  166. SDMMC_Send_Cmd(SD_CMD_APP_CMD,1,0); //发送CMD55,短响应
  167. errorstatus=CmdResp1Error(SD_CMD_APP_CMD); //等待R1响应
  168. if(errorstatus==SD_OK)//SD2.0/SD 1.1,否则为MMC卡
  169. {
  170. //SD卡,发送ACMD41 SD_APP_OP_COND,参数为:0x80100000
  171. while((!validvoltage)&&(count<SD_MAX_VOLT_TRIAL))
  172. {
  173. SDMMC_Send_Cmd(SD_CMD_APP_CMD,1,0); //发送CMD55,短响应
  174. errorstatus=CmdResp1Error(SD_CMD_APP_CMD); //等待R1响应
  175. if(errorstatus!=SD_OK)return errorstatus; //响应错误
  176. SDMMC_Send_Cmd(SD_CMD_SD_APP_OP_COND,1,SD_VOLTAGE_WINDOW_SD|SDType);//发送ACMD41,短响应
  177. errorstatus=CmdResp3Error(); //等待R3响应
  178. if(errorstatus!=SD_OK)return errorstatus; //响应错误
  179. response=SDMMC1->RESP1;; //得到响应
  180. validvoltage=(((response>>31)==1)?1:0); //判断SD卡上电是否完成
  181. count++;
  182. }
  183. if(count>=SD_MAX_VOLT_TRIAL)
  184. {
  185. errorstatus=SD_INVALID_VOLTRANGE;
  186. return errorstatus;
  187. }
  188. if(response&=SD_HIGH_CAPACITY)
  189. {
  190. CardType=HIGH_CAPACITY_SD_CARD;
  191. }
  192. }else//MMC卡
  193. {
  194. //MMC卡,发送CMD1 SDMMC_SEND_OP_COND,参数为:0x80FF8000
  195. while((!validvoltage)&&(count<SD_MAX_VOLT_TRIAL))
  196. {
  197. SDMMC_Send_Cmd(SD_CMD_SEND_OP_COND,1,SD_VOLTAGE_WINDOW_MMC);//发送CMD1,短响应
  198. errorstatus=CmdResp3Error(); //等待R3响应
  199. if(errorstatus!=SD_OK)return errorstatus; //响应错误
  200. response=SDMMC1->RESP1;; //得到响应
  201. validvoltage=(((response>>31)==1)?1:0);
  202. count++;
  203. }
  204. if(count>=SD_MAX_VOLT_TRIAL)
  205. {
  206. errorstatus=SD_INVALID_VOLTRANGE;
  207. return errorstatus;
  208. }
  209. CardType=MULTIMEDIA_CARD;
  210. }
  211. return(errorstatus);
  212. }
  213. //SD卡 Power OFF
  214. //返回值:错误代码;(0,无错误)
  215. SD_Error SD_PowerOFF(void)
  216. {
  217. SDMMC1->POWER&=~(3<<0);//SDMMC电源关闭,时钟停止
  218. return SD_OK;
  219. }
  220. //初始化所有的卡,并让卡进入就绪状态
  221. //返回值:错误代码
  222. SD_Error SD_InitializeCards(void)
  223. {
  224. SD_Error errorstatus=SD_OK;
  225. u16 rca = 0x01;
  226. if((SDMMC1->POWER&0X03)==0)return SD_REQUEST_NOT_APPLICABLE;//检查电源状态,确保为上电状态
  227. if(SECURE_DIGITAL_IO_CARD!=CardType) //非SECURE_DIGITAL_IO_CARD
  228. {
  229. SDMMC_Send_Cmd(SD_CMD_ALL_SEND_CID,3,0); //发送CMD2,取得CID,长响应
  230. errorstatus=CmdResp2Error(); //等待R2响应
  231. if(errorstatus!=SD_OK)return errorstatus; //响应错误
  232. CID_Tab[0]=SDMMC1->RESP1;
  233. CID_Tab[1]=SDMMC1->RESP2;
  234. CID_Tab[2]=SDMMC1->RESP3;
  235. CID_Tab[3]=SDMMC1->RESP4;
  236. }
  237. if((STD_CAPACITY_SD_CARD_V1_1==CardType)||(STD_CAPACITY_SD_CARD_V2_0==CardType)||(SECURE_DIGITAL_IO_COMBO_CARD==CardType)||(HIGH_CAPACITY_SD_CARD==CardType))//判断卡类型
  238. {
  239. SDMMC_Send_Cmd(SD_CMD_SET_REL_ADDR,1,0); //发送CMD3,短响应
  240. errorstatus=CmdResp6Error(SD_CMD_SET_REL_ADDR,&rca);//等待R6响应
  241. if(errorstatus!=SD_OK)return errorstatus; //响应错误
  242. }
  243. if (MULTIMEDIA_CARD==CardType)
  244. {
  245. SDMMC_Send_Cmd(SD_CMD_SET_REL_ADDR,1,(u32)(rca<<16));//发送CMD3,短响应
  246. errorstatus=CmdResp2Error(); //等待R2响应
  247. if(errorstatus!=SD_OK)return errorstatus; //响应错误
  248. }
  249. if (SECURE_DIGITAL_IO_CARD!=CardType) //非SECURE_DIGITAL_IO_CARD
  250. {
  251. RCA = rca;
  252. SDMMC_Send_Cmd(SD_CMD_SEND_CSD,3,(u32)(rca<<16));//发送CMD9+卡RCA,取得CSD,长响应
  253. errorstatus=CmdResp2Error(); //等待R2响应
  254. if(errorstatus!=SD_OK)return errorstatus; //响应错误
  255. CSD_Tab[0]=SDMMC1->RESP1;
  256. CSD_Tab[1]=SDMMC1->RESP2;
  257. CSD_Tab[2]=SDMMC1->RESP3;
  258. CSD_Tab[3]=SDMMC1->RESP4;
  259. }
  260. return SD_OK;//卡初始化成功
  261. }
  262. //得到卡信息
  263. //cardinfo:卡信息存储区
  264. //返回值:错误状态
  265. SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo)
  266. {
  267. SD_Error errorstatus=SD_OK;
  268. u8 tmp=0;
  269. cardinfo->CardType=(u8)CardType; //卡类型
  270. cardinfo->RCA=(u16)RCA; //卡RCA值
  271. tmp=(u8)((CSD_Tab[0]&0xFF000000)>>24);
  272. cardinfo->SD_csd.CSDStruct=(tmp&0xC0)>>6; //CSD结构
  273. cardinfo->SD_csd.SysSpecVersion=(tmp&0x3C)>>2; //2.0协议还没定义这部分(为保留),应该是后续协议定义的
  274. cardinfo->SD_csd.Reserved1=tmp&0x03; //2个保留位
  275. tmp=(u8)((CSD_Tab[0]&0x00FF0000)>>16); //第1个字节
  276. cardinfo->SD_csd.TAAC=tmp; //数据读时间1
  277. tmp=(u8)((CSD_Tab[0]&0x0000FF00)>>8); //第2个字节
  278. cardinfo->SD_csd.NSAC=tmp; //数据读时间2
  279. tmp=(u8)(CSD_Tab[0]&0x000000FF); //第3个字节
  280. cardinfo->SD_csd.MaxBusClkFrec=tmp; //传输速度
  281. tmp=(u8)((CSD_Tab[1]&0xFF000000)>>24); //第4个字节
  282. cardinfo->SD_csd.CardComdClasses=tmp<<4; //卡指令类高四位
  283. tmp=(u8)((CSD_Tab[1]&0x00FF0000)>>16); //第5个字节
  284. cardinfo->SD_csd.CardComdClasses|=(tmp&0xF0)>>4;//卡指令类低四位
  285. cardinfo->SD_csd.RdBlockLen=tmp&0x0F; //最大读取数据长度
  286. tmp=(u8)((CSD_Tab[1]&0x0000FF00)>>8); //第6个字节
  287. cardinfo->SD_csd.PartBlockRead=(tmp&0x80)>>7; //允许分块读
  288. cardinfo->SD_csd.WrBlockMisalign=(tmp&0x40)>>6; //写块错位
  289. cardinfo->SD_csd.RdBlockMisalign=(tmp&0x20)>>5; //读块错位
  290. cardinfo->SD_csd.DSRImpl=(tmp&0x10)>>4;
  291. cardinfo->SD_csd.Reserved2=0; //保留
  292. if((CardType==STD_CAPACITY_SD_CARD_V1_1)||(CardType==STD_CAPACITY_SD_CARD_V2_0)||(MULTIMEDIA_CARD==CardType))//标准1.1/2.0卡/MMC卡
  293. {
  294. cardinfo->SD_csd.DeviceSize=(tmp&0x03)<<10; //C_SIZE(12位)
  295. tmp=(u8)(CSD_Tab[1]&0x000000FF); //第7个字节
  296. cardinfo->SD_csd.DeviceSize|=(tmp)<<2;
  297. tmp=(u8)((CSD_Tab[2]&0xFF000000)>>24); //第8个字节
  298. cardinfo->SD_csd.DeviceSize|=(tmp&0xC0)>>6;
  299. cardinfo->SD_csd.MaxRdCurrentVDDMin=(tmp&0x38)>>3;
  300. cardinfo->SD_csd.MaxRdCurrentVDDMax=(tmp&0x07);
  301. tmp=(u8)((CSD_Tab[2]&0x00FF0000)>>16); //第9个字节
  302. cardinfo->SD_csd.MaxWrCurrentVDDMin=(tmp&0xE0)>>5;
  303. cardinfo->SD_csd.MaxWrCurrentVDDMax=(tmp&0x1C)>>2;
  304. cardinfo->SD_csd.DeviceSizeMul=(tmp&0x03)<<1;//C_SIZE_MULT
  305. tmp=(u8)((CSD_Tab[2]&0x0000FF00)>>8); //第10个字节
  306. cardinfo->SD_csd.DeviceSizeMul|=(tmp&0x80)>>7;
  307. cardinfo->CardCapacity=(cardinfo->SD_csd.DeviceSize+1);//计算卡容量
  308. cardinfo->CardCapacity*=(1<<(cardinfo->SD_csd.DeviceSizeMul+2));
  309. cardinfo->CardBlockSize=1<<(cardinfo->SD_csd.RdBlockLen);//块大小
  310. cardinfo->CardCapacity*=cardinfo->CardBlockSize;
  311. }else if(CardType==HIGH_CAPACITY_SD_CARD) //高容量卡
  312. {
  313. tmp=(u8)(CSD_Tab[1]&0x000000FF); //第7个字节
  314. cardinfo->SD_csd.DeviceSize=(tmp&0x3F)<<16;//C_SIZE
  315. tmp=(u8)((CSD_Tab[2]&0xFF000000)>>24); //第8个字节
  316. cardinfo->SD_csd.DeviceSize|=(tmp<<8);
  317. tmp=(u8)((CSD_Tab[2]&0x00FF0000)>>16); //第9个字节
  318. cardinfo->SD_csd.DeviceSize|=(tmp);
  319. tmp=(u8)((CSD_Tab[2]&0x0000FF00)>>8); //第10个字节
  320. cardinfo->CardCapacity=(long long)(cardinfo->SD_csd.DeviceSize+1)*512*1024;//计算卡容量
  321. cardinfo->CardBlockSize=512; //块大小固定为512字节
  322. }
  323. cardinfo->SD_csd.EraseGrSize=(tmp&0x40)>>6;
  324. cardinfo->SD_csd.EraseGrMul=(tmp&0x3F)<<1;
  325. tmp=(u8)(CSD_Tab[2]&0x000000FF); //第11个字节
  326. cardinfo->SD_csd.EraseGrMul|=(tmp&0x80)>>7;
  327. cardinfo->SD_csd.WrProtectGrSize=(tmp&0x7F);
  328. tmp=(u8)((CSD_Tab[3]&0xFF000000)>>24); //第12个字节
  329. cardinfo->SD_csd.WrProtectGrEnable=(tmp&0x80)>>7;
  330. cardinfo->SD_csd.ManDeflECC=(tmp&0x60)>>5;
  331. cardinfo->SD_csd.WrSpeedFact=(tmp&0x1C)>>2;
  332. cardinfo->SD_csd.MaxWrBlockLen=(tmp&0x03)<<2;
  333. tmp=(u8)((CSD_Tab[3]&0x00FF0000)>>16); //第13个字节
  334. cardinfo->SD_csd.MaxWrBlockLen|=(tmp&0xC0)>>6;
  335. cardinfo->SD_csd.WriteBlockPaPartial=(tmp&0x20)>>5;
  336. cardinfo->SD_csd.Reserved3=0;
  337. cardinfo->SD_csd.ContentProtectAppli=(tmp&0x01);
  338. tmp=(u8)((CSD_Tab[3]&0x0000FF00)>>8); //第14个字节
  339. cardinfo->SD_csd.FileFormatGrouop=(tmp&0x80)>>7;
  340. cardinfo->SD_csd.CopyFlag=(tmp&0x40)>>6;
  341. cardinfo->SD_csd.PermWrProtect=(tmp&0x20)>>5;
  342. cardinfo->SD_csd.TempWrProtect=(tmp&0x10)>>4;
  343. cardinfo->SD_csd.FileFormat=(tmp&0x0C)>>2;
  344. cardinfo->SD_csd.ECC=(tmp&0x03);
  345. tmp=(u8)(CSD_Tab[3]&0x000000FF); //第15个字节
  346. cardinfo->SD_csd.CSD_CRC=(tmp&0xFE)>>1;
  347. cardinfo->SD_csd.Reserved4=1;
  348. tmp=(u8)((CID_Tab[0]&0xFF000000)>>24); //第0个字节
  349. cardinfo->SD_cid.ManufacturerID=tmp;
  350. tmp=(u8)((CID_Tab[0]&0x00FF0000)>>16); //第1个字节
  351. cardinfo->SD_cid.OEM_AppliID=tmp<<8;
  352. tmp=(u8)((CID_Tab[0]&0x000000FF00)>>8); //第2个字节
  353. cardinfo->SD_cid.OEM_AppliID|=tmp;
  354. tmp=(u8)(CID_Tab[0]&0x000000FF); //第3个字节
  355. cardinfo->SD_cid.ProdName1=tmp<<24;
  356. tmp=(u8)((CID_Tab[1]&0xFF000000)>>24); //第4个字节
  357. cardinfo->SD_cid.ProdName1|=tmp<<16;
  358. tmp=(u8)((CID_Tab[1]&0x00FF0000)>>16); //第5个字节
  359. cardinfo->SD_cid.ProdName1|=tmp<<8;
  360. tmp=(u8)((CID_Tab[1]&0x0000FF00)>>8); //第6个字节
  361. cardinfo->SD_cid.ProdName1|=tmp;
  362. tmp=(u8)(CID_Tab[1]&0x000000FF); //第7个字节
  363. cardinfo->SD_cid.ProdName2=tmp;
  364. tmp=(u8)((CID_Tab[2]&0xFF000000)>>24); //第8个字节
  365. cardinfo->SD_cid.ProdRev=tmp;
  366. tmp=(u8)((CID_Tab[2]&0x00FF0000)>>16); //第9个字节
  367. cardinfo->SD_cid.ProdSN=tmp<<24;
  368. tmp=(u8)((CID_Tab[2]&0x0000FF00)>>8); //第10个字节
  369. cardinfo->SD_cid.ProdSN|=tmp<<16;
  370. tmp=(u8)(CID_Tab[2]&0x000000FF); //第11个字节
  371. cardinfo->SD_cid.ProdSN|=tmp<<8;
  372. tmp=(u8)((CID_Tab[3]&0xFF000000)>>24); //第12个字节
  373. cardinfo->SD_cid.ProdSN|=tmp;
  374. tmp=(u8)((CID_Tab[3]&0x00FF0000)>>16); //第13个字节
  375. cardinfo->SD_cid.Reserved1|=(tmp&0xF0)>>4;
  376. cardinfo->SD_cid.ManufactDate=(tmp&0x0F)<<8;
  377. tmp=(u8)((CID_Tab[3]&0x0000FF00)>>8); //第14个字节
  378. cardinfo->SD_cid.ManufactDate|=tmp;
  379. tmp=(u8)(CID_Tab[3]&0x000000FF); //第15个字节
  380. cardinfo->SD_cid.CID_CRC=(tmp&0xFE)>>1;
  381. cardinfo->SD_cid.Reserved2=1;
  382. return errorstatus;
  383. }
  384. //设置SDMMC总线宽度(MMC卡不支持4bit模式)
  385. //wmode:位宽模式.0,1位数据宽度;1,4位数据宽度;2,8位数据宽度
  386. //返回值:SD卡错误状态
  387. SD_Error SD_EnableWideBusOperation(u32 wmode)
  388. {
  389. SD_Error errorstatus=SD_OK;
  390. u16 clkcr=0;
  391. if(MULTIMEDIA_CARD==CardType)return SD_UNSUPPORTED_FEATURE;//MMC卡不支持
  392. else if((STD_CAPACITY_SD_CARD_V1_1==CardType)||(STD_CAPACITY_SD_CARD_V2_0==CardType)||(HIGH_CAPACITY_SD_CARD==CardType))
  393. {
  394. if(wmode>=2)return SD_UNSUPPORTED_FEATURE;//不支持8位模式
  395. else
  396. {
  397. errorstatus=SDEnWideBus(wmode);
  398. if(SD_OK==errorstatus)
  399. {
  400. clkcr=SDMMC1->CLKCR; //读取CLKCR的值
  401. clkcr&=~(3<<14); //清除之前的位宽设置
  402. clkcr|=(u32)wmode<<14; //1位/4位总线宽度
  403. clkcr|=0<<17; //不开启硬件流控制
  404. SDMMC1->CLKCR=clkcr; //重新设置CLKCR值
  405. }
  406. }
  407. }
  408. return errorstatus;
  409. }
  410. //选卡
  411. //发送CMD7,选择相对地址(rca)为addr的卡,取消其他卡.如果为0,则都不选择.
  412. //addr:卡的RCA地址
  413. SD_Error SD_SelectDeselect(u32 addr)
  414. {
  415. SDMMC_Send_Cmd(SD_CMD_SEL_DESEL_CARD,1,addr); //发送CMD7,选择卡,短响应
  416. return CmdResp1Error(SD_CMD_SEL_DESEL_CARD);
  417. }
  418. //SD卡读取单个/多个块
  419. //buf:读数据缓存区
  420. //addr:读取地址
  421. //blksize:块大小
  422. //nblks:要读取的块数,1,表示读取单个块
  423. //返回值:错误状态
  424. SD_Error SD_ReadBlocks(u8 *buf,long long addr,u16 blksize,u32 nblks)
  425. {
  426. SD_Error errorstatus=SD_OK;
  427. u32 count=0;
  428. u32 timeout=SDMMC_DATATIMEOUT;
  429. u32 *tempbuff=(u32*)buf; //转换为u32指针
  430. SDMMC1->DCTRL=0x0; //数据控制寄存器清零(关DMA)
  431. if(CardType==HIGH_CAPACITY_SD_CARD)//大容量卡
  432. {
  433. blksize=512;
  434. addr>>=9;
  435. }
  436. SDMMC_Send_Cmd(SD_CMD_SET_BLOCKLEN,1,blksize); //发送CMD16+设置数据长度为blksize,短响应
  437. errorstatus=CmdResp1Error(SD_CMD_SET_BLOCKLEN); //等待R1响应
  438. if(errorstatus!=SD_OK)
  439. {
  440. printf("SDMMC_Send_Cmd=%d\r\n",errorstatus);
  441. return errorstatus; //响应错误
  442. }
  443. SDMMC_Send_Data_Cfg(SD_DATATIMEOUT,nblks*blksize,9,1); //nblks*blksize,块大小恒为512,卡到控制器
  444. SDMMC1->CMD|=1<<6; //CMDTRANS=1,产生一个数据传输命令
  445. if(nblks>1) //多块读
  446. {
  447. SDMMC_Send_Cmd(SD_CMD_READ_MULT_BLOCK,1,addr); //发送CMD18+从addr地址出读取数据,短响应
  448. errorstatus=CmdResp1Error(SD_CMD_READ_MULT_BLOCK); //等待R1响应
  449. if(errorstatus!=SD_OK)
  450. {
  451. printf("SD_CMD_READ_MULT_BLOCK Error\r\n");
  452. return errorstatus; //响应错误
  453. }
  454. }else //单块读
  455. {
  456. SDMMC_Send_Cmd(SD_CMD_READ_SINGLE_BLOCK,1,addr); //发送CMD17+从addr地址出读取数据,短响应
  457. errorstatus=CmdResp1Error(SD_CMD_READ_SINGLE_BLOCK);//等待R1响应
  458. if(errorstatus!=SD_OK)return errorstatus; //响应错误
  459. }
  460. INTX_DISABLE();//关闭总中断(POLLING模式,严禁中断打断SDMMC读写操作!!!)
  461. while(!(SDMMC1->STA&((1<<5)|(1<<1)|(1<<3)|(1<<8))))//无上溢/CRC/超时/完成(标志)
  462. {
  463. if(SDMMC1->STA&(1<<15)) //接收区半满,表示至少存了8个字
  464. {
  465. for(count=0;count<8;count++) //循环读取数据
  466. {
  467. *(tempbuff+count)=SDMMC1->FIFO;
  468. }
  469. tempbuff+=8;
  470. timeout=0X7FFFFF; //读数据溢出时间
  471. }else //处理超时
  472. {
  473. if(timeout==0)return SD_DATA_TIMEOUT;
  474. timeout--;
  475. }
  476. }
  477. SDMMC1->CMD&=~(1<<6); //CMDTRANS=0,结束数据传输
  478. INTX_ENABLE(); //开启总中断
  479. if(SDMMC1->STA&(1<<3)) //数据超时错误
  480. {
  481. SDMMC1->ICR|=1<<3; //清错误标志
  482. return SD_DATA_TIMEOUT;
  483. }else if(SDMMC1->STA&(1<<1))//数据块CRC错误
  484. {
  485. SDMMC1->ICR|=1<<1; //清错误标志
  486. if(nblks>1) //针对可能出现的CRC错误,如果是多块读取,必须发送结束传输命令!
  487. {
  488. SDMMC_Send_Cmd(SD_CMD_STOP_TRANSMISSION,1,0); //发送CMD12+结束传输
  489. errorstatus=CmdResp1Error(SD_CMD_STOP_TRANSMISSION);//等待R1响应
  490. }
  491. return SD_DATA_CRC_FAIL;
  492. }else if(SDMMC1->STA&(1<<5))//接收fifo上溢错误
  493. {
  494. SDMMC1->ICR|=1<<5; //清错误标志
  495. return SD_RX_OVERRUN;
  496. }
  497. if((SDMMC1->STA&(1<<8))&&(nblks>1))//多块接收结束,发送结束指令
  498. {
  499. if((STD_CAPACITY_SD_CARD_V1_1==CardType)||(STD_CAPACITY_SD_CARD_V2_0==CardType)||(HIGH_CAPACITY_SD_CARD==CardType))
  500. {
  501. SDMMC_Send_Cmd(SD_CMD_STOP_TRANSMISSION,1,0); //发送CMD12+结束传输
  502. errorstatus=CmdResp1Error(SD_CMD_STOP_TRANSMISSION);//等待R1响应
  503. if(errorstatus!=SD_OK)return errorstatus;
  504. }
  505. }
  506. SDMMC1->ICR=0X1FE00FFF; //清除所有标记
  507. return errorstatus;
  508. }
  509. //SD卡写单个/多个块
  510. //buf:数据缓存区
  511. //addr:写地址
  512. //blksize:块大小
  513. //nblks:要读取的块数,1,表示读取单个块
  514. //返回值:错误状态
  515. SD_Error SD_WriteBlocks(u8 *buf,long long addr,u16 blksize,u32 nblks)
  516. {
  517. SD_Error errorstatus = SD_OK;
  518. u8 cardstate=0;
  519. u32 timeout=0,bytestransferred=0;
  520. u32 cardstatus=0,count=0,restwords=0;
  521. u32 tlen=nblks*blksize; //总长度(字节)
  522. u32*tempbuff=(u32*)buf;
  523. if(buf==NULL)return SD_INVALID_PARAMETER; //参数错误
  524. SDMMC1->DCTRL=0x0; //数据控制寄存器清零(关DMA)
  525. if(CardType==HIGH_CAPACITY_SD_CARD) //大容量卡
  526. {
  527. blksize=512;
  528. addr>>=9;
  529. }
  530. SDMMC_Send_Cmd(SD_CMD_SET_BLOCKLEN,1,blksize); //发送CMD16+设置数据长度为blksize,短响应
  531. errorstatus=CmdResp1Error(SD_CMD_SET_BLOCKLEN); //等待R1响应
  532. if(errorstatus!=SD_OK)return errorstatus; //响应错误
  533. if(nblks>1) //多块写
  534. {
  535. if(nblks*blksize>SD_MAX_DATA_LENGTH)return SD_INVALID_PARAMETER;
  536. if((STD_CAPACITY_SD_CARD_V1_1==CardType)||(STD_CAPACITY_SD_CARD_V2_0==CardType)||(HIGH_CAPACITY_SD_CARD==CardType))
  537. {
  538. //提高性能
  539. SDMMC_Send_Cmd(SD_CMD_APP_CMD,1,(u32)RCA<<16); //发送ACMD55,短响应
  540. errorstatus=CmdResp1Error(SD_CMD_APP_CMD); //等待R1响应
  541. if(errorstatus!=SD_OK)return errorstatus;
  542. SDMMC_Send_Cmd(SD_CMD_SET_BLOCK_COUNT,1,nblks); //发送CMD23,设置块数量,短响应
  543. errorstatus=CmdResp1Error(SD_CMD_SET_BLOCK_COUNT);//等待R1响应
  544. if(errorstatus!=SD_OK)return errorstatus;
  545. }
  546. SDMMC_Send_Cmd(SD_CMD_WRITE_MULT_BLOCK,1,addr); //发送CMD25,多块写指令,短响应
  547. errorstatus=CmdResp1Error(SD_CMD_WRITE_MULT_BLOCK); //等待R1响应
  548. }else //单块写
  549. {
  550. SDMMC_Send_Cmd(SD_CMD_SEND_STATUS,1,(u32)RCA<<16); //发送CMD13,查询卡的状态,短响应
  551. errorstatus=CmdResp1Error(SD_CMD_SEND_STATUS); //等待R1响应
  552. if(errorstatus!=SD_OK)return errorstatus;
  553. cardstatus=SDMMC1->RESP1;
  554. timeout=SD_DATATIMEOUT;
  555. while(((cardstatus&0x00000100)==0)&&(timeout>0)) //检查READY_FOR_DATA位是否置位
  556. {
  557. timeout--;
  558. SDMMC_Send_Cmd(SD_CMD_SEND_STATUS,1,(u32)RCA<<16);//发送CMD13,查询卡的状态,短响应
  559. errorstatus=CmdResp1Error(SD_CMD_SEND_STATUS); //等待R1响应
  560. if(errorstatus!=SD_OK)return errorstatus;
  561. cardstatus=SDMMC1->RESP1;
  562. }
  563. if(timeout==0)return SD_ERROR;
  564. SDMMC_Send_Cmd(SD_CMD_WRITE_SINGLE_BLOCK,1,addr); //发送CMD24,写单块指令,短响应
  565. errorstatus=CmdResp1Error(SD_CMD_WRITE_SINGLE_BLOCK);//等待R1响应
  566. }
  567. if(errorstatus!=SD_OK)return errorstatus;
  568. SDMMC_Send_Data_Cfg(SD_DATATIMEOUT,nblks*blksize,9,0); //blksize,块大小恒为512字节,控制器到卡
  569. SDMMC1->CMD|=1<<6; //CMDTRANS=1,产生一个数据传输命令
  570. timeout=SDMMC_DATATIMEOUT;
  571. INTX_DISABLE();//关闭总中断(POLLING模式,严禁中断打断SDMMC读写操作!!!)
  572. while(!(SDMMC1->STA&((1<<4)|(1<<1)|(1<<8)|(1<<3))))//下溢/CRC/数据结束/超时
  573. {
  574. if(SDMMC1->STA&(1<<14)) //发送区半空,表示至少存了8字(32字节)
  575. {
  576. if((tlen-bytestransferred)<SD_HALFFIFOBYTES)//不够32字节了
  577. {
  578. restwords=((tlen-bytestransferred)%4==0)?((tlen-bytestransferred)/4):((tlen-bytestransferred)/4+1);
  579. for(count=0;count<restwords;count++,tempbuff++,bytestransferred+=4)
  580. {
  581. SDMMC1->FIFO=*tempbuff;
  582. }
  583. }else //发送区半空,可以发送至少8字(32字节)数据
  584. {
  585. for(count=0;count<SD_HALFFIFO;count++)
  586. {
  587. SDMMC1->FIFO=*(tempbuff+count);
  588. }
  589. tempbuff+=SD_HALFFIFO;
  590. bytestransferred+=SD_HALFFIFOBYTES;
  591. }
  592. timeout=0X3FFFFFFF; //写数据溢出时间
  593. }else
  594. {
  595. if(timeout==0)return SD_DATA_TIMEOUT;
  596. timeout--;
  597. }
  598. }
  599. SDMMC1->CMD&=~(1<<6); //CMDTRANS=0,结束数据传输
  600. INTX_ENABLE(); //开启总中断
  601. if(SDMMC1->STA&(1<<3)) //数据超时错误
  602. {
  603. SDMMC1->ICR|=1<<3; //清错误标志
  604. return SD_DATA_TIMEOUT;
  605. }else if(SDMMC1->STA&(1<<1)) //数据块CRC错误
  606. {
  607. SDMMC1->ICR|=1<<1; //清错误标志
  608. if(nblks>1) //针对可能出现的CRC错误,如果是多块读取,必须发送结束传输命令!
  609. {
  610. SDMMC_Send_Cmd(SD_CMD_STOP_TRANSMISSION,1,0); //发送CMD12+结束传输
  611. errorstatus=CmdResp1Error(SD_CMD_STOP_TRANSMISSION);//等待R1响应
  612. }
  613. return SD_DATA_CRC_FAIL;
  614. }else if(SDMMC1->STA&(1<<4)) //接收fifo下溢错误
  615. {
  616. SDMMC1->ICR|=1<<4; //清错误标志
  617. return SD_TX_UNDERRUN;
  618. }
  619. if((SDMMC1->STA&(1<<8))&&(nblks>1))//多块发送结束,发送结束指令
  620. {
  621. if((STD_CAPACITY_SD_CARD_V1_1==CardType)||(STD_CAPACITY_SD_CARD_V2_0==CardType)||(HIGH_CAPACITY_SD_CARD==CardType))
  622. {
  623. SDMMC_Send_Cmd(SD_CMD_STOP_TRANSMISSION,1,0); //发送CMD12+结束传输
  624. errorstatus=CmdResp1Error(SD_CMD_STOP_TRANSMISSION);//等待R1响应
  625. if(errorstatus!=SD_OK)return errorstatus;
  626. }
  627. }
  628. SDMMC1->ICR=0X1FE00FFF; //清除所有标记
  629. errorstatus=IsCardProgramming(&cardstate);
  630. while((errorstatus==SD_OK)&&((cardstate==SD_CARD_PROGRAMMING)||(cardstate==SD_CARD_RECEIVING)))
  631. {
  632. errorstatus=IsCardProgramming(&cardstate);
  633. }
  634. return errorstatus;
  635. }
  636. //检查CMD0的执行状态
  637. //返回值:sd卡错误码
  638. SD_Error CmdError(void)
  639. {
  640. SD_Error errorstatus = SD_OK;
  641. u32 timeout=SDMMC_CMD0TIMEOUT;
  642. while(timeout--)
  643. {
  644. if(SDMMC1->STA&(1<<7))break;//命令已发送(无需响应)
  645. }
  646. if(timeout==0)return SD_CMD_RSP_TIMEOUT;
  647. SDMMC1->ICR=0X1FE00FFF; //清除标记
  648. return errorstatus;
  649. }
  650. //检查R7响应的错误状态
  651. //返回值:sd卡错误码
  652. SD_Error CmdResp7Error(void)
  653. {
  654. SD_Error errorstatus=SD_OK;
  655. u32 status;
  656. u32 timeout=SDMMC_CMD0TIMEOUT;
  657. while(timeout--)
  658. {
  659. status=SDMMC1->STA;
  660. if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)
  661. }
  662. if((timeout==0)||(status&(1<<2))) //响应超时
  663. {
  664. errorstatus=SD_CMD_RSP_TIMEOUT; //当前卡不是2.0兼容卡,或者不支持设定的电压范围
  665. SDMMC1->ICR|=1<<2; //清除命令响应超时标志
  666. return errorstatus;
  667. }
  668. if(status&1<<6) //成功接收到响应
  669. {
  670. errorstatus=SD_OK;
  671. SDMMC1->ICR|=1<<6; //清除响应标志
  672. }
  673. return errorstatus;
  674. }
  675. //检查R1响应的错误状态
  676. //cmd:当前命令
  677. //返回值:sd卡错误码
  678. SD_Error CmdResp1Error(u8 cmd)
  679. {
  680. u32 status;
  681. while(1)
  682. {
  683. status=SDMMC1->STA;
  684. if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)
  685. }
  686. if(status&(1<<2)) //响应超时
  687. {
  688. SDMMC1->ICR=1<<2; //清除命令响应超时标志
  689. SDMMC1->ICR=0X1FE00FFF; //清除标记
  690. return SD_CMD_RSP_TIMEOUT;
  691. }
  692. if(status&(1<<0)) //CRC错误
  693. {
  694. SDMMC1->ICR=1<<0; //清除标志
  695. return SD_CMD_CRC_FAIL;
  696. }
  697. if(SDMMC1->RESPCMD!=cmd)return SD_ILLEGAL_CMD;//命令不匹配
  698. SDMMC1->ICR=0X1FE00FFF; //清除标记
  699. return (SD_Error)(SDMMC1->RESP1&SD_OCR_ERRORBITS);//返回卡响应
  700. }
  701. //检查R3响应的错误状态
  702. //返回值:错误状态
  703. SD_Error CmdResp3Error(void)
  704. {
  705. u32 status;
  706. while(1)
  707. {
  708. status=SDMMC1->STA;
  709. if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)
  710. }
  711. if(status&(1<<2)) //响应超时
  712. {
  713. SDMMC1->ICR|=1<<2; //清除命令响应超时标志
  714. return SD_CMD_RSP_TIMEOUT;
  715. }
  716. SDMMC1->ICR=0X1FE00FFF; //清除标记
  717. return SD_OK;
  718. }
  719. //检查R2响应的错误状态
  720. //返回值:错误状态
  721. SD_Error CmdResp2Error(void)
  722. {
  723. SD_Error errorstatus=SD_OK;
  724. u32 status;
  725. u32 timeout=SDMMC_CMD0TIMEOUT;
  726. while(timeout--)
  727. {
  728. status=SDMMC1->STA;
  729. if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)
  730. }
  731. if((timeout==0)||(status&(1<<2))) //响应超时
  732. {
  733. errorstatus=SD_CMD_RSP_TIMEOUT;
  734. SDMMC1->ICR|=1<<2; //清除命令响应超时标志
  735. return errorstatus;
  736. }
  737. if(status&1<<0) //CRC错误
  738. {
  739. errorstatus=SD_CMD_CRC_FAIL;
  740. SDMMC1->ICR|=1<<0; //清除响应标志
  741. }
  742. SDMMC1->ICR=0X1FE00FFF; //清除标记
  743. return errorstatus;
  744. }
  745. //检查R6响应的错误状态
  746. //cmd:之前发送的命令
  747. //prca:卡返回的RCA地址
  748. //返回值:错误状态
  749. SD_Error CmdResp6Error(u8 cmd,u16*prca)
  750. {
  751. SD_Error errorstatus=SD_OK;
  752. u32 status;
  753. u32 rspr1;
  754. while(1)
  755. {
  756. status=SDMMC1->STA;
  757. if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)
  758. }
  759. if(status&(1<<2)) //响应超时
  760. {
  761. SDMMC1->ICR|=1<<2; //清除命令响应超时标志
  762. return SD_CMD_RSP_TIMEOUT;
  763. }
  764. if(status&1<<0) //CRC错误
  765. {
  766. SDMMC1->ICR|=1<<0; //清除响应标志
  767. return SD_CMD_CRC_FAIL;
  768. }
  769. if(SDMMC1->RESPCMD!=cmd) //判断是否响应cmd命令
  770. {
  771. return SD_ILLEGAL_CMD;
  772. }
  773. SDMMC1->ICR=0X1FE00FFF; //清除所有标记
  774. rspr1=SDMMC1->RESP1; //得到响应
  775. if(SD_ALLZERO==(rspr1&(SD_R6_GENERAL_UNKNOWN_ERROR|SD_R6_ILLEGAL_CMD|SD_R6_COM_CRC_FAILED)))
  776. {
  777. *prca=(u16)(rspr1>>16); //右移16位得到,rca
  778. return errorstatus;
  779. }
  780. if(rspr1&SD_R6_GENERAL_UNKNOWN_ERROR)return SD_GENERAL_UNKNOWN_ERROR;
  781. if(rspr1&SD_R6_ILLEGAL_CMD)return SD_ILLEGAL_CMD;
  782. if(rspr1&SD_R6_COM_CRC_FAILED)return SD_COM_CRC_FAILED;
  783. return errorstatus;
  784. }
  785. //SDMMC使能宽总线模式
  786. //enx:0,不使能;1,使能;
  787. //返回值:错误状态
  788. SD_Error SDEnWideBus(u8 enx)
  789. {
  790. SD_Error errorstatus = SD_OK;
  791. u32 scr[2]={0,0};
  792. u8 arg=0X00;
  793. if(enx)arg=0X02;
  794. else arg=0X00;
  795. if(SDMMC1->RESP1&SD_CARD_LOCKED)return SD_LOCK_UNLOCK_FAILED;//SD卡处于LOCKED状态
  796. errorstatus=FindSCR(RCA,scr); //得到SCR寄存器数据
  797. if(errorstatus!=SD_OK)return errorstatus;
  798. if((scr[1]&SD_WIDE_BUS_SUPPORT)!=SD_ALLZERO) //支持宽总线
  799. {
  800. SDMMC_Send_Cmd(SD_CMD_APP_CMD,1,(u32)RCA<<16); //发送CMD55+RCA,短响应
  801. errorstatus=CmdResp1Error(SD_CMD_APP_CMD);
  802. if(errorstatus!=SD_OK)return errorstatus;
  803. SDMMC_Send_Cmd(SD_CMD_APP_SD_SET_BUSWIDTH,1,arg);//发送ACMD6,短响应,参数:10,4位;00,1位.
  804. errorstatus=CmdResp1Error(SD_CMD_APP_SD_SET_BUSWIDTH);
  805. return errorstatus;
  806. }else return SD_REQUEST_NOT_APPLICABLE; //不支持宽总线设置
  807. }
  808. //检查卡是否正在执行写操作
  809. //pstatus:当前状态.
  810. //返回值:错误代码
  811. SD_Error IsCardProgramming(u8 *pstatus)
  812. {
  813. vu32 respR1 = 0, status = 0;
  814. SDMMC_Send_Cmd(SD_CMD_SEND_STATUS,1,(u32)RCA<<16); //发送CMD13
  815. status=SDMMC1->STA;
  816. while(!(status&((1<<0)|(1<<6)|(1<<2))))status=SDMMC1->STA;//等待操作完成
  817. if(status&(1<<0)) //CRC检测失败
  818. {
  819. SDMMC1->ICR|=1<<0; //清除错误标记
  820. return SD_CMD_CRC_FAIL;
  821. }
  822. if(status&(1<<2)) //命令超时
  823. {
  824. SDMMC1->ICR|=1<<2; //清除错误标记
  825. return SD_CMD_RSP_TIMEOUT;
  826. }
  827. if(SDMMC1->RESPCMD!=SD_CMD_SEND_STATUS)return SD_ILLEGAL_CMD;
  828. SDMMC1->ICR=0X1FE00FFF; //清除所有标记
  829. respR1=SDMMC1->RESP1;
  830. *pstatus=(u8)((respR1>>9)&0x0000000F);
  831. return SD_OK;
  832. }
  833. //读取当前卡状态
  834. //pcardstatus:卡状态
  835. //返回值:错误代码
  836. SD_Error SD_SendStatus(uint32_t *pcardstatus)
  837. {
  838. SD_Error errorstatus = SD_OK;
  839. if(pcardstatus==NULL)
  840. {
  841. errorstatus=SD_INVALID_PARAMETER;
  842. return errorstatus;
  843. }
  844. SDMMC_Send_Cmd(SD_CMD_SEND_STATUS,1,RCA<<16); //发送CMD13,短响应
  845. errorstatus=CmdResp1Error(SD_CMD_SEND_STATUS); //查询响应状态
  846. if(errorstatus!=SD_OK)return errorstatus;
  847. *pcardstatus=SDMMC1->RESP1;//读取响应值
  848. return errorstatus;
  849. }
  850. //返回SD卡的状态
  851. //返回值:SD卡状态
  852. SDCardState SD_GetState(void)
  853. {
  854. u32 resp1=0;
  855. if(SD_SendStatus(&resp1)!=SD_OK)return SD_CARD_ERROR;
  856. else return (SDCardState)((resp1>>9) & 0x0F);
  857. }
  858. //查找SD卡的SCR寄存器值
  859. //rca:卡相对地址
  860. //pscr:数据缓存区(存储SCR内容)
  861. //返回值:错误状态
  862. SD_Error FindSCR(u16 rca,u32 *pscr)
  863. {
  864. SD_Error errorstatus = SD_OK;
  865. u32 tempscr[2]={0,0};
  866. SDMMC_Send_Cmd(SD_CMD_SET_BLOCKLEN,1,8); //发送CMD16,短响应,设置Block Size为8字节
  867. errorstatus=CmdResp1Error(SD_CMD_SET_BLOCKLEN);
  868. if(errorstatus!=SD_OK)return errorstatus;
  869. SDMMC_Send_Cmd(SD_CMD_APP_CMD,1,(u32)rca<<16); //发送CMD55,短响应
  870. errorstatus=CmdResp1Error(SD_CMD_APP_CMD);
  871. if(errorstatus!=SD_OK)return errorstatus;
  872. SDMMC_Send_Data_Cfg(SD_DATATIMEOUT,8,3,1); //8个字节长度,block为8字节,SD卡到SDMMC.
  873. SDMMC_Send_Cmd(SD_CMD_SD_APP_SEND_SCR,1,0); //发送ACMD51,短响应,参数为0
  874. errorstatus=CmdResp1Error(SD_CMD_SD_APP_SEND_SCR);
  875. if(errorstatus!=SD_OK)return errorstatus;
  876. while(!(SDMMC1->STA&(SDMMC_STA_RXOVERR|SDMMC_STA_DCRCFAIL|SDMMC_STA_DTIMEOUT|SDMMC_STA_DBCKEND|SDMMC_STA_DATAEND)))
  877. {
  878. if(!(SDMMC1->STA&(1<<19))) //接收FIFO数据可用
  879. {
  880. tempscr[0]=SDMMC1->FIFO; //读取FIFO内容
  881. tempscr[1]=SDMMC1->FIFO; //读取FIFO内容
  882. break;
  883. }
  884. }
  885. if(SDMMC1->STA&(1<<3)) //接收数据超时
  886. {
  887. SDMMC1->ICR|=1<<3; //清除标记
  888. return SD_DATA_TIMEOUT;
  889. }else if(SDMMC1->STA&(1<<1))//已发送/接收的数据块CRC校验错误
  890. {
  891. SDMMC1->ICR|=1<<1; //清除标记
  892. return SD_DATA_CRC_FAIL;
  893. }else if(SDMMC1->STA&(1<<5))//接收FIFO溢出
  894. {
  895. SDMMC1->ICR|=1<<5; //清除标记
  896. return SD_RX_OVERRUN;
  897. }
  898. SDMMC1->ICR=0X1FE00FFF; //清除标记
  899. //把数据顺序按8位为单位倒过来.
  900. *(pscr+1)=((tempscr[0]&SD_0TO7BITS)<<24)|((tempscr[0]&SD_8TO15BITS)<<8)|((tempscr[0]&SD_16TO23BITS)>>8)|((tempscr[0]&SD_24TO31BITS)>>24);
  901. *(pscr)=((tempscr[1]&SD_0TO7BITS)<<24)|((tempscr[1]&SD_8TO15BITS)<<8)|((tempscr[1]&SD_16TO23BITS)>>8)|((tempscr[1]&SD_24TO31BITS)>>24);
  902. return errorstatus;
  903. }
  904. //读SD卡
  905. //buf:读数据缓存区
  906. //sector:扇区地址
  907. //cnt:扇区个数
  908. //返回值:错误状态;0,正常;其他,错误代码;
  909. u8 SD_ReadDisk(u8*buf,u32 sector,u32 cnt)
  910. {
  911. u8 sta=SD_OK;
  912. long long lsector=sector;
  913. u32 n;
  914. if(CardType!=STD_CAPACITY_SD_CARD_V1_1)lsector<<=9;
  915. if((u32)buf%4!=0)
  916. {
  917. for(n=0;n<cnt;n++)
  918. {
  919. sta=SD_ReadBlocks(SDMMC_DATA_BUFFER,lsector+512*n,512,1);//单个sector的读操作
  920. memcpy(buf,SDMMC_DATA_BUFFER,512);
  921. buf+=512;
  922. }
  923. }else sta=SD_ReadBlocks(buf,lsector,512,cnt); //单个/多个sector
  924. return sta;
  925. }
  926. //写SD卡
  927. //buf:写数据缓存区
  928. //sector:扇区地址
  929. //cnt:扇区个数
  930. //返回值:错误状态;0,正常;其他,错误代码;
  931. u8 SD_WriteDisk(u8*buf,u32 sector,u32 cnt)
  932. {
  933. u8 sta=SD_OK;
  934. u32 n;
  935. long long lsector=sector;
  936. if(CardType!=STD_CAPACITY_SD_CARD_V1_1)lsector<<=9;
  937. if((u32)buf%4!=0)
  938. {
  939. for(n=0;n<cnt;n++)
  940. {
  941. memcpy(SDMMC_DATA_BUFFER,buf,512);
  942. sta=SD_WriteBlocks(SDMMC_DATA_BUFFER,lsector+512*n,512,1);//单个sector的写操作
  943. buf+=512;
  944. }
  945. }else sta=SD_WriteBlocks(buf,lsector,512,cnt); //单个/多个sector
  946. return sta;
  947. }
  948. #endif