SWM320_sdio.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  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. * 输 入: uint32_t freq SDIO_CLK时钟频率
  28. * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
  29. * 注意事项: 无
  30. ******************************************************************************************************************************************/
  31. uint32_t SDIO_Init(uint32_t freq)
  32. {
  33. uint32_t res;
  34. uint32_t resp, resps[4];
  35. SYS->CLKDIV &= ~SYS_CLKDIV_SDIO_Msk;
  36. if (SystemCoreClock > 80000000) //SDIO时钟需要小于52MHz
  37. SYS->CLKDIV |= (2 << SYS_CLKDIV_SDIO_Pos); //SDCLK = SYSCLK / 4
  38. else
  39. SYS->CLKDIV |= (1 << SYS_CLKDIV_SDIO_Pos); //SDCLK = SYSCLK / 2
  40. SYS->CLKEN |= (0x01 << SYS_CLKEN_SDIO_Pos);
  41. SDIO->CR2 = (1 << SDIO_CR2_RSTALL_Pos);
  42. SDIO->CR1 = (1 << SDIO_CR1_CDSRC_Pos) |
  43. (0 << SDIO_CR1_8BIT_Pos) |
  44. (0 << SDIO_CR1_4BIT_Pos) |
  45. (1 << SDIO_CR1_PWRON_Pos) |
  46. (7 << SDIO_CR1_VOLT_Pos);
  47. SDIO->CR2 = (1 << SDIO_CR2_CLKEN_Pos) |
  48. (1 << SDIO_CR2_SDCLKEN_Pos) |
  49. (calcSDCLKDiv(100000) << SDIO_CR2_SDCLKDIV_Pos) |
  50. (0xC << SDIO_CR2_TIMEOUT_Pos); // 2**25 SDIO_CLK
  51. while ((SDIO->CR2 & SDIO_CR2_CLKRDY_Msk) == 0)
  52. ;
  53. SDIO->IFE = 0xFFFFFFFF;
  54. SDIO_SendCmd(SD_CMD_GO_IDLE_STATE, 0x00, SD_RESP_NO, 0); //CMD0: GO_IDLE_STATE
  55. res = SDIO_SendCmd(SD_CMD_SEND_IF_COND, 0x1AA, SD_RESP_32b, &resp); //CMD8: SEND_IF_COND, 检测工作电压、检测是否支持SD 2.0
  56. if (res != SD_RES_OK)
  57. return res;
  58. if (resp == 0x1AA)
  59. SD_cardInfo.CardType = SDIO_STD_CAPACITY_SD_CARD_V2_0;
  60. else
  61. SD_cardInfo.CardType = SDIO_STD_CAPACITY_SD_CARD_V1_1;
  62. do //ACMD41: SD_CMD_SD_APP_OP_COND
  63. {
  64. res = SDIO_SendCmd(SD_CMD_APP_CMD, 0x00, SD_RESP_32b, &resp);
  65. if (res != SD_RES_OK)
  66. return res;
  67. if (resp != 0x120)
  68. return SD_RES_ERR; //不是SD卡,可能是MMC卡
  69. if (SD_cardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0)
  70. SDIO_SendCmd(SD_CMD_SD_APP_OP_COND, 0x80100000 | 0x40000000, SD_RESP_32b, &resp);
  71. else
  72. SDIO_SendCmd(SD_CMD_SD_APP_OP_COND, 0x80100000 | 0x00000000, SD_RESP_32b, &resp);
  73. } while (((resp >> 31) & 0x01) == 0); //上电没完成时resp[31] == 0
  74. if (((resp >> 30) & 0x01) == 1)
  75. SD_cardInfo.CardType = SDIO_HIGH_CAPACITY_SD_CARD;
  76. SDIO_SendCmd(SD_CMD_ALL_SEND_CID, 0x00, SD_RESP_128b, resps); //CMD2: SD_CMD_ALL_SEND_CID,获取CID
  77. parseCID(resps);
  78. SDIO_SendCmd(SD_CMD_SET_REL_ADDR, 0x00, SD_RESP_32b, &resp); //CMD3: SD_CMD_SET_REL_ADDR,设置RCA
  79. SD_cardInfo.RCA = resp >> 16;
  80. SDIO_SendCmd(SD_CMD_SEND_CSD, SD_cardInfo.RCA << 16, SD_RESP_128b, resps); //CMD9: SD_CMD_SEND_CSD,获取CSD
  81. parseCSD(resps);
  82. if (SD_cardInfo.CardBlockSize < 0x200)
  83. return SD_RES_ERR; //本驱动只支持以512字节为单位的读写,所以最大读写单位必须不小于512
  84. SDIO->CR2 &= ~(SDIO_CR2_SDCLKEN_Msk | SDIO_CR2_SDCLKDIV_Msk);
  85. SDIO->CR2 |= (1 << SDIO_CR2_SDCLKEN_Pos) |
  86. (calcSDCLKDiv(freq) << SDIO_CR2_SDCLKDIV_Pos); //初始化完成,SDCLK切换到高速
  87. SDIO_SendCmd(SD_CMD_SEL_DESEL_CARD, SD_cardInfo.RCA << 16, SD_RESP_32b_busy, &resp); //CMD7: 选中卡,从Standy模式进入Transfer模式
  88. SDIO->IF = SDIO_IF_TRXDONE_Msk;
  89. SDIO_SendCmd(SD_CMD_APP_CMD, SD_cardInfo.RCA << 16, SD_RESP_32b, &resp);
  90. SDIO_SendCmd(SD_CMD_APP_SD_SET_BUSWIDTH, SD_BUSWIDTH_4b, SD_RESP_32b, &resp); //切换成4位总线模式
  91. SDIO->CR1 |= (1 << SDIO_CR1_4BIT_Pos);
  92. SDIO_SendCmd(SD_CMD_SET_BLOCKLEN, 512, SD_RESP_32b, &resp); //固定块大小位512字节
  93. SDIO->BLK = 512;
  94. return SD_RES_OK;
  95. }
  96. /******************************************************************************************************************************************
  97. * 函数名称: SDIO_BlockWrite()
  98. * 功能说明: 向SD卡写入数据
  99. * 输 入: uint32_t block_addr SD卡块地址,每块512字节
  100. * uint32_t buff[] 要写入的数据
  101. * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
  102. * 注意事项: 无
  103. ******************************************************************************************************************************************/
  104. uint32_t SDIO_BlockWrite(uint32_t block_addr, uint32_t buff[])
  105. {
  106. uint32_t res, i;
  107. uint32_t addr, resp;
  108. if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  109. addr = block_addr;
  110. else
  111. addr = block_addr * 512;
  112. res = SDIO_SendCmdWithData(SD_CMD_WRITE_SINGLE_BLOCK, addr, SD_RESP_32b, &resp, 0, 1);
  113. if (res != SD_RES_OK)
  114. return res;
  115. while ((SDIO->IF & SDIO_IF_BUFWRRDY_Msk) == 0)
  116. __NOP();
  117. SDIO->IF = SDIO_IF_BUFWRRDY_Msk;
  118. for (i = 0; i < 512 / 4; i++)
  119. SDIO->DATA = buff[i];
  120. while ((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0)
  121. __NOP();
  122. SDIO->IF = SDIO_IF_TRXDONE_Msk;
  123. return SD_RES_OK;
  124. }
  125. /******************************************************************************************************************************************
  126. * 函数名称: SDIO_MultiBlockWrite()
  127. * 功能说明: 向SD卡写入多块数据
  128. * 输 入: uint32_t block_addr SD卡块地址,每块512字节
  129. * uint16_t block_cnt 要写入的块数
  130. * uint32_t buff[] 要写入的数据
  131. * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
  132. * 注意事项: 无
  133. ******************************************************************************************************************************************/
  134. uint32_t SDIO_MultiBlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[])
  135. {
  136. uint32_t res, i, j;
  137. uint32_t addr, resp;
  138. if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  139. addr = block_addr;
  140. else
  141. addr = block_addr * 512;
  142. res = SDIO_SendCmdWithData(SD_CMD_WRITE_MULT_BLOCK, addr, SD_RESP_32b, &resp, 0, block_cnt);
  143. if (res != SD_RES_OK)
  144. return res;
  145. for (i = 0; i < block_cnt; i++)
  146. {
  147. while ((SDIO->IF & SDIO_IF_BUFWRRDY_Msk) == 0)
  148. __NOP();
  149. SDIO->IF = SDIO_IF_BUFWRRDY_Msk;
  150. for (j = 0; j < 512 / 4; j++)
  151. SDIO->DATA = buff[i * (512 / 4) + j];
  152. }
  153. while ((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0)
  154. __NOP();
  155. SDIO->IF = SDIO_IF_TRXDONE_Msk;
  156. return SD_RES_OK;
  157. }
  158. /******************************************************************************************************************************************
  159. * 函数名称: SDIO_DMABlockWrite()
  160. * 功能说明: 通过DMA向SD卡写入多块数据
  161. * 输 入: uint32_t block_addr SD卡块地址,每块512字节
  162. * uint16_t block_cnt 要写入的块数
  163. * uint32_t buff[] 要写入的数据
  164. * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
  165. * 注意事项: 无
  166. ******************************************************************************************************************************************/
  167. uint32_t SDIO_DMABlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[])
  168. {
  169. uint32_t res;
  170. uint32_t addr, resp;
  171. if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  172. addr = block_addr;
  173. else
  174. addr = block_addr * 512;
  175. SDIO->DMA_MEM_ADDR = (uint32_t)buff;
  176. res = SDIO_SendCmdWithDataByDMA(SD_CMD_WRITE_MULT_BLOCK, addr, SD_RESP_32b, &resp, 0, block_cnt);
  177. if (res != SD_RES_OK)
  178. return res;
  179. while ((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0)
  180. __NOP();
  181. SDIO->IF = SDIO_IF_TRXDONE_Msk;
  182. return SD_RES_OK;
  183. }
  184. /******************************************************************************************************************************************
  185. * 函数名称: SDIO_BlockRead()
  186. * 功能说明: 从SD卡读出数据
  187. * 输 入: uint32_t block_addr SD卡块地址,每块512字节
  188. * uint32_t buff[] 读出的数据
  189. * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
  190. * 注意事项: 无
  191. ******************************************************************************************************************************************/
  192. uint32_t SDIO_BlockRead(uint32_t block_addr, uint32_t buff[])
  193. {
  194. uint32_t res, i;
  195. uint32_t addr, resp;
  196. if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  197. addr = block_addr;
  198. else
  199. addr = block_addr * 512;
  200. res = SDIO_SendCmdWithData(SD_CMD_READ_SINGLE_BLOCK, addr, SD_RESP_32b, &resp, 1, 1);
  201. if (res != SD_RES_OK)
  202. return res;
  203. while ((SDIO->IF & SDIO_IF_BUFRDRDY_Msk) == 0)
  204. __NOP();
  205. SDIO->IF = SDIO_IF_BUFRDRDY_Msk;
  206. for (i = 0; i < 512 / 4; i++)
  207. buff[i] = SDIO->DATA;
  208. while ((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0)
  209. __NOP();
  210. SDIO->IF = SDIO_IF_TRXDONE_Msk;
  211. return SD_RES_OK;
  212. }
  213. /******************************************************************************************************************************************
  214. * 函数名称: SDIO_MultiBlockRead()
  215. * 功能说明: 从SD卡读出多块数据
  216. * 输 入: uint32_t block_addr SD卡块地址,每块512字节
  217. * uint16_t block_cnt 要读出的块数
  218. * uint32_t buff[] 读出的数据
  219. * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
  220. * 注意事项: 无
  221. ******************************************************************************************************************************************/
  222. uint32_t SDIO_MultiBlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[])
  223. {
  224. uint32_t res, i, j;
  225. uint32_t addr, resp;
  226. if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  227. addr = block_addr;
  228. else
  229. addr = block_addr * 512;
  230. res = SDIO_SendCmdWithData(SD_CMD_READ_MULT_BLOCK, addr, SD_RESP_32b, &resp, 1, block_cnt);
  231. if (res != SD_RES_OK)
  232. return res;
  233. for (i = 0; i < block_cnt; i++)
  234. {
  235. while ((SDIO->IF & SDIO_IF_BUFRDRDY_Msk) == 0)
  236. __NOP();
  237. SDIO->IF = SDIO_IF_BUFRDRDY_Msk;
  238. for (j = 0; j < 512 / 4; j++)
  239. buff[i * (512 / 4) + j] = SDIO->DATA;
  240. }
  241. while ((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0)
  242. __NOP();
  243. SDIO->IF = SDIO_IF_TRXDONE_Msk;
  244. return SD_RES_OK;
  245. }
  246. /******************************************************************************************************************************************
  247. * 函数名称: SDIO_DMABlockRead()
  248. * 功能说明: 通过DMA从SD卡读出多块数据
  249. * 输 入: uint32_t block_addr SD卡块地址,每块512字节
  250. * uint16_t block_cnt 要读出的块数
  251. * uint32_t buff[] 读出的数据
  252. * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
  253. * 注意事项: 无
  254. ******************************************************************************************************************************************/
  255. uint32_t SDIO_DMABlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[])
  256. {
  257. uint32_t res;
  258. uint32_t addr, resp;
  259. if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  260. addr = block_addr;
  261. else
  262. addr = block_addr * 512;
  263. SDIO->DMA_MEM_ADDR = (uint32_t)buff;
  264. res = SDIO_SendCmdWithDataByDMA(SD_CMD_READ_MULT_BLOCK, addr, SD_RESP_32b, &resp, 1, block_cnt);
  265. if (res != SD_RES_OK)
  266. return res;
  267. while ((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0)
  268. __NOP();
  269. SDIO->IF = SDIO_IF_TRXDONE_Msk;
  270. return SD_RES_OK;
  271. }
  272. /******************************************************************************************************************************************
  273. * 函数名称: _SDIO_SendCmd()
  274. * 功能说明: SDIO向SD卡发送命令
  275. * 输 入: uint32_t cmd 命令索引
  276. * uint32_t arg 命令参数
  277. * uint32_t resp_type 响应类型,取值SD_RESP_NO、SD_RESP_32b、SD_RESP_128b、SD_RESP_32b_busy
  278. * uint32_t *resp_data 响应内容
  279. * uint32_t have_data 是否有数据传输
  280. * uint32_t data_read 1 读SD卡 0 写SD卡
  281. * uint16_t block_cnt 读写块个数
  282. * uint32_t use_dma 1 使用DMA搬运数据
  283. * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
  284. * 注意事项: 无
  285. ******************************************************************************************************************************************/
  286. uint32_t _SDIO_SendCmd(uint32_t cmd, uint32_t arg, uint32_t resp_type, uint32_t *resp_data, uint32_t have_data, uint32_t data_read, uint16_t block_cnt, uint32_t use_dma)
  287. {
  288. SDIO->BLK &= ~SDIO_BLK_COUNT_Msk;
  289. SDIO->BLK |= (block_cnt << SDIO_BLK_COUNT_Pos);
  290. SDIO->ARG = arg;
  291. SDIO->CMD = (cmd << SDIO_CMD_CMDINDX_Pos) |
  292. (0 << SDIO_CMD_CMDTYPE_Pos) |
  293. (0 << SDIO_CMD_IDXCHECK_Pos) |
  294. (0 << SDIO_CMD_CRCCHECK_Pos) |
  295. (resp_type << SDIO_CMD_RESPTYPE_Pos) |
  296. (have_data << SDIO_CMD_HAVEDATA_Pos) |
  297. (data_read << SDIO_CMD_DIRREAD_Pos) |
  298. ((block_cnt > 1) << SDIO_CMD_MULTBLK_Pos) |
  299. ((block_cnt > 1) << SDIO_CMD_BLKCNTEN_Pos) |
  300. ((block_cnt > 1) << SDIO_CMD_AUTOCMD12_Pos) |
  301. (use_dma << SDIO_CMD_DMAEN_Pos);
  302. while ((SDIO->IF & SDIO_IF_CMDDONE_Msk) == 0)
  303. {
  304. if (SDIO->IF & SDIO_IF_CMDTIMEOUT_Msk)
  305. {
  306. SDIO->IF = SDIO_IF_CMDTIMEOUT_Msk;
  307. return SD_RES_TIMEOUT;
  308. }
  309. else if (SDIO->IF & SDIO_IF_ERROR_Msk)
  310. {
  311. SDIO->IF = 0xFFFFFFFF;
  312. return SD_RES_ERR;
  313. }
  314. }
  315. SDIO->IF = SDIO_IF_CMDDONE_Msk;
  316. if (resp_type == SD_RESP_32b)
  317. {
  318. resp_data[0] = SDIO->RESP[0];
  319. }
  320. else if (resp_type == SD_RESP_128b)
  321. {
  322. //寄存器中将CID/CSD[127-8]依次存放在了RESP3-0[119-0],最低位的CRC被丢掉
  323. //读出数据时调整了顺序,将CID/CSD[127-8]存放在resp_data0-3[127-8],最低8位填充0x00
  324. resp_data[0] = (SDIO->RESP[3] << 8) + ((SDIO->RESP[2] >> 24) & 0xFF);
  325. resp_data[1] = (SDIO->RESP[2] << 8) + ((SDIO->RESP[1] >> 24) & 0xFF);
  326. resp_data[2] = (SDIO->RESP[1] << 8) + ((SDIO->RESP[0] >> 24) & 0xFF);
  327. resp_data[3] = (SDIO->RESP[0] << 8) + 0x00;
  328. }
  329. return SD_RES_OK;
  330. }
  331. void parseCID(uint32_t CID_Tab[4])
  332. {
  333. uint8_t tmp = 0;
  334. /*!< Byte 0 */
  335. tmp = (uint8_t)((CID_Tab[0] & 0xFF000000) >> 24);
  336. SD_cardInfo.SD_cid.ManufacturerID = tmp;
  337. /*!< Byte 1 */
  338. tmp = (uint8_t)((CID_Tab[0] & 0x00FF0000) >> 16);
  339. SD_cardInfo.SD_cid.OEM_AppliID = tmp << 8;
  340. /*!< Byte 2 */
  341. tmp = (uint8_t)((CID_Tab[0] & 0x000000FF00) >> 8);
  342. SD_cardInfo.SD_cid.OEM_AppliID |= tmp;
  343. /*!< Byte 3 */
  344. tmp = (uint8_t)(CID_Tab[0] & 0x000000FF);
  345. SD_cardInfo.SD_cid.ProdName1 = tmp << 24;
  346. /*!< Byte 4 */
  347. tmp = (uint8_t)((CID_Tab[1] & 0xFF000000) >> 24);
  348. SD_cardInfo.SD_cid.ProdName1 |= tmp << 16;
  349. /*!< Byte 5 */
  350. tmp = (uint8_t)((CID_Tab[1] & 0x00FF0000) >> 16);
  351. SD_cardInfo.SD_cid.ProdName1 |= tmp << 8;
  352. /*!< Byte 6 */
  353. tmp = (uint8_t)((CID_Tab[1] & 0x0000FF00) >> 8);
  354. SD_cardInfo.SD_cid.ProdName1 |= tmp;
  355. /*!< Byte 7 */
  356. tmp = (uint8_t)(CID_Tab[1] & 0x000000FF);
  357. SD_cardInfo.SD_cid.ProdName2 = tmp;
  358. /*!< Byte 8 */
  359. tmp = (uint8_t)((CID_Tab[2] & 0xFF000000) >> 24);
  360. SD_cardInfo.SD_cid.ProdRev = tmp;
  361. /*!< Byte 9 */
  362. tmp = (uint8_t)((CID_Tab[2] & 0x00FF0000) >> 16);
  363. SD_cardInfo.SD_cid.ProdSN = tmp << 24;
  364. /*!< Byte 10 */
  365. tmp = (uint8_t)((CID_Tab[2] & 0x0000FF00) >> 8);
  366. SD_cardInfo.SD_cid.ProdSN |= tmp << 16;
  367. /*!< Byte 11 */
  368. tmp = (uint8_t)(CID_Tab[2] & 0x000000FF);
  369. SD_cardInfo.SD_cid.ProdSN |= tmp << 8;
  370. /*!< Byte 12 */
  371. tmp = (uint8_t)((CID_Tab[3] & 0xFF000000) >> 24);
  372. SD_cardInfo.SD_cid.ProdSN |= tmp;
  373. /*!< Byte 13 */
  374. tmp = (uint8_t)((CID_Tab[3] & 0x00FF0000) >> 16);
  375. SD_cardInfo.SD_cid.Reserved1 |= (tmp & 0xF0) >> 4;
  376. SD_cardInfo.SD_cid.ManufactDate = (tmp & 0x0F) << 8;
  377. /*!< Byte 14 */
  378. tmp = (uint8_t)((CID_Tab[3] & 0x0000FF00) >> 8);
  379. SD_cardInfo.SD_cid.ManufactDate |= tmp;
  380. }
  381. void parseCSD(uint32_t CSD_Tab[4])
  382. {
  383. uint8_t tmp = 0;
  384. /*!< Byte 0 */
  385. tmp = (uint8_t)((CSD_Tab[0] & 0xFF000000) >> 24);
  386. SD_cardInfo.SD_csd.CSDStruct = (tmp & 0xC0) >> 6;
  387. SD_cardInfo.SD_csd.SysSpecVersion = (tmp & 0x3C) >> 2;
  388. SD_cardInfo.SD_csd.Reserved1 = tmp & 0x03;
  389. /*!< Byte 1 */
  390. tmp = (uint8_t)((CSD_Tab[0] & 0x00FF0000) >> 16);
  391. SD_cardInfo.SD_csd.TAAC = tmp;
  392. /*!< Byte 2 */
  393. tmp = (uint8_t)((CSD_Tab[0] & 0x0000FF00) >> 8);
  394. SD_cardInfo.SD_csd.NSAC = tmp;
  395. /*!< Byte 3 */
  396. tmp = (uint8_t)(CSD_Tab[0] & 0x000000FF);
  397. SD_cardInfo.SD_csd.MaxBusClkFrec = tmp;
  398. /*!< Byte 4 */
  399. tmp = (uint8_t)((CSD_Tab[1] & 0xFF000000) >> 24);
  400. SD_cardInfo.SD_csd.CardComdClasses = tmp << 4;
  401. /*!< Byte 5 */
  402. tmp = (uint8_t)((CSD_Tab[1] & 0x00FF0000) >> 16);
  403. SD_cardInfo.SD_csd.CardComdClasses |= (tmp & 0xF0) >> 4;
  404. SD_cardInfo.SD_csd.RdBlockLen = tmp & 0x0F;
  405. /*!< Byte 6 */
  406. tmp = (uint8_t)((CSD_Tab[1] & 0x0000FF00) >> 8);
  407. SD_cardInfo.SD_csd.PartBlockRead = (tmp & 0x80) >> 7;
  408. SD_cardInfo.SD_csd.WrBlockMisalign = (tmp & 0x40) >> 6;
  409. SD_cardInfo.SD_csd.RdBlockMisalign = (tmp & 0x20) >> 5;
  410. SD_cardInfo.SD_csd.DSRImpl = (tmp & 0x10) >> 4;
  411. SD_cardInfo.SD_csd.Reserved2 = 0; /*!< Reserved */
  412. if ((SD_cardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V1_1) ||
  413. (SD_cardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0))
  414. {
  415. SD_cardInfo.SD_csd.DeviceSize = (tmp & 0x03) << 10;
  416. /*!< Byte 7 */
  417. tmp = (uint8_t)(CSD_Tab[1] & 0x000000FF);
  418. SD_cardInfo.SD_csd.DeviceSize |= (tmp) << 2;
  419. /*!< Byte 8 */
  420. tmp = (uint8_t)((CSD_Tab[2] & 0xFF000000) >> 24);
  421. SD_cardInfo.SD_csd.DeviceSize |= (tmp & 0xC0) >> 6;
  422. SD_cardInfo.SD_csd.MaxRdCurrentVDDMin = (tmp & 0x38) >> 3;
  423. SD_cardInfo.SD_csd.MaxRdCurrentVDDMax = (tmp & 0x07);
  424. /*!< Byte 9 */
  425. tmp = (uint8_t)((CSD_Tab[2] & 0x00FF0000) >> 16);
  426. SD_cardInfo.SD_csd.MaxWrCurrentVDDMin = (tmp & 0xE0) >> 5;
  427. SD_cardInfo.SD_csd.MaxWrCurrentVDDMax = (tmp & 0x1C) >> 2;
  428. SD_cardInfo.SD_csd.DeviceSizeMul = (tmp & 0x03) << 1;
  429. /*!< Byte 10 */
  430. tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8);
  431. SD_cardInfo.SD_csd.DeviceSizeMul |= (tmp & 0x80) >> 7;
  432. SD_cardInfo.CardCapacity = (SD_cardInfo.SD_csd.DeviceSize + 1);
  433. SD_cardInfo.CardCapacity *= (1 << (SD_cardInfo.SD_csd.DeviceSizeMul + 2));
  434. SD_cardInfo.CardBlockSize = 1 << (SD_cardInfo.SD_csd.RdBlockLen);
  435. SD_cardInfo.CardCapacity *= SD_cardInfo.CardBlockSize;
  436. }
  437. else if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  438. {
  439. /*!< Byte 7 */
  440. tmp = (uint8_t)(CSD_Tab[1] & 0x000000FF);
  441. SD_cardInfo.SD_csd.DeviceSize = (tmp & 0x3F) << 16;
  442. /*!< Byte 8 */
  443. tmp = (uint8_t)((CSD_Tab[2] & 0xFF000000) >> 24);
  444. SD_cardInfo.SD_csd.DeviceSize |= (tmp << 8);
  445. /*!< Byte 9 */
  446. tmp = (uint8_t)((CSD_Tab[2] & 0x00FF0000) >> 16);
  447. SD_cardInfo.SD_csd.DeviceSize |= (tmp);
  448. /*!< Byte 10 */
  449. tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8);
  450. SD_cardInfo.CardCapacity = (uint64_t)(SD_cardInfo.SD_csd.DeviceSize + 1) * 512 * 1024;
  451. SD_cardInfo.CardBlockSize = 512;
  452. }
  453. SD_cardInfo.SD_csd.EraseGrSize = (tmp & 0x40) >> 6;
  454. SD_cardInfo.SD_csd.EraseGrMul = (tmp & 0x3F) << 1;
  455. /*!< Byte 11 */
  456. tmp = (uint8_t)(CSD_Tab[2] & 0x000000FF);
  457. SD_cardInfo.SD_csd.EraseGrMul |= (tmp & 0x80) >> 7;
  458. SD_cardInfo.SD_csd.WrProtectGrSize = (tmp & 0x7F);
  459. /*!< Byte 12 */
  460. tmp = (uint8_t)((CSD_Tab[3] & 0xFF000000) >> 24);
  461. SD_cardInfo.SD_csd.WrProtectGrEnable = (tmp & 0x80) >> 7;
  462. SD_cardInfo.SD_csd.ManDeflECC = (tmp & 0x60) >> 5;
  463. SD_cardInfo.SD_csd.WrSpeedFact = (tmp & 0x1C) >> 2;
  464. SD_cardInfo.SD_csd.MaxWrBlockLen = (tmp & 0x03) << 2;
  465. /*!< Byte 13 */
  466. tmp = (uint8_t)((CSD_Tab[3] & 0x00FF0000) >> 16);
  467. SD_cardInfo.SD_csd.MaxWrBlockLen |= (tmp & 0xC0) >> 6;
  468. SD_cardInfo.SD_csd.WriteBlockPaPartial = (tmp & 0x20) >> 5;
  469. SD_cardInfo.SD_csd.Reserved3 = 0;
  470. SD_cardInfo.SD_csd.ContentProtectAppli = (tmp & 0x01);
  471. /*!< Byte 14 */
  472. tmp = (uint8_t)((CSD_Tab[3] & 0x0000FF00) >> 8);
  473. SD_cardInfo.SD_csd.FileFormatGrouop = (tmp & 0x80) >> 7;
  474. SD_cardInfo.SD_csd.CopyFlag = (tmp & 0x40) >> 6;
  475. SD_cardInfo.SD_csd.PermWrProtect = (tmp & 0x20) >> 5;
  476. SD_cardInfo.SD_csd.TempWrProtect = (tmp & 0x10) >> 4;
  477. SD_cardInfo.SD_csd.FileFormat = (tmp & 0x0C) >> 2;
  478. SD_cardInfo.SD_csd.ECC = (tmp & 0x03);
  479. }
  480. uint32_t calcSDCLKDiv(uint32_t freq)
  481. {
  482. uint32_t prediv = ((SYS->CLKDIV & SYS_CLKDIV_SDIO_Msk) >> SYS_CLKDIV_SDIO_Pos);
  483. uint32_t clkdiv = (SystemCoreClock / (1 << prediv)) / freq;
  484. uint32_t regdiv = 0;
  485. if (clkdiv > 128)
  486. regdiv = 0x80;
  487. else if (clkdiv > 64)
  488. regdiv = 0x40;
  489. else if (clkdiv > 32)
  490. regdiv = 0x20;
  491. else if (clkdiv > 16)
  492. regdiv = 0x10;
  493. else if (clkdiv > 8)
  494. regdiv = 0x08;
  495. else if (clkdiv > 4)
  496. regdiv = 0x04;
  497. else if (clkdiv > 2)
  498. regdiv = 0x02;
  499. else if (clkdiv > 1)
  500. regdiv = 0x01;
  501. else
  502. regdiv = 0x00;
  503. return regdiv;
  504. }