SWM320_sdio.c 23 KB

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