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