1 /******************************************************************************************************************************************
2 * 文件名称: SWM341_sdio.c
3 * 功能说明: SWM341单片机的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 "SWM341.h"
22 #include "SWM341_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 res;
37 uint32_t resp, resps[4];
38
39 SYS->CLKSEL &= ~SYS_CLKSEL_SDIO_Msk;
40 if(SystemCoreClock > 80000000) //SDIO时钟需要小于52MHz
41 SYS->CLKSEL |= (2 << SYS_CLKSEL_SDIO_Pos); //SDCLK = SYSCLK / 4
42 else
43 SYS->CLKSEL |= (0 << SYS_CLKSEL_SDIO_Pos); //SDCLK = SYSCLK / 2
44
45 SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_SDIO_Pos);
46
47 SDIO->CR2 = (1 << SDIO_CR2_RSTALL_Pos);
48
49 SDIO->CR1 = (1 << SDIO_CR1_CDSRC_Pos) |
50 (0 << SDIO_CR1_8BIT_Pos) |
51 (0 << SDIO_CR1_4BIT_Pos) |
52 (1 << SDIO_CR1_PWRON_Pos) |
53 (7 << SDIO_CR1_VOLT_Pos);
54
55 SDIO->CR2 = (1 << SDIO_CR2_CLKEN_Pos) |
56 (1 << SDIO_CR2_SDCLKEN_Pos) |
57 (calcSDCLKDiv(100000) << SDIO_CR2_SDCLKDIV_Pos) |
58 (0xC << SDIO_CR2_TIMEOUT_Pos); // 2**25 SDIO_CLK
59
60 while((SDIO->CR2 & SDIO_CR2_CLKRDY_Msk) == 0);
61
62 for(int i = 0; i < CyclesPerUs * 10; i++) __NOP();
63
64 SDIO->IM = 0xFFFFFFFF;
65
66
67 SDIO_SendCmd(SD_CMD_GO_IDLE_STATE, 0x00, SD_RESP_NO, 0); //CMD0: GO_IDLE_STATE
68
69 res = SDIO_SendCmd(SD_CMD_SEND_IF_COND, 0x1AA, SD_RESP_32b, &resp); //CMD8: SEND_IF_COND, 检测工作电压、检测是否支持SD 2.0
70 if(res != SD_RES_OK)
71 return res;
72
73 if(resp == 0x1AA) SD_cardInfo.CardType = SDIO_STD_CAPACITY_SD_CARD_V2_0;
74 else SD_cardInfo.CardType = SDIO_STD_CAPACITY_SD_CARD_V1_1;
75
76 do //ACMD41: SD_CMD_SD_APP_OP_COND
77 {
78 res = SDIO_SendCmd(SD_CMD_APP_CMD, 0x00, SD_RESP_32b, &resp);
79 if(res != SD_RES_OK)
80 return res;
81
82 if((resp & SD_CS_APP_CMD) == 0) return SD_RES_ERR;
83
84 if(SD_cardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0)
85 SDIO_SendCmd(SD_CMD_SD_APP_OP_COND, 0x80100000|0x40000000, SD_RESP_32b, &resp);
86 else
87 SDIO_SendCmd(SD_CMD_SD_APP_OP_COND, 0x80100000|0x00000000, SD_RESP_32b, &resp);
88 } while(((resp >> 31) & 0x01) == 0); //上电没完成时resp[31] == 0
89
90 if(((resp >> 30) & 0x01) == 1) SD_cardInfo.CardType = SDIO_HIGH_CAPACITY_SD_CARD;
91
92
93 SDIO_SendCmd(SD_CMD_ALL_SEND_CID, 0x00, SD_RESP_128b, resps); //CMD2: SD_CMD_ALL_SEND_CID,获取CID
94
95 parseCID(resps);
96
97
98 SDIO_SendCmd(SD_CMD_SET_REL_ADDR, 0x00, SD_RESP_32b, &resp); //CMD3: SD_CMD_SET_REL_ADDR,设置RCA
99
100 SD_cardInfo.RCA = resp >> 16;
101
102
103 SDIO_SendCmd(SD_CMD_SEND_CSD, SD_cardInfo.RCA << 16, SD_RESP_128b, resps); //CMD9: SD_CMD_SEND_CSD,获取CSD
104
105 parseCSD(resps);
106
107 if(SD_cardInfo.CardBlockSize < 0x200) return SD_RES_ERR; //本驱动只支持以512字节为单位的读写,所以最大读写单位必须不小于512
108
109
110 SDIO->CR2 &= ~(SDIO_CR2_SDCLKEN_Msk | SDIO_CR2_SDCLKDIV_Msk);
111 SDIO->CR2 |= (1 << SDIO_CR2_SDCLKEN_Pos) |
112 (calcSDCLKDiv(freq) << SDIO_CR2_SDCLKDIV_Pos); //初始化完成,SDCLK切换到高速
113
114
115 SDIO_SendCmd(SD_CMD_SEL_DESEL_CARD, SD_cardInfo.RCA << 16, SD_RESP_32b_busy, &resp); //CMD7: 选中卡,从Standy模式进入Transfer模式
116 SDIO->IF = SDIO_IF_TRXDONE_Msk;
117
118 SDIO_SendCmd(SD_CMD_APP_CMD, SD_cardInfo.RCA << 16, SD_RESP_32b, &resp);
119
120 SDIO_SendCmd(SD_CMD_APP_SD_SET_BUSWIDTH, SD_BUSWIDTH_4b, SD_RESP_32b, &resp); //切换成4位总线模式
121
122 SDIO->CR1 |= (1 << SDIO_CR1_4BIT_Pos);
123
124
125 SDIO_SendCmd(SD_CMD_SET_BLOCKLEN, 512, SD_RESP_32b, &resp); //固定块大小位512字节
126
127 SD_cardInfo.CardBlockSize = 512;
128
129 SDIO->BLK = 512;
130
131 return SD_RES_OK;
132 }
133
134 /******************************************************************************************************************************************
135 * 函数名称: SDIO_BlockWrite()
136 * 功能说明: 向SD卡写入数据
137 * 输 入: uint32_t block_addr SD卡块地址,每块512字节
138 * uint32_t buff[] 要写入的数据
139 * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
140 * 注意事项: 无
141 ******************************************************************************************************************************************/
SDIO_BlockWrite(uint32_t block_addr,uint32_t buff[])142 uint32_t SDIO_BlockWrite(uint32_t block_addr, uint32_t buff[])
143 {
144 uint32_t res, i;
145 uint32_t addr, resp;
146
147 if(SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) addr = block_addr;
148 else addr = block_addr * 512;
149
150 res = SDIO_SendCmdWithData(SD_CMD_WRITE_SINGLE_BLOCK, addr, SD_RESP_32b, &resp, 0, 1);
151 if(res != SD_RES_OK)
152 return res;
153
154 while((SDIO->IF & SDIO_IF_BUFWRRDY_Msk) == 0) __NOP();
155 SDIO->IF = SDIO_IF_BUFWRRDY_Msk;
156
157 for(i = 0; i < 512/4; i++) SDIO->DATA = buff[i];
158
159 while((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) __NOP();
160 SDIO->IF = SDIO_IF_TRXDONE_Msk;
161
162 return SD_RES_OK;
163 }
164
165 /******************************************************************************************************************************************
166 * 函数名称: SDIO_MultiBlockWrite()
167 * 功能说明: 向SD卡写入多块数据
168 * 输 入: uint32_t block_addr SD卡块地址,每块512字节
169 * uint16_t block_cnt 要写入的块数
170 * uint32_t buff[] 要写入的数据
171 * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
172 * 注意事项: 无
173 ******************************************************************************************************************************************/
SDIO_MultiBlockWrite(uint32_t block_addr,uint16_t block_cnt,uint32_t buff[])174 uint32_t SDIO_MultiBlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[])
175 {
176 uint32_t res, i, j;
177 uint32_t addr, resp;
178
179 if(SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) addr = block_addr;
180 else addr = block_addr * 512;
181
182 res = SDIO_SendCmdWithData(SD_CMD_WRITE_MULT_BLOCK, addr, SD_RESP_32b, &resp, 0, block_cnt);
183 if(res != SD_RES_OK)
184 return res;
185
186 for(i = 0; i < block_cnt; i++)
187 {
188 while((SDIO->IF & SDIO_IF_BUFWRRDY_Msk) == 0) __NOP();
189 SDIO->IF = SDIO_IF_BUFWRRDY_Msk;
190
191 for(j = 0; j < 512/4; j++) SDIO->DATA = buff[i*(512/4) + j];
192 }
193
194 while((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) __NOP();
195 SDIO->IF = SDIO_IF_TRXDONE_Msk;
196
197 return SD_RES_OK;
198 }
199
200 /******************************************************************************************************************************************
201 * 函数名称: SDIO_DMABlockWrite()
202 * 功能说明: 通过DMA向SD卡写入多块数据
203 * 输 入: uint32_t block_addr SD卡块地址,每块512字节
204 * uint16_t block_cnt 要写入的块数
205 * uint32_t buff[] 要写入的数据
206 * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
207 * 注意事项: 无
208 ******************************************************************************************************************************************/
SDIO_DMABlockWrite(uint32_t block_addr,uint16_t block_cnt,uint32_t buff[])209 uint32_t SDIO_DMABlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[])
210 {
211 uint32_t res;
212 uint32_t addr, resp;
213
214 if(SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) addr = block_addr;
215 else addr = block_addr * 512;
216
217 SDIO->DMA_MEM_ADDR = (uint32_t) buff;
218
219 res = SDIO_SendCmdWithDataByDMA(SD_CMD_WRITE_MULT_BLOCK, addr, SD_RESP_32b, &resp, 0, block_cnt);
220 if(res != SD_RES_OK)
221 return res;
222
223 while((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) __NOP();
224 SDIO->IF = SDIO_IF_TRXDONE_Msk;
225
226 return SD_RES_OK;
227 }
228
229 /******************************************************************************************************************************************
230 * 函数名称: SDIO_BlockRead()
231 * 功能说明: 从SD卡读出数据
232 * 输 入: uint32_t block_addr SD卡块地址,每块512字节
233 * uint32_t buff[] 读出的数据
234 * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
235 * 注意事项: 无
236 ******************************************************************************************************************************************/
SDIO_BlockRead(uint32_t block_addr,uint32_t buff[])237 uint32_t SDIO_BlockRead(uint32_t block_addr, uint32_t buff[])
238 {
239 uint32_t res, i;
240 uint32_t addr, resp;
241
242 if(SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) addr = block_addr;
243 else addr = block_addr * 512;
244
245 res = SDIO_SendCmdWithData(SD_CMD_READ_SINGLE_BLOCK, addr, SD_RESP_32b, &resp, 1, 1);
246 if(res != SD_RES_OK)
247 return res;
248
249 while((SDIO->IF & SDIO_IF_BUFRDRDY_Msk) == 0) __NOP();
250 SDIO->IF = SDIO_IF_BUFRDRDY_Msk;
251
252 for(i = 0; i < 512/4; i++) buff[i] = SDIO->DATA;
253
254 while((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) __NOP();
255 SDIO->IF = SDIO_IF_TRXDONE_Msk;
256
257 return SD_RES_OK;
258 }
259
260 /******************************************************************************************************************************************
261 * 函数名称: SDIO_MultiBlockRead()
262 * 功能说明: 从SD卡读出多块数据
263 * 输 入: uint32_t block_addr SD卡块地址,每块512字节
264 * uint16_t block_cnt 要读出的块数
265 * uint32_t buff[] 读出的数据
266 * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
267 * 注意事项: 无
268 ******************************************************************************************************************************************/
SDIO_MultiBlockRead(uint32_t block_addr,uint16_t block_cnt,uint32_t buff[])269 uint32_t SDIO_MultiBlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[])
270 {
271 uint32_t res, i, j;
272 uint32_t addr, resp;
273
274 if(SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) addr = block_addr;
275 else addr = block_addr * 512;
276
277 res = SDIO_SendCmdWithData(SD_CMD_READ_MULT_BLOCK, addr, SD_RESP_32b, &resp, 1, block_cnt);
278 if(res != SD_RES_OK)
279 return res;
280
281 for(i = 0; i < block_cnt; i++)
282 {
283 while((SDIO->IF & SDIO_IF_BUFRDRDY_Msk) == 0) __NOP();
284 SDIO->IF = SDIO_IF_BUFRDRDY_Msk;
285
286 for(j = 0; j < 512/4; j++) buff[i*(512/4) + j] = SDIO->DATA;
287 }
288
289 while((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) __NOP();
290 SDIO->IF = SDIO_IF_TRXDONE_Msk;
291
292 return SD_RES_OK;
293 }
294
295 /******************************************************************************************************************************************
296 * 函数名称: SDIO_DMABlockRead()
297 * 功能说明: 通过DMA从SD卡读出多块数据
298 * 输 入: uint32_t block_addr SD卡块地址,每块512字节
299 * uint16_t block_cnt 要读出的块数
300 * uint32_t buff[] 读出的数据
301 * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
302 * 注意事项: 无
303 ******************************************************************************************************************************************/
SDIO_DMABlockRead(uint32_t block_addr,uint16_t block_cnt,uint32_t buff[])304 uint32_t SDIO_DMABlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[])
305 {
306 uint32_t res;
307 uint32_t addr, resp;
308
309 if(SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) addr = block_addr;
310 else addr = block_addr * 512;
311
312 SDIO->DMA_MEM_ADDR = (uint32_t)buff;
313
314 res = SDIO_SendCmdWithDataByDMA(SD_CMD_READ_MULT_BLOCK, addr, SD_RESP_32b, &resp, 1, block_cnt);
315 if(res != SD_RES_OK)
316 return res;
317
318 while((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) __NOP();
319 SDIO->IF = SDIO_IF_TRXDONE_Msk;
320
321 return SD_RES_OK;
322 }
323
324 /******************************************************************************************************************************************
325 * 函数名称: _SDIO_SendCmd()
326 * 功能说明: SDIO向SD卡发送命令
327 * 输 入: uint32_t cmd 命令索引
328 * uint32_t arg 命令参数
329 * uint32_t resp_type 响应类型,取值SD_RESP_NO、SD_RESP_32b、SD_RESP_128b、SD_RESP_32b_busy
330 * uint32_t *resp_data 响应内容
331 * uint32_t have_data 是否有数据传输
332 * uint32_t data_read 1 读SD卡 0 写SD卡
333 * uint16_t block_cnt 读写块个数
334 * uint32_t use_dma 1 使用DMA搬运数据
335 * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
336 * 注意事项: 无
337 ******************************************************************************************************************************************/
_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)338 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)
339 {
340 SDIO->BLK &= ~SDIO_BLK_COUNT_Msk;
341 SDIO->BLK |= (block_cnt << SDIO_BLK_COUNT_Pos);
342
343 SDIO->ARG = arg;
344 SDIO->CMD = (cmd << SDIO_CMD_CMDINDX_Pos) |
345 (0 << SDIO_CMD_CMDTYPE_Pos) |
346 (0 << SDIO_CMD_IDXCHECK_Pos) |
347 (0 << SDIO_CMD_CRCCHECK_Pos) |
348 (resp_type << SDIO_CMD_RESPTYPE_Pos) |
349 (have_data << SDIO_CMD_HAVEDATA_Pos) |
350 (data_read << SDIO_CMD_DIRREAD_Pos) |
351 ((block_cnt > 1) << SDIO_CMD_MULTBLK_Pos) |
352 ((block_cnt > 1) << SDIO_CMD_BLKCNTEN_Pos) |
353 (((cmd == 53) ? 0 : (block_cnt > 1)) << SDIO_CMD_AUTOCMD12_Pos) |
354 (use_dma << SDIO_CMD_DMAEN_Pos);
355
356 while((SDIO->IF & SDIO_IF_CMDDONE_Msk) == 0)
357 {
358 if(SDIO->IF & SDIO_IF_CMDTIMEOUT_Msk)
359 {
360 SDIO->IF = SDIO_IF_CMDTIMEOUT_Msk;
361
362 return SD_RES_TIMEOUT;
363 }
364 else if(SDIO->IF & SDIO_IF_ERROR_Msk)
365 {
366 SDIO->IF = 0xFFFFFFFF;
367
368 return SD_RES_ERR;
369 }
370 }
371 SDIO->IF = SDIO_IF_CMDDONE_Msk;
372
373 if(resp_type == SD_RESP_32b)
374 {
375 resp_data[0] = SDIO->RESP[0];
376 }
377 else if(resp_type == SD_RESP_128b)
378 {
379 //寄存器中将CID/CSD[127-8]依次存放在了RESP3-0[119-0],最低位的CRC被丢掉
380 //读出数据时调整了顺序,将CID/CSD[127-8]存放在resp_data0-3[127-8],最低8位填充0x00
381 resp_data[0] = (SDIO->RESP[3] << 8) + ((SDIO->RESP[2] >> 24) & 0xFF);
382 resp_data[1] = (SDIO->RESP[2] << 8) + ((SDIO->RESP[1] >> 24) & 0xFF);
383 resp_data[2] = (SDIO->RESP[1] << 8) + ((SDIO->RESP[0] >> 24) & 0xFF);
384 resp_data[3] = (SDIO->RESP[0] << 8) + 0x00;
385 }
386
387 return SD_RES_OK;
388 }
389
390
parseCID(uint32_t CID_Tab[4])391 void parseCID(uint32_t CID_Tab[4])
392 {
393 uint8_t tmp = 0;
394
395 /*!< Byte 0 */
396 tmp = (uint8_t)((CID_Tab[0] & 0xFF000000) >> 24);
397 SD_cardInfo.SD_cid.ManufacturerID = tmp;
398
399 /*!< Byte 1 */
400 tmp = (uint8_t)((CID_Tab[0] & 0x00FF0000) >> 16);
401 SD_cardInfo.SD_cid.OEM_AppliID = tmp << 8;
402
403 /*!< Byte 2 */
404 tmp = (uint8_t)((CID_Tab[0] & 0x000000FF00) >> 8);
405 SD_cardInfo.SD_cid.OEM_AppliID |= tmp;
406
407 /*!< Byte 3 */
408 tmp = (uint8_t)(CID_Tab[0] & 0x000000FF);
409 SD_cardInfo.SD_cid.ProdName1 = tmp << 24;
410
411 /*!< Byte 4 */
412 tmp = (uint8_t)((CID_Tab[1] & 0xFF000000) >> 24);
413 SD_cardInfo.SD_cid.ProdName1 |= tmp << 16;
414
415 /*!< Byte 5 */
416 tmp = (uint8_t)((CID_Tab[1] & 0x00FF0000) >> 16);
417 SD_cardInfo.SD_cid.ProdName1 |= tmp << 8;
418
419 /*!< Byte 6 */
420 tmp = (uint8_t)((CID_Tab[1] & 0x0000FF00) >> 8);
421 SD_cardInfo.SD_cid.ProdName1 |= tmp;
422
423 /*!< Byte 7 */
424 tmp = (uint8_t)(CID_Tab[1] & 0x000000FF);
425 SD_cardInfo.SD_cid.ProdName2 = tmp;
426
427 /*!< Byte 8 */
428 tmp = (uint8_t)((CID_Tab[2] & 0xFF000000) >> 24);
429 SD_cardInfo.SD_cid.ProdRev = tmp;
430
431 /*!< Byte 9 */
432 tmp = (uint8_t)((CID_Tab[2] & 0x00FF0000) >> 16);
433 SD_cardInfo.SD_cid.ProdSN = tmp << 24;
434
435 /*!< Byte 10 */
436 tmp = (uint8_t)((CID_Tab[2] & 0x0000FF00) >> 8);
437 SD_cardInfo.SD_cid.ProdSN |= tmp << 16;
438
439 /*!< Byte 11 */
440 tmp = (uint8_t)(CID_Tab[2] & 0x000000FF);
441 SD_cardInfo.SD_cid.ProdSN |= tmp << 8;
442
443 /*!< Byte 12 */
444 tmp = (uint8_t)((CID_Tab[3] & 0xFF000000) >> 24);
445 SD_cardInfo.SD_cid.ProdSN |= tmp;
446
447 /*!< Byte 13 */
448 tmp = (uint8_t)((CID_Tab[3] & 0x00FF0000) >> 16);
449 SD_cardInfo.SD_cid.Reserved1 |= (tmp & 0xF0) >> 4;
450 SD_cardInfo.SD_cid.ManufactDate = (tmp & 0x0F) << 8;
451
452 /*!< Byte 14 */
453 tmp = (uint8_t)((CID_Tab[3] & 0x0000FF00) >> 8);
454 SD_cardInfo.SD_cid.ManufactDate |= tmp;
455 }
456
parseCSD(uint32_t CSD_Tab[4])457 void parseCSD(uint32_t CSD_Tab[4])
458 {
459 uint8_t tmp = 0;
460
461 /*!< Byte 0 */
462 tmp = (uint8_t)((CSD_Tab[0] & 0xFF000000) >> 24);
463 SD_cardInfo.SD_csd.CSDStruct = (tmp & 0xC0) >> 6;
464 SD_cardInfo.SD_csd.SysSpecVersion = (tmp & 0x3C) >> 2;
465 SD_cardInfo.SD_csd.Reserved1 = tmp & 0x03;
466
467 /*!< Byte 1 */
468 tmp = (uint8_t)((CSD_Tab[0] & 0x00FF0000) >> 16);
469 SD_cardInfo.SD_csd.TAAC = tmp;
470
471 /*!< Byte 2 */
472 tmp = (uint8_t)((CSD_Tab[0] & 0x0000FF00) >> 8);
473 SD_cardInfo.SD_csd.NSAC = tmp;
474
475 /*!< Byte 3 */
476 tmp = (uint8_t)(CSD_Tab[0] & 0x000000FF);
477 SD_cardInfo.SD_csd.MaxBusClkFrec = tmp;
478
479 /*!< Byte 4 */
480 tmp = (uint8_t)((CSD_Tab[1] & 0xFF000000) >> 24);
481 SD_cardInfo.SD_csd.CardComdClasses = tmp << 4;
482
483 /*!< Byte 5 */
484 tmp = (uint8_t)((CSD_Tab[1] & 0x00FF0000) >> 16);
485 SD_cardInfo.SD_csd.CardComdClasses |= (tmp & 0xF0) >> 4;
486 SD_cardInfo.SD_csd.RdBlockLen = tmp & 0x0F;
487
488 /*!< Byte 6 */
489 tmp = (uint8_t)((CSD_Tab[1] & 0x0000FF00) >> 8);
490 SD_cardInfo.SD_csd.PartBlockRead = (tmp & 0x80) >> 7;
491 SD_cardInfo.SD_csd.WrBlockMisalign = (tmp & 0x40) >> 6;
492 SD_cardInfo.SD_csd.RdBlockMisalign = (tmp & 0x20) >> 5;
493 SD_cardInfo.SD_csd.DSRImpl = (tmp & 0x10) >> 4;
494 SD_cardInfo.SD_csd.Reserved2 = 0; /*!< Reserved */
495
496 if ((SD_cardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V1_1) ||
497 (SD_cardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0))
498 {
499 SD_cardInfo.SD_csd.DeviceSize = (tmp & 0x03) << 10;
500
501 /*!< Byte 7 */
502 tmp = (uint8_t)(CSD_Tab[1] & 0x000000FF);
503 SD_cardInfo.SD_csd.DeviceSize |= (tmp) << 2;
504
505 /*!< Byte 8 */
506 tmp = (uint8_t)((CSD_Tab[2] & 0xFF000000) >> 24);
507 SD_cardInfo.SD_csd.DeviceSize |= (tmp & 0xC0) >> 6;
508
509 SD_cardInfo.SD_csd.MaxRdCurrentVDDMin = (tmp & 0x38) >> 3;
510 SD_cardInfo.SD_csd.MaxRdCurrentVDDMax = (tmp & 0x07);
511
512 /*!< Byte 9 */
513 tmp = (uint8_t)((CSD_Tab[2] & 0x00FF0000) >> 16);
514 SD_cardInfo.SD_csd.MaxWrCurrentVDDMin = (tmp & 0xE0) >> 5;
515 SD_cardInfo.SD_csd.MaxWrCurrentVDDMax = (tmp & 0x1C) >> 2;
516 SD_cardInfo.SD_csd.DeviceSizeMul = (tmp & 0x03) << 1;
517 /*!< Byte 10 */
518 tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8);
519 SD_cardInfo.SD_csd.DeviceSizeMul |= (tmp & 0x80) >> 7;
520
521 SD_cardInfo.CardCapacity = (SD_cardInfo.SD_csd.DeviceSize + 1) ;
522 SD_cardInfo.CardCapacity *= (1 << (SD_cardInfo.SD_csd.DeviceSizeMul + 2));
523 SD_cardInfo.CardBlockSize = 1 << (SD_cardInfo.SD_csd.RdBlockLen);
524 SD_cardInfo.CardCapacity *= SD_cardInfo.CardBlockSize;
525 }
526 else if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD)
527 {
528 /*!< Byte 7 */
529 tmp = (uint8_t)(CSD_Tab[1] & 0x000000FF);
530 SD_cardInfo.SD_csd.DeviceSize = (tmp & 0x3F) << 16;
531
532 /*!< Byte 8 */
533 tmp = (uint8_t)((CSD_Tab[2] & 0xFF000000) >> 24);
534
535 SD_cardInfo.SD_csd.DeviceSize |= (tmp << 8);
536
537 /*!< Byte 9 */
538 tmp = (uint8_t)((CSD_Tab[2] & 0x00FF0000) >> 16);
539
540 SD_cardInfo.SD_csd.DeviceSize |= (tmp);
541
542 /*!< Byte 10 */
543 tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8);
544
545 SD_cardInfo.CardCapacity = (uint64_t)(SD_cardInfo.SD_csd.DeviceSize + 1) * 512 * 1024;
546 SD_cardInfo.CardBlockSize = 512;
547 }
548
549 SD_cardInfo.SD_csd.EraseGrSize = (tmp & 0x40) >> 6;
550 SD_cardInfo.SD_csd.EraseGrMul = (tmp & 0x3F) << 1;
551
552 /*!< Byte 11 */
553 tmp = (uint8_t)(CSD_Tab[2] & 0x000000FF);
554 SD_cardInfo.SD_csd.EraseGrMul |= (tmp & 0x80) >> 7;
555 SD_cardInfo.SD_csd.WrProtectGrSize = (tmp & 0x7F);
556
557 /*!< Byte 12 */
558 tmp = (uint8_t)((CSD_Tab[3] & 0xFF000000) >> 24);
559 SD_cardInfo.SD_csd.WrProtectGrEnable = (tmp & 0x80) >> 7;
560 SD_cardInfo.SD_csd.ManDeflECC = (tmp & 0x60) >> 5;
561 SD_cardInfo.SD_csd.WrSpeedFact = (tmp & 0x1C) >> 2;
562 SD_cardInfo.SD_csd.MaxWrBlockLen = (tmp & 0x03) << 2;
563
564 /*!< Byte 13 */
565 tmp = (uint8_t)((CSD_Tab[3] & 0x00FF0000) >> 16);
566 SD_cardInfo.SD_csd.MaxWrBlockLen |= (tmp & 0xC0) >> 6;
567 SD_cardInfo.SD_csd.WriteBlockPaPartial = (tmp & 0x20) >> 5;
568 SD_cardInfo.SD_csd.Reserved3 = 0;
569 SD_cardInfo.SD_csd.ContentProtectAppli = (tmp & 0x01);
570
571 /*!< Byte 14 */
572 tmp = (uint8_t)((CSD_Tab[3] & 0x0000FF00) >> 8);
573 SD_cardInfo.SD_csd.FileFormatGrouop = (tmp & 0x80) >> 7;
574 SD_cardInfo.SD_csd.CopyFlag = (tmp & 0x40) >> 6;
575 SD_cardInfo.SD_csd.PermWrProtect = (tmp & 0x20) >> 5;
576 SD_cardInfo.SD_csd.TempWrProtect = (tmp & 0x10) >> 4;
577 SD_cardInfo.SD_csd.FileFormat = (tmp & 0x0C) >> 2;
578 SD_cardInfo.SD_csd.ECC = (tmp & 0x03);
579 }
580
calcSDCLKDiv(uint32_t freq)581 uint32_t calcSDCLKDiv(uint32_t freq)
582 {
583 uint32_t prediv;
584 switch((SYS->CLKSEL & SYS_CLKSEL_SDIO_Msk) >> SYS_CLKSEL_SDIO_Pos)
585 {
586 case 0: prediv = 1; break;
587 case 1: prediv = 3; break;
588 case 2: prediv = 2; break;
589 case 3: prediv = 0; break;
590 }
591
592 uint32_t clkdiv = (SystemCoreClock / (1 << prediv)) / freq;
593 uint32_t regdiv = 0;
594
595 if(clkdiv > 128) regdiv = 0x80;
596 else if(clkdiv > 64) regdiv = 0x40;
597 else if(clkdiv > 32) regdiv = 0x20;
598 else if(clkdiv > 16) regdiv = 0x10;
599 else if(clkdiv > 8) regdiv = 0x08;
600 else if(clkdiv > 4) regdiv = 0x04;
601 else if(clkdiv > 2) regdiv = 0x02;
602 else if(clkdiv > 1) regdiv = 0x01;
603 else regdiv = 0x00;
604
605 return regdiv;
606 }
607
608
609 /******************************************************************************************************************************************
610 * 函数名称: SDIO_IO_Init()
611 * 功能说明: SDIO读写IO卡初始化
612 * 输 入: uint32_t freq SDIO_CLK时钟频率
613 * enum SDIO_bus_width w SDIO_1bit 1-bit bus SDIO_4bit 4-bit bus
614 * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
615 * 注意事项: 无
616 ******************************************************************************************************************************************/
SDIO_IO_Init(uint32_t freq,enum SDIO_bus_width w)617 uint32_t SDIO_IO_Init(uint32_t freq, enum SDIO_bus_width w)
618 {
619 uint32_t res;
620 uint32_t resp, resps[4];
621
622 SYS->CLKSEL &= ~SYS_CLKSEL_SDIO_Msk;
623 if(SystemCoreClock > 80000000) //SDIO时钟需要小于52MHz
624 SYS->CLKSEL |= (2 << SYS_CLKSEL_SDIO_Pos); //SDCLK = SYSCLK / 4
625 else
626 SYS->CLKSEL |= (0 << SYS_CLKSEL_SDIO_Pos); //SDCLK = SYSCLK / 2
627
628 SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_SDIO_Pos);
629
630 // SDIO->CR2 = (1 << SDIO_CR2_RSTALL_Pos);
631 for(int i = 0; i < CyclesPerUs; i++) __NOP();
632
633 SDIO->CR1 = (1 << SDIO_CR1_CDSRC_Pos) |
634 (0 << SDIO_CR1_8BIT_Pos) |
635 (w << SDIO_CR1_4BIT_Pos) |
636 (1 << SDIO_CR1_PWRON_Pos) |
637 (7 << SDIO_CR1_VOLT_Pos);
638
639 SDIO->CR2 = (1 << SDIO_CR2_CLKEN_Pos) |
640 (1 << SDIO_CR2_SDCLKEN_Pos) |
641 (calcSDCLKDiv(freq) << SDIO_CR2_SDCLKDIV_Pos) |
642 (0xC << SDIO_CR2_TIMEOUT_Pos); // 2**25 SDIO_CLK
643
644 while((SDIO->CR2 & SDIO_CR2_CLKRDY_Msk) == 0);
645
646 for(int i = 0; i < CyclesPerUs * 10; i++) __NOP();
647
648 SDIO->IM = 0xFFFFFFFF;
649
650 return SD_RES_OK;
651 }
652
653
654 /******************************************************************************************************************************************
655 * 函数名称: SDIO_IO_ByteWrite()
656 * 功能说明: 向IO卡写入单个字节
657 * 输 入: uint8_t func The number of the function within the I/O card you wish to read or write
658 * uint32_t addr Start Address of I/O register to read or write. Range is 0--0x1FFFF
659 * uint32_t buff[] 要写出的数据
660 * uint16_t block_size 要写出的字节个数,取值 1--512
661 * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
662 * 注意事项: 无
663 ******************************************************************************************************************************************/
SDIO_IO_ByteWrite(uint8_t func,uint32_t addr,uint8_t data)664 uint32_t SDIO_IO_ByteWrite(uint8_t func, uint32_t addr, uint8_t data)
665 {
666 uint32_t res;
667 uint32_t arg, resp;
668
669 arg = (1u << SD_CMD53_ARG_nRW) |
670 (func << SD_CMD53_ARG_Function) |
671 (addr << SD_CMD53_ARG_Addr) | data;
672
673 res = SDIO_SendCmd(52, arg, SD_RESP_32b, &resp);
674 if(res != SD_RES_OK)
675 return res;
676
677 return SD_RES_OK;
678 }
679
680
681 /******************************************************************************************************************************************
682 * 函数名称: SDIO_IO_ByteRead()
683 * 功能说明: 从IO卡读出单个字节
684 * 输 入: uint8_t func The number of the function within the I/O card you wish to read or write
685 * uint32_t addr Start Address of I/O register to read or write. Range is 0--0x1FFFF
686 * uint32_t buff[] 读取到的数据存入此数组
687 * uint16_t block_size 要读取的字节个数,取值 1--512
688 * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
689 * 注意事项: 无
690 ******************************************************************************************************************************************/
SDIO_IO_ByteRead(uint8_t func,uint32_t addr,uint8_t * data)691 uint32_t SDIO_IO_ByteRead(uint8_t func, uint32_t addr, uint8_t * data)
692 {
693 uint32_t res;
694 uint32_t arg, resp;
695
696 arg = (0u << SD_CMD53_ARG_nRW) |
697 (func << SD_CMD53_ARG_Function) |
698 (addr << SD_CMD53_ARG_Addr) | 0x00;
699
700 res = SDIO_SendCmd(52, arg, SD_RESP_32b, &resp);
701 if(res != SD_RES_OK)
702 return res;
703
704 *data = resp & 0xFF;
705
706 return SD_RES_OK;
707 }
708
709
710 /******************************************************************************************************************************************
711 * 函数名称: SDIO_IO_BlockWrite()
712 * 功能说明: 向IO卡写入单个块数据
713 * 输 入: uint8_t func The number of the function within the I/O card you wish to read or write
714 * uint32_t addr Start Address of I/O register to read or write. Range is 0--0x1FFFF
715 * uint8_t addrInc 0 Multi byte R/W to fixed address 1 Multi byte R/W to incrementing address
716 * uint32_t buff[] 要写出的数据
717 * uint16_t block_size 要写出的字节个数,取值 1--512
718 * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
719 * 注意事项: 无
720 ******************************************************************************************************************************************/
SDIO_IO_BlockWrite(uint8_t func,uint32_t addr,uint8_t addrInc,uint32_t buff[],uint16_t block_size)721 uint32_t SDIO_IO_BlockWrite(uint8_t func, uint32_t addr, uint8_t addrInc, uint32_t buff[], uint16_t block_size)
722 {
723 uint32_t res, i;
724 uint32_t arg, resp;
725
726 SDIO->BLK = block_size;
727
728 arg = (1u << SD_CMD53_ARG_nRW) |
729 (func << SD_CMD53_ARG_Function) |
730 (addr << SD_CMD53_ARG_Addr) |
731 (addrInc << SD_CMD53_ARG_AddrInc) |
732 ((block_size % 512) << SD_CMD53_ARG_Count) |
733 (0 << SD_CMD53_ARG_CountUnit);
734
735 res = SDIO_SendCmdWithData(53, arg, SD_RESP_32b, &resp, 0, 1);
736 if(res != SD_RES_OK)
737 return res;
738
739 while((SDIO->IF & SDIO_IF_BUFWRRDY_Msk) == 0) __NOP();
740 SDIO->IF = SDIO_IF_BUFWRRDY_Msk;
741
742 for(i = 0; i < block_size/4; i++) SDIO->DATA = buff[i];
743
744 while((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) __NOP();
745 SDIO->IF = SDIO_IF_TRXDONE_Msk;
746
747 return SD_RES_OK;
748 }
749
750
751 /******************************************************************************************************************************************
752 * 函数名称: SDIO_IO_BlockRead()
753 * 功能说明: 从IO卡读出单个块数据
754 * 输 入: uint8_t func The number of the function within the I/O card you wish to read or write
755 * uint32_t addr Start Address of I/O register to read or write. Range is 0--0x1FFFF
756 * uint8_t addrInc 0 Multi byte R/W to fixed address 1 Multi byte R/W to incrementing address
757 * uint32_t buff[] 读取到的数据存入此数组
758 * uint16_t block_size 要读取的字节个数,取值 1--512
759 * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
760 * 注意事项: 无
761 ******************************************************************************************************************************************/
SDIO_IO_BlockRead(uint8_t func,uint32_t addr,uint8_t addrInc,uint32_t buff[],uint16_t block_size)762 uint32_t SDIO_IO_BlockRead(uint8_t func, uint32_t addr, uint8_t addrInc, uint32_t buff[], uint16_t block_size)
763 {
764 uint32_t res, i;
765 uint32_t arg, resp;
766
767 SDIO->BLK = block_size;
768
769 arg = (0u << SD_CMD53_ARG_nRW) |
770 (func << SD_CMD53_ARG_Function) |
771 (addr << SD_CMD53_ARG_Addr) |
772 (addrInc << SD_CMD53_ARG_AddrInc) |
773 ((block_size % 512) << SD_CMD53_ARG_Count) |
774 (0 << SD_CMD53_ARG_CountUnit);
775
776 res = SDIO_SendCmdWithData(53, arg, SD_RESP_32b, &resp, 1, 1);
777 if(res != SD_RES_OK)
778 return res;
779
780 while((SDIO->IF & SDIO_IF_BUFRDRDY_Msk) == 0) __NOP();
781 SDIO->IF = SDIO_IF_BUFRDRDY_Msk;
782
783 for(i = 0; i < block_size/4; i++) buff[i] = SDIO->DATA;
784
785 while((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) __NOP();
786 SDIO->IF = SDIO_IF_TRXDONE_Msk;
787
788 return SD_RES_OK;
789 }
790
791
792 /******************************************************************************************************************************************
793 * 函数名称: SDIO_IO_MultiBlockWrite()
794 * 功能说明: 向IO卡写入多个块数据
795 * 输 入: uint8_t func The number of the function within the I/O card you wish to read or write
796 * uint32_t addr Start Address of I/O register to read or write. Range is 0--0x1FFFF
797 * uint8_t addrInc 0 Multi byte R/W to fixed address 1 Multi byte R/W to incrementing address
798 * uint32_t buff[] 要写出的数据
799 * uint16_t block_count 要写出的块个数,块大小为 512 字节
800 * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
801 * 注意事项: 无
802 ******************************************************************************************************************************************/
SDIO_IO_MultiBlockWrite(uint8_t func,uint32_t addr,uint8_t addrInc,uint32_t buff[],uint16_t block_count)803 uint32_t SDIO_IO_MultiBlockWrite(uint8_t func, uint32_t addr, uint8_t addrInc, uint32_t buff[], uint16_t block_count)
804 {
805 uint32_t res, i, j;
806 uint32_t arg, resp;
807
808 SDIO->BLK = 512;
809
810 arg = (1u << SD_CMD53_ARG_nRW) |
811 (func << SD_CMD53_ARG_Function) |
812 (addr << SD_CMD53_ARG_Addr) |
813 (addrInc << SD_CMD53_ARG_AddrInc) |
814 (block_count << SD_CMD53_ARG_Count) |
815 (1 << SD_CMD53_ARG_CountUnit);
816
817 res = SDIO_SendCmdWithData(53, arg, SD_RESP_32b, &resp, 0, block_count);
818 if(res != SD_RES_OK)
819 return res;
820
821 for(i = 0; i < block_count; i++)
822 {
823 while((SDIO->IF & SDIO_IF_BUFWRRDY_Msk) == 0) __NOP();
824 SDIO->IF = SDIO_IF_BUFWRRDY_Msk;
825
826 for(j = 0; j < 512/4; j++) SDIO->DATA = buff[i*(512/4) + j];
827 }
828
829 while((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) __NOP();
830 SDIO->IF = SDIO_IF_TRXDONE_Msk;
831
832 return SD_RES_OK;
833 }
834
835
836 /******************************************************************************************************************************************
837 * 函数名称: SDIO_IO_MultiBlockRead()
838 * 功能说明: 从IO卡读出多个块数据
839 * 输 入: uint8_t func The number of the function within the I/O card you wish to read or write
840 * uint32_t addr Start Address of I/O register to read or write. Range is 0--0x1FFFF
841 * uint8_t addrInc 0 Multi byte R/W to fixed address 1 Multi byte R/W to incrementing address
842 * uint32_t buff[] 读取到的数据存入此数组
843 * uint16_t block_count 要读取的块个数,块大小为 512 字节
844 * 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时
845 * 注意事项: 无
846 ******************************************************************************************************************************************/
SDIO_IO_MultiBlockRead(uint8_t func,uint32_t addr,uint8_t addrInc,uint32_t buff[],uint16_t block_count)847 uint32_t SDIO_IO_MultiBlockRead(uint8_t func, uint32_t addr, uint8_t addrInc, uint32_t buff[], uint16_t block_count)
848 {
849 uint32_t res, i, j;
850 uint32_t arg, resp;
851
852 SDIO->BLK = 512;
853
854 arg = (0u << SD_CMD53_ARG_nRW) |
855 (func << SD_CMD53_ARG_Function) |
856 (addr << SD_CMD53_ARG_Addr) |
857 (addrInc << SD_CMD53_ARG_AddrInc) |
858 (block_count << SD_CMD53_ARG_Count) |
859 (1 << SD_CMD53_ARG_CountUnit);
860
861 res = SDIO_SendCmdWithData(53, arg, SD_RESP_32b, &resp, 1, block_count);
862 if(res != SD_RES_OK)
863 return res;
864
865 for(i = 0; i < block_count; i++)
866 {
867 while((SDIO->IF & SDIO_IF_BUFRDRDY_Msk) == 0) __NOP();
868 SDIO->IF = SDIO_IF_BUFRDRDY_Msk;
869
870 for(j = 0; j < 512/4; j++) buff[i*(512/4) + j] = SDIO->DATA;
871 }
872
873 while((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) __NOP();
874 SDIO->IF = SDIO_IF_TRXDONE_Msk;
875
876 return SD_RES_OK;
877 }
878