SWM320_sdio.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /******************************************************************************************************************************************
  2. * 文件名称: SWM320_sdio.c
  3. * 功能说明: SWM320单片机的SDIO接口驱动库
  4. * 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1
  5. * 注意事项: 为了通用性、兼容性、易用性,只支持以512字节为单位的读写
  6. * 版本日期: V1.1.0 2017年10月25日
  7. * 升级记录:
  8. *
  9. *
  10. *******************************************************************************************************************************************
  11. * @attention
  12. *
  13. * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION
  14. * REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE
  15. * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
  16. * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN-
  17. * -ECTION WITH THEIR PRODUCTS.
  18. *
  19. * COPYRIGHT 2012 Synwit Technology
  20. *******************************************************************************************************************************************/
  21. #include "SWM320.h"
  22. #include "SWM320_sdio.h"
  23. SD_CardInfo SD_cardInfo;
  24. /******************************************************************************************************************************************
  25. * 函数名称: SDIO_Init()
  26. * 功能说明: SDIO读写SD卡初始化,初始化成高速4线模式、读写以512字节大小进行
  27. * 输 入: 无
  28. * 输 出: 无
  29. * 注意事项: 无
  30. ******************************************************************************************************************************************/
  31. uint32_t SDIO_Init(void)
  32. {
  33. uint32_t resp, resps[4];
  34. SYS->CLKDIV &= ~SYS_CLKDIV_SDIO_Msk;
  35. if (SystemCoreClock > 80000000) //SDIO时钟需要小于52MHz
  36. SYS->CLKDIV |= (2 << SYS_CLKDIV_SDIO_Pos); //SDCLK = SYSCLK / 4
  37. else
  38. SYS->CLKDIV |= (1 << SYS_CLKDIV_SDIO_Pos); //SDCLK = SYSCLK / 2
  39. SYS->CLKEN |= (0x01 << SYS_CLKEN_SDIO_Pos);
  40. SDIO->CR2 = (1 << SDIO_CR2_RSTALL_Pos);
  41. SDIO->CR1 = (1 << SDIO_CR1_CDSRC_Pos) |
  42. (0 << SDIO_CR1_8BIT_Pos) |
  43. (0 << SDIO_CR1_4BIT_Pos) |
  44. (1 << SDIO_CR1_PWRON_Pos) |
  45. (7 << SDIO_CR1_VOLT_Pos);
  46. SDIO->CR2 = (1 << SDIO_CR2_CLKEN_Pos) |
  47. (1 << SDIO_CR2_SDCLKEN_Pos) |
  48. (calcSDCLKDiv(SD_CLK_400KHz) << SDIO_CR2_SDCLKDIV_Pos) |
  49. (0xC << SDIO_CR2_TIMEOUT_Pos);
  50. while ((SDIO->CR2 & SDIO_CR2_CLKRDY_Msk) == 0);
  51. SDIO->IE = 0xFFFF01FF;
  52. SDIO->IM = 0x00FF00FF;
  53. SDIO_SendCmd(SD_CMD_GO_IDLE_STATE, 0x00, SD_RESP_NO, 0, 0, 0); //CMD0: GO_IDLE_STATE
  54. SDIO_SendCmd(SD_CMD_SEND_IF_COND, 0x1AA, SD_RESP_32b, &resp, 0, 0); //CMD8: SEND_IF_COND, 检测工作电压、检测是否支持SD 2.0
  55. if (resp == 0x1AA) SD_cardInfo.CardType = SDIO_STD_CAPACITY_SD_CARD_V2_0;
  56. else SD_cardInfo.CardType = SDIO_STD_CAPACITY_SD_CARD_V1_1;
  57. do //ACMD41: SD_CMD_SD_APP_OP_COND
  58. {
  59. SDIO_SendCmd(SD_CMD_APP_CMD, 0x00, SD_RESP_32b, &resp, 0, 0);
  60. if (resp != 0x120) return SD_RES_ERR; //不是SD卡,可能是MMC卡
  61. if (SD_cardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0)
  62. SDIO_SendCmd(SD_CMD_SD_APP_OP_COND, 0x80100000 | 0x40000000, SD_RESP_32b, &resp, 0, 0);
  63. else
  64. SDIO_SendCmd(SD_CMD_SD_APP_OP_COND, 0x80100000 | 0x00000000, SD_RESP_32b, &resp, 0, 0);
  65. }
  66. while (((resp >> 31) & 0x01) == 0); //上电没完成时resp[31] == 0
  67. if (((resp >> 30) & 0x01) == 1) SD_cardInfo.CardType = SDIO_HIGH_CAPACITY_SD_CARD;
  68. SDIO_SendCmd(SD_CMD_ALL_SEND_CID, 0x00, SD_RESP_128b, resps, 0, 0); //CMD2: SD_CMD_ALL_SEND_CID,获取CID
  69. parseCID(resps);
  70. SDIO_SendCmd(SD_CMD_SET_REL_ADDR, 0x00, SD_RESP_32b, &resp, 0, 0); //CMD3: SD_CMD_SET_REL_ADDR,设置RCA
  71. SD_cardInfo.RCA = resp >> 16;
  72. SDIO_SendCmd(SD_CMD_SEND_CSD, SD_cardInfo.RCA << 16, SD_RESP_128b, resps, 0, 0); //CMD9: SD_CMD_SEND_CSD,获取CSD
  73. parseCSD(resps);
  74. if (SD_cardInfo.CardBlockSize < 0x200) return SD_RES_ERR; //本驱动只支持以512字节为单位的读写,所以最大读写单位必须不小于512
  75. SDIO->CR2 &= ~(SDIO_CR2_SDCLKEN_Msk | SDIO_CR2_SDCLKDIV_Msk);
  76. SDIO->CR2 |= (1 << SDIO_CR2_SDCLKEN_Pos) |
  77. (calcSDCLKDiv(SD_CLK_20MHz) << SDIO_CR2_SDCLKDIV_Pos); //初始化完成,SDCLK切换到高速
  78. SDIO_SendCmd(SD_CMD_SEL_DESEL_CARD, SD_cardInfo.RCA << 16, SD_RESP_32b_busy, &resp, 0, 0); //CMD7: 选中卡,从Standy模式进入Transfer模式
  79. SDIO_SendCmd(SD_CMD_APP_CMD, SD_cardInfo.RCA << 16, SD_RESP_32b, &resp, 0, 0);
  80. SDIO_SendCmd(SD_CMD_APP_SD_SET_BUSWIDTH, SD_BUSWIDTH_4b, SD_RESP_32b, &resp, 0, 0); //切换成4位总线模式
  81. SDIO->CR1 |= (1 << SDIO_CR1_4BIT_Pos);
  82. SDIO_SendCmd(SD_CMD_SET_BLOCKLEN, 512, SD_RESP_32b, &resp, 0, 0); //固定块大小位512字节
  83. SDIO->BLK = 512;
  84. return SD_RES_OK;
  85. }
  86. /******************************************************************************************************************************************
  87. * 函数名称: SDIO_BlockWrite()
  88. * 功能说明: 向SD卡写入数据
  89. * 输 入: uint32_t block_addr SD卡块地址,每块512字节
  90. * uint32_t buff[] 要写入的数据
  91. * 输 出: 无
  92. * 注意事项: 无
  93. ******************************************************************************************************************************************/
  94. void SDIO_BlockWrite(uint32_t block_addr, uint32_t buff[])
  95. {
  96. uint32_t i, resp, addr;
  97. if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) addr = block_addr;
  98. else addr = block_addr * 512;
  99. SDIO_SendCmd(SD_CMD_WRITE_SINGLE_BLOCK, addr, SD_RESP_32b, &resp, 1, 0);
  100. while ((SDIO->IF & SDIO_IF_BUFWRRDY_Msk) == 0);
  101. SDIO->IF = SDIO_IF_BUFWRRDY_Msk;
  102. for (i = 0; i < 512 / 4; i++) SDIO->DATA = buff[i];
  103. SDIO->IF = SDIO_IF_TRXDONE_Msk; //?? 这个必须有
  104. while ((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0);
  105. SDIO->IF = SDIO_IF_TRXDONE_Msk;
  106. }
  107. /******************************************************************************************************************************************
  108. * 函数名称: SDIO_BlockRead()
  109. * 功能说明: 从SD卡读出数据
  110. * 输 入: uint32_t block_addr SD卡块地址,每块512字节
  111. * uint32_t buff[] 读出的数据
  112. * 输 出: 无
  113. * 注意事项: 无
  114. ******************************************************************************************************************************************/
  115. void SDIO_BlockRead(uint32_t block_addr, uint32_t buff[])
  116. {
  117. uint32_t i, resp, addr;
  118. if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) addr = block_addr;
  119. else addr = block_addr * 512;
  120. SDIO_SendCmd(SD_CMD_READ_SINGLE_BLOCK, addr, SD_RESP_32b, &resp, 1, 1);
  121. while ((SDIO->IF & SDIO_IF_BUFRDRDY_Msk) == 0);
  122. SDIO->IF = SDIO_IF_BUFRDRDY_Msk;
  123. for (i = 0; i < 512 / 4; i++) buff[i] = SDIO->DATA;
  124. while ((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0);
  125. SDIO->IF = SDIO_IF_TRXDONE_Msk;
  126. }
  127. /******************************************************************************************************************************************
  128. * 函数名称: SDIO_SendCmd()
  129. * 功能说明: SDIO向SD卡发送命令
  130. * 输 入: uint32_t cmd 命令索引
  131. * uint32_t arg 命令参数
  132. * uint32_t resp_type 响应类型,取值SD_RESP_NO、SD_RESP_32b、SD_RESP_128b、SD_RESP_32b_busy
  133. * uint32_t *resp_data 响应内容
  134. * uint32_t have_data 是否有数据传输
  135. * uint32_t data_read 1 读SD卡 0 写SD卡
  136. * 输 出: 无
  137. * 注意事项: 无
  138. ******************************************************************************************************************************************/
  139. void SDIO_SendCmd(uint32_t cmd, uint32_t arg, uint32_t resp_type, uint32_t *resp_data, uint32_t have_data, uint32_t data_read)
  140. {
  141. SDIO->ARG = arg;
  142. SDIO->CMD = (cmd << SDIO_CMD_CMDINDX_Pos) |
  143. (0 << SDIO_CMD_CMDTYPE_Pos) |
  144. (have_data << SDIO_CMD_HAVEDATA_Pos) |
  145. (0 << SDIO_CMD_IDXCHECK_Pos) |
  146. (0 << SDIO_CMD_CRCCHECK_Pos) |
  147. (resp_type << SDIO_CMD_RESPTYPE_Pos) |
  148. (0 << SDIO_CMD_MULTBLK_Pos) |
  149. (data_read << SDIO_CMD_DIRREAD_Pos) |
  150. (0 << SDIO_CMD_BLKCNTEN_Pos);
  151. while ((SDIO->IF & SDIO_IF_CMDDONE_Msk) == 0);
  152. SDIO->IF = SDIO_IF_CMDDONE_Msk;
  153. if (resp_type == SD_RESP_32b)
  154. {
  155. resp_data[0] = SDIO->RESP[0];
  156. }
  157. else if (resp_type == SD_RESP_128b)
  158. {
  159. //寄存器中将CID/CSD[127-8]依次存放在了RESP3-0[119-0],最低位的CRC被丢掉
  160. //读出数据时调整了顺序,将CID/CSD[127-8]存放在resp_data0-3[127-8],最低8位填充0x00
  161. resp_data[0] = (SDIO->RESP[3] << 8) + ((SDIO->RESP[2] >> 24) & 0xFF);
  162. resp_data[1] = (SDIO->RESP[2] << 8) + ((SDIO->RESP[1] >> 24) & 0xFF);
  163. resp_data[2] = (SDIO->RESP[1] << 8) + ((SDIO->RESP[0] >> 24) & 0xFF);
  164. resp_data[3] = (SDIO->RESP[0] << 8) + 0x00;
  165. }
  166. }
  167. void parseCID(uint32_t CID_Tab[4])
  168. {
  169. uint8_t tmp = 0;
  170. /*!< Byte 0 */
  171. tmp = (uint8_t)((CID_Tab[0] & 0xFF000000) >> 24);
  172. SD_cardInfo.SD_cid.ManufacturerID = tmp;
  173. /*!< Byte 1 */
  174. tmp = (uint8_t)((CID_Tab[0] & 0x00FF0000) >> 16);
  175. SD_cardInfo.SD_cid.OEM_AppliID = tmp << 8;
  176. /*!< Byte 2 */
  177. tmp = (uint8_t)((CID_Tab[0] & 0x000000FF00) >> 8);
  178. SD_cardInfo.SD_cid.OEM_AppliID |= tmp;
  179. /*!< Byte 3 */
  180. tmp = (uint8_t)(CID_Tab[0] & 0x000000FF);
  181. SD_cardInfo.SD_cid.ProdName1 = tmp << 24;
  182. /*!< Byte 4 */
  183. tmp = (uint8_t)((CID_Tab[1] & 0xFF000000) >> 24);
  184. SD_cardInfo.SD_cid.ProdName1 |= tmp << 16;
  185. /*!< Byte 5 */
  186. tmp = (uint8_t)((CID_Tab[1] & 0x00FF0000) >> 16);
  187. SD_cardInfo.SD_cid.ProdName1 |= tmp << 8;
  188. /*!< Byte 6 */
  189. tmp = (uint8_t)((CID_Tab[1] & 0x0000FF00) >> 8);
  190. SD_cardInfo.SD_cid.ProdName1 |= tmp;
  191. /*!< Byte 7 */
  192. tmp = (uint8_t)(CID_Tab[1] & 0x000000FF);
  193. SD_cardInfo.SD_cid.ProdName2 = tmp;
  194. /*!< Byte 8 */
  195. tmp = (uint8_t)((CID_Tab[2] & 0xFF000000) >> 24);
  196. SD_cardInfo.SD_cid.ProdRev = tmp;
  197. /*!< Byte 9 */
  198. tmp = (uint8_t)((CID_Tab[2] & 0x00FF0000) >> 16);
  199. SD_cardInfo.SD_cid.ProdSN = tmp << 24;
  200. /*!< Byte 10 */
  201. tmp = (uint8_t)((CID_Tab[2] & 0x0000FF00) >> 8);
  202. SD_cardInfo.SD_cid.ProdSN |= tmp << 16;
  203. /*!< Byte 11 */
  204. tmp = (uint8_t)(CID_Tab[2] & 0x000000FF);
  205. SD_cardInfo.SD_cid.ProdSN |= tmp << 8;
  206. /*!< Byte 12 */
  207. tmp = (uint8_t)((CID_Tab[3] & 0xFF000000) >> 24);
  208. SD_cardInfo.SD_cid.ProdSN |= tmp;
  209. /*!< Byte 13 */
  210. tmp = (uint8_t)((CID_Tab[3] & 0x00FF0000) >> 16);
  211. SD_cardInfo.SD_cid.Reserved1 |= (tmp & 0xF0) >> 4;
  212. SD_cardInfo.SD_cid.ManufactDate = (tmp & 0x0F) << 8;
  213. /*!< Byte 14 */
  214. tmp = (uint8_t)((CID_Tab[3] & 0x0000FF00) >> 8);
  215. SD_cardInfo.SD_cid.ManufactDate |= tmp;
  216. }
  217. void parseCSD(uint32_t CSD_Tab[4])
  218. {
  219. uint8_t tmp = 0;
  220. /*!< Byte 0 */
  221. tmp = (uint8_t)((CSD_Tab[0] & 0xFF000000) >> 24);
  222. SD_cardInfo.SD_csd.CSDStruct = (tmp & 0xC0) >> 6;
  223. SD_cardInfo.SD_csd.SysSpecVersion = (tmp & 0x3C) >> 2;
  224. SD_cardInfo.SD_csd.Reserved1 = tmp & 0x03;
  225. /*!< Byte 1 */
  226. tmp = (uint8_t)((CSD_Tab[0] & 0x00FF0000) >> 16);
  227. SD_cardInfo.SD_csd.TAAC = tmp;
  228. /*!< Byte 2 */
  229. tmp = (uint8_t)((CSD_Tab[0] & 0x0000FF00) >> 8);
  230. SD_cardInfo.SD_csd.NSAC = tmp;
  231. /*!< Byte 3 */
  232. tmp = (uint8_t)(CSD_Tab[0] & 0x000000FF);
  233. SD_cardInfo.SD_csd.MaxBusClkFrec = tmp;
  234. /*!< Byte 4 */
  235. tmp = (uint8_t)((CSD_Tab[1] & 0xFF000000) >> 24);
  236. SD_cardInfo.SD_csd.CardComdClasses = tmp << 4;
  237. /*!< Byte 5 */
  238. tmp = (uint8_t)((CSD_Tab[1] & 0x00FF0000) >> 16);
  239. SD_cardInfo.SD_csd.CardComdClasses |= (tmp & 0xF0) >> 4;
  240. SD_cardInfo.SD_csd.RdBlockLen = tmp & 0x0F;
  241. /*!< Byte 6 */
  242. tmp = (uint8_t)((CSD_Tab[1] & 0x0000FF00) >> 8);
  243. SD_cardInfo.SD_csd.PartBlockRead = (tmp & 0x80) >> 7;
  244. SD_cardInfo.SD_csd.WrBlockMisalign = (tmp & 0x40) >> 6;
  245. SD_cardInfo.SD_csd.RdBlockMisalign = (tmp & 0x20) >> 5;
  246. SD_cardInfo.SD_csd.DSRImpl = (tmp & 0x10) >> 4;
  247. SD_cardInfo.SD_csd.Reserved2 = 0; /*!< Reserved */
  248. if ((SD_cardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V1_1) ||
  249. (SD_cardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0))
  250. {
  251. SD_cardInfo.SD_csd.DeviceSize = (tmp & 0x03) << 10;
  252. /*!< Byte 7 */
  253. tmp = (uint8_t)(CSD_Tab[1] & 0x000000FF);
  254. SD_cardInfo.SD_csd.DeviceSize |= (tmp) << 2;
  255. /*!< Byte 8 */
  256. tmp = (uint8_t)((CSD_Tab[2] & 0xFF000000) >> 24);
  257. SD_cardInfo.SD_csd.DeviceSize |= (tmp & 0xC0) >> 6;
  258. SD_cardInfo.SD_csd.MaxRdCurrentVDDMin = (tmp & 0x38) >> 3;
  259. SD_cardInfo.SD_csd.MaxRdCurrentVDDMax = (tmp & 0x07);
  260. /*!< Byte 9 */
  261. tmp = (uint8_t)((CSD_Tab[2] & 0x00FF0000) >> 16);
  262. SD_cardInfo.SD_csd.MaxWrCurrentVDDMin = (tmp & 0xE0) >> 5;
  263. SD_cardInfo.SD_csd.MaxWrCurrentVDDMax = (tmp & 0x1C) >> 2;
  264. SD_cardInfo.SD_csd.DeviceSizeMul = (tmp & 0x03) << 1;
  265. /*!< Byte 10 */
  266. tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8);
  267. SD_cardInfo.SD_csd.DeviceSizeMul |= (tmp & 0x80) >> 7;
  268. SD_cardInfo.CardCapacity = (SD_cardInfo.SD_csd.DeviceSize + 1) ;
  269. SD_cardInfo.CardCapacity *= (1 << (SD_cardInfo.SD_csd.DeviceSizeMul + 2));
  270. SD_cardInfo.CardBlockSize = 1 << (SD_cardInfo.SD_csd.RdBlockLen);
  271. SD_cardInfo.CardCapacity *= SD_cardInfo.CardBlockSize;
  272. }
  273. else if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  274. {
  275. /*!< Byte 7 */
  276. tmp = (uint8_t)(CSD_Tab[1] & 0x000000FF);
  277. SD_cardInfo.SD_csd.DeviceSize = (tmp & 0x3F) << 16;
  278. /*!< Byte 8 */
  279. tmp = (uint8_t)((CSD_Tab[2] & 0xFF000000) >> 24);
  280. SD_cardInfo.SD_csd.DeviceSize |= (tmp << 8);
  281. /*!< Byte 9 */
  282. tmp = (uint8_t)((CSD_Tab[2] & 0x00FF0000) >> 16);
  283. SD_cardInfo.SD_csd.DeviceSize |= (tmp);
  284. /*!< Byte 10 */
  285. tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8);
  286. SD_cardInfo.CardCapacity = (SD_cardInfo.SD_csd.DeviceSize + 1) * 512 * 1024;
  287. SD_cardInfo.CardBlockSize = 512;
  288. }
  289. SD_cardInfo.SD_csd.EraseGrSize = (tmp & 0x40) >> 6;
  290. SD_cardInfo.SD_csd.EraseGrMul = (tmp & 0x3F) << 1;
  291. /*!< Byte 11 */
  292. tmp = (uint8_t)(CSD_Tab[2] & 0x000000FF);
  293. SD_cardInfo.SD_csd.EraseGrMul |= (tmp & 0x80) >> 7;
  294. SD_cardInfo.SD_csd.WrProtectGrSize = (tmp & 0x7F);
  295. /*!< Byte 12 */
  296. tmp = (uint8_t)((CSD_Tab[3] & 0xFF000000) >> 24);
  297. SD_cardInfo.SD_csd.WrProtectGrEnable = (tmp & 0x80) >> 7;
  298. SD_cardInfo.SD_csd.ManDeflECC = (tmp & 0x60) >> 5;
  299. SD_cardInfo.SD_csd.WrSpeedFact = (tmp & 0x1C) >> 2;
  300. SD_cardInfo.SD_csd.MaxWrBlockLen = (tmp & 0x03) << 2;
  301. /*!< Byte 13 */
  302. tmp = (uint8_t)((CSD_Tab[3] & 0x00FF0000) >> 16);
  303. SD_cardInfo.SD_csd.MaxWrBlockLen |= (tmp & 0xC0) >> 6;
  304. SD_cardInfo.SD_csd.WriteBlockPaPartial = (tmp & 0x20) >> 5;
  305. SD_cardInfo.SD_csd.Reserved3 = 0;
  306. SD_cardInfo.SD_csd.ContentProtectAppli = (tmp & 0x01);
  307. /*!< Byte 14 */
  308. tmp = (uint8_t)((CSD_Tab[3] & 0x0000FF00) >> 8);
  309. SD_cardInfo.SD_csd.FileFormatGrouop = (tmp & 0x80) >> 7;
  310. SD_cardInfo.SD_csd.CopyFlag = (tmp & 0x40) >> 6;
  311. SD_cardInfo.SD_csd.PermWrProtect = (tmp & 0x20) >> 5;
  312. SD_cardInfo.SD_csd.TempWrProtect = (tmp & 0x10) >> 4;
  313. SD_cardInfo.SD_csd.FileFormat = (tmp & 0x0C) >> 2;
  314. SD_cardInfo.SD_csd.ECC = (tmp & 0x03);
  315. }
  316. uint32_t calcSDCLKDiv(uint32_t freq_sel)
  317. {
  318. uint32_t regdiv = 0;
  319. uint32_t clkdiv = 0;
  320. if (((SYS->CLKDIV & SYS_CLKDIV_SDIO_Msk) >> SYS_CLKDIV_SDIO_Pos) == 1)
  321. clkdiv = SystemCoreClock / 2 / ((freq_sel == SD_CLK_400KHz) ? 300000 : 15000000);
  322. else if (((SYS->CLKDIV & SYS_CLKDIV_SDIO_Msk) >> SYS_CLKDIV_SDIO_Pos) == 2)
  323. clkdiv = SystemCoreClock / 4 / ((freq_sel == SD_CLK_400KHz) ? 300000 : 15000000);
  324. if (clkdiv > 128) regdiv = 0x80;
  325. else if (clkdiv > 64) regdiv = 0x40;
  326. else if (clkdiv > 32) regdiv = 0x20;
  327. else if (clkdiv > 16) regdiv = 0x10;
  328. else if (clkdiv > 8) regdiv = 0x08;
  329. else if (clkdiv > 4) regdiv = 0x04;
  330. else if (clkdiv > 2) regdiv = 0x02;
  331. else if (clkdiv > 1) regdiv = 0x01;
  332. else regdiv = 0x00;
  333. return regdiv;
  334. }