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