1 /**************************************************************************//**
2 * @file sdh.c
3 * @version V1.00
4 * @brief SDH driver source file
5 *
6 * @copyright SPDX-License-Identifier: Apache-2.0
7 * @copyright Copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include "NuMicro.h"
13
14 #if defined (__ICCARM__)
15 # pragma diag_suppress=Pm073, Pm143 /* Misra C 2004 rule 14.7 */
16 #endif
17
18
19 /** @addtogroup Standard_Driver Standard Driver
20 @{
21 */
22
23 /** @addtogroup SDH_Driver SDH Driver
24 @{
25 */
26
27 /** @addtogroup SDH_EXPORTED_FUNCTIONS SDH Exported Functions
28 @{
29 */
30
31 #define SDH_BLOCK_SIZE 512UL
32
33 /* #define DEBUG_PRINTF printf */
34 #define DEBUG_PRINTF(...)
35
36 /** @cond HIDDEN_SYMBOLS */
37
38 /* global variables */
39 /* For response R3 (such as ACMD41, CRC-7 is invalid; but SD controller will still */
40 /* calculate CRC-7 and get an error result, software should ignore this error and clear SDISR [CRC_IF] flag */
41 /* _sd_uR3_CMD is the flag for it. 1 means software should ignore CRC-7 error */
42 uint8_t g_u8R3Flag = 0UL;
43 uint8_t volatile g_u8SDDataReadyFlag = (uint8_t)FALSE;
44
45 static uint32_t _SDH_uR7_CMD = 0UL;
46 static uint32_t _SDH_ReferenceClock;
47
48 #if defined ( __ICCARM__ ) /*!< IAR Compiler */
49 #pragma data_alignment = 4
50 static uint8_t _SDH_ucSDHCBuffer[512];
51 #else
52 static __attribute__((aligned)) uint8_t _SDH_ucSDHCBuffer[512];
53 #endif
54
55 /* Declare these functions here to avoid MISRA C 2004 rule 8.1 error */
56 void SDH_CheckRB(SDH_T *sdh);
57 uint32_t SDH_SDCommand(SDH_T *sdh, uint32_t u32Cmd, uint32_t u32Arg);
58 uint32_t SDH_SDCmdAndRsp(SDH_T *sdh, uint32_t u32Cmd, uint32_t u32Arg, uint32_t u32TickCount);
59 uint32_t SDH_Swap32(uint32_t u32Val);
60 uint32_t SDH_SDCmdAndRsp2(SDH_T *sdh, uint32_t u32Cmd, uint32_t u32Arg, uint32_t pu32R2ptr[]);
61 uint32_t SDH_SDCmdAndRspDataIn(SDH_T *sdh, uint32_t u32Cmd, uint32_t u32Arg);
62 void SDH_Set_clock(SDH_T *sdh, uint32_t u32SDClockKhz);
63 uint32_t SDH_CardDetection(SDH_T *sdh);
64 uint32_t SDH_Init(SDH_T *sdh);
65 uint32_t SDH_SwitchToHighSpeed(SDH_T *sdh, SDH_INFO_T *pSD);
66 uint32_t SDH_SelectCardType(SDH_T *sdh);
67 void SDH_Get_SD_info(SDH_T *sdh);
68
69 SDH_INFO_T SD0;
70
SDH_CheckRB(SDH_T * sdh)71 void SDH_CheckRB(SDH_T *sdh)
72 {
73 while(1)
74 {
75 sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
76 while(sdh->CTL & SDH_CTL_CLK8OEN_Msk) {}
77 if(sdh->INTSTS & SDH_INTSTS_DAT0STS_Msk)
78 {
79 break;
80 }
81 }
82 }
83
84
SDH_SDCommand(SDH_T * sdh,uint32_t u32Cmd,uint32_t u32Arg)85 uint32_t SDH_SDCommand(SDH_T *sdh, uint32_t u32Cmd, uint32_t u32Arg)
86 {
87 SDH_INFO_T *pSD;
88 volatile uint32_t u32Status = Successful;
89
90 /* Only support SDH0 here*/
91 pSD = &SD0;
92
93 sdh->CMDARG = u32Arg;
94 sdh->CTL = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | (u32Cmd << 8) | (SDH_CTL_COEN_Msk);
95
96 while(sdh->CTL & SDH_CTL_COEN_Msk)
97 {
98 if(pSD->IsCardInsert == (uint32_t)FALSE)
99 {
100 u32Status = SDH_NO_SD_CARD;
101 }
102 }
103 return u32Status;
104 }
105
106
SDH_SDCmdAndRsp(SDH_T * sdh,uint32_t u32Cmd,uint32_t u32Arg,uint32_t u32TickCount)107 uint32_t SDH_SDCmdAndRsp(SDH_T *sdh, uint32_t u32Cmd, uint32_t u32Arg, uint32_t u32TickCount)
108 {
109 SDH_INFO_T *pSD;
110
111 /* Only support SDH0 here*/
112 pSD = &SD0;
113
114 sdh->CMDARG = u32Arg;
115 sdh->CTL = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | (u32Cmd << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk);
116
117 if(u32TickCount > 0UL)
118 {
119 while(sdh->CTL & SDH_CTL_RIEN_Msk)
120 {
121 if(u32TickCount-- == 0UL)
122 {
123 sdh->CTL |= SDH_CTL_CTLRST_Msk; /* reset SD engine */
124 return 2UL;
125 }
126 if(pSD->IsCardInsert == (uint8_t)FALSE)
127 {
128 return SDH_NO_SD_CARD;
129 }
130 }
131 }
132 else
133 {
134 while(sdh->CTL & SDH_CTL_RIEN_Msk)
135 {
136 if(pSD->IsCardInsert == (uint8_t)FALSE)
137 {
138 return SDH_NO_SD_CARD;
139 }
140 }
141 }
142
143 if(_SDH_uR7_CMD)
144 {
145 if((sdh->RESP1 & 0xffUL) != 0x55UL)
146 {
147 if((sdh->RESP0 & 0xfUL) != 0x01UL)
148 {
149 _SDH_uR7_CMD = 0UL;
150 return SDH_CMD8_ERROR;
151 }
152 }
153 }
154
155 if(!g_u8R3Flag)
156 {
157 if(sdh->INTSTS & SDH_INTSTS_CRC7_Msk) /* check CRC7 */
158 {
159 return Successful;
160 }
161 else
162 {
163 return SDH_CRC7_ERROR;
164 }
165 }
166 else /* ignore CRC error for R3 case */
167 {
168 g_u8R3Flag = 0UL;
169 sdh->INTSTS = SDH_INTSTS_CRCIF_Msk;
170 return Successful;
171 }
172 }
173
174
SDH_Swap32(uint32_t u32Val)175 uint32_t SDH_Swap32(uint32_t u32Val)
176 {
177 uint32_t u32Buf;
178
179 u32Buf = u32Val;
180 u32Val <<= 24;
181 u32Val |= (u32Buf << 8) & 0xff0000UL;
182 u32Val |= (u32Buf >> 8) & 0xff00UL;
183 u32Val |= (u32Buf >> 24) & 0xffUL;
184 return u32Val;
185 }
186
187 /* Get 16 bytes CID or CSD */
SDH_SDCmdAndRsp2(SDH_T * sdh,uint32_t u32Cmd,uint32_t u32Arg,uint32_t pu32R2ptr[])188 uint32_t SDH_SDCmdAndRsp2(SDH_T *sdh, uint32_t u32Cmd, uint32_t u32Arg, uint32_t pu32R2ptr[])
189 {
190 uint32_t i;
191 uint32_t au32TmpBuf[5];
192 SDH_INFO_T *pSD;
193
194 /* Only support SDH0 here*/
195 pSD = &SD0;
196
197 sdh->CMDARG = u32Arg;
198 sdh->CTL = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | (u32Cmd << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_R2EN_Msk);
199
200 while(sdh->CTL & SDH_CTL_R2EN_Msk)
201 {
202 if(pSD->IsCardInsert == (uint8_t)FALSE)
203 {
204 return SDH_NO_SD_CARD;
205 }
206 }
207
208 if(sdh->INTSTS & SDH_INTSTS_CRC7_Msk)
209 {
210 for(i = 0UL; i < 5UL; i++)
211 {
212 au32TmpBuf[i] = SDH_Swap32(sdh->FB[i]);
213 }
214 for(i = 0UL; i < 4UL; i++)
215 {
216 pu32R2ptr[i] = ((au32TmpBuf[i] & 0x00ffffffUL) << 8) | ((au32TmpBuf[i + 1UL] & 0xff000000UL) >> 24);
217 }
218 return Successful;
219 }
220 else
221 {
222 return SDH_CRC7_ERROR;
223 }
224 }
225
226
SDH_SDCmdAndRspDataIn(SDH_T * sdh,uint32_t u32Cmd,uint32_t u32Arg)227 uint32_t SDH_SDCmdAndRspDataIn(SDH_T *sdh, uint32_t u32Cmd, uint32_t u32Arg)
228 {
229 SDH_INFO_T *pSD;
230
231 /* Only support SDH0 here*/
232 pSD = &SD0;
233
234 sdh->CMDARG = u32Arg;
235 sdh->CTL = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | ((uint32_t)u32Cmd << 8) |
236 (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk);
237
238 while(sdh->CTL & SDH_CTL_RIEN_Msk)
239 {
240 if(pSD->IsCardInsert == (uint32_t)FALSE)
241 {
242 return SDH_NO_SD_CARD;
243 }
244 }
245
246 while(sdh->CTL & SDH_CTL_DIEN_Msk)
247 {
248 if(pSD->IsCardInsert == (uint32_t)FALSE)
249 {
250 return SDH_NO_SD_CARD;
251 }
252 }
253
254 if(!(sdh->INTSTS & SDH_INTSTS_CRC7_Msk)) /* check CRC7 */
255 {
256 return SDH_CRC7_ERROR;
257 }
258
259 if(!(sdh->INTSTS & SDH_INTSTS_CRC16_Msk)) /* check CRC16 */
260 {
261 return SDH_CRC16_ERROR;
262 }
263
264 return Successful;
265 }
266
267 /* there are 8 bits for divider0, maximum is 256 */
268 #define SDH_CLK_DIV0_MAX 256UL
269
SDH_Set_clock(SDH_T * sdh,uint32_t u32SDClockKhz)270 void SDH_Set_clock(SDH_T *sdh, uint32_t u32SDClockKhz)
271 {
272 (void)sdh;
273 if(!(__PC() & (1UL << 28)))
274 {
275 uint32_t u32Rate, u32Div1;
276 static uint32_t u32SDClkSrc = 0UL;
277
278 /* Only support SDH0 here*/
279 u32SDClkSrc = (CLK->CLKSEL0 & CLK_CLKSEL0_SDH0SEL_Msk);
280 if(u32SDClkSrc == CLK_CLKSEL0_SDH0SEL_HXT)
281 {
282 _SDH_ReferenceClock = (CLK_GetHXTFreq() / 1000UL);
283 }
284 else if(u32SDClkSrc == CLK_CLKSEL0_SDH0SEL_HIRC)
285 {
286 _SDH_ReferenceClock = (__HIRC / 1000UL);
287 }
288 else if(u32SDClkSrc == CLK_CLKSEL0_SDH0SEL_PLL)
289 {
290 _SDH_ReferenceClock = (CLK_GetPLLClockFreq() / 1000UL);
291 }
292 else if(u32SDClkSrc == CLK_CLKSEL0_SDH0SEL_HCLK)
293 {
294 _SDH_ReferenceClock = (CLK_GetHCLKFreq() / 1000UL);
295 }
296
297 if(u32SDClockKhz >= 50000UL)
298 {
299 u32SDClockKhz = 50000UL;
300 }
301 u32Rate = _SDH_ReferenceClock / u32SDClockKhz;
302
303 /* choose slower clock if system clock cannot divisible by wanted clock */
304 if(_SDH_ReferenceClock % u32SDClockKhz != 0UL)
305 {
306 u32Rate++;
307 }
308
309 if(u32Rate >= SDH_CLK_DIV0_MAX)
310 {
311 u32Rate = SDH_CLK_DIV0_MAX;
312 }
313
314 /* --- calculate the second divider CLKDIV0[SDHOST_N] */
315 if(u32Rate == 0UL)
316 {
317 u32Div1 = 0UL;
318 }
319 else
320 {
321 u32Div1 = ((u32Rate - 1UL) & 0xFFUL);
322 }
323
324 /* --- setup register */
325 /* Only support SDH0 here*/
326 CLK->CLKDIV0 &= ~CLK_CLKDIV0_SDH0DIV_Msk;
327 CLK->CLKDIV0 |= (u32Div1 << CLK_CLKDIV0_SDH0DIV_Pos);
328 }
329 }
330
SDH_CardDetection(SDH_T * sdh)331 uint32_t SDH_CardDetection(SDH_T *sdh)
332 {
333 uint32_t i, u32Status = (uint32_t)TRUE;
334 SDH_INFO_T *pSD;
335
336 /* Only support SDH0 here*/
337 pSD = &SD0;
338
339 if(sdh->INTEN & SDH_INTEN_CDSRC_Msk) /* Card detect pin from GPIO */
340 {
341 if(sdh->INTSTS & SDH_INTSTS_CDSTS_Msk) /* Card remove */
342 {
343 pSD->IsCardInsert = (uint8_t)FALSE;
344 u32Status = (uint32_t)FALSE;
345 }
346 else
347 {
348 pSD->IsCardInsert = (uint8_t)TRUE;
349 }
350 }
351 else if(!(sdh->INTEN & SDH_INTEN_CDSRC_Msk))
352 {
353 sdh->CTL |= SDH_CTL_CLKKEEP_Msk;
354 for(i = 0UL; i < 5000UL; i++) {}
355
356 if(sdh->INTSTS & SDH_INTSTS_CDSTS_Msk) /* Card insert */
357 {
358 pSD->IsCardInsert = (uint8_t)TRUE;
359 }
360 else
361 {
362 pSD->IsCardInsert = (uint8_t)FALSE;
363 u32Status = (uint32_t)FALSE;
364 }
365
366 sdh->CTL &= ~SDH_CTL_CLKKEEP_Msk;
367 }
368
369 return u32Status;
370 }
371
372
373 /* Initial */
SDH_Init(SDH_T * sdh)374 uint32_t SDH_Init(SDH_T *sdh)
375 {
376 uint32_t volatile i, u32Status;
377 uint32_t u32Resp;
378 uint32_t au32CIDBuffer[4];
379 uint32_t volatile u32CmdTimeOut;
380 SDH_INFO_T *pSD;
381
382 /* Only support SDH0 here*/
383 pSD = &SD0;
384
385 /* set the clock to 300KHz */
386 SDH_Set_clock(sdh, 300UL);
387
388 /* power ON 74 clock */
389 sdh->CTL |= SDH_CTL_CLK74OEN_Msk;
390
391 while(sdh->CTL & SDH_CTL_CLK74OEN_Msk)
392 {
393 if(pSD->IsCardInsert == (uint8_t)FALSE)
394 {
395 return SDH_NO_SD_CARD;
396 }
397 }
398
399 SDH_SDCommand(sdh, 0UL, 0UL); /* reset all cards */
400 for(i = 0x1000UL; i > 0UL; i--) {}
401
402 /* initial SDHC */
403 _SDH_uR7_CMD = 1UL;
404 u32CmdTimeOut = 0xFFFFFUL;
405
406 i = SDH_SDCmdAndRsp(sdh, 8UL, 0x00000155UL, u32CmdTimeOut);
407 if(i == Successful)
408 {
409 /* SD 2.0 */
410 SDH_SDCmdAndRsp(sdh, 55UL, 0x00UL, u32CmdTimeOut);
411 g_u8R3Flag = 1UL;
412 SDH_SDCmdAndRsp(sdh, 41UL, 0x40ff8000UL, u32CmdTimeOut); /* 2.7v-3.6v */
413 u32Resp = sdh->RESP0;
414
415 while(!(u32Resp & 0x00800000UL)) /* check if card is ready */
416 {
417 SDH_SDCmdAndRsp(sdh, 55UL, 0x00UL, u32CmdTimeOut);
418 g_u8R3Flag = 1UL;
419 SDH_SDCmdAndRsp(sdh, 41UL, 0x40ff8000UL, u32CmdTimeOut); /* 3.0v-3.4v */
420 u32Resp = sdh->RESP0;
421 }
422 if(u32Resp & 0x00400000UL)
423 {
424 pSD->CardType = SDH_TYPE_SD_HIGH;
425 }
426 else
427 {
428 pSD->CardType = SDH_TYPE_SD_LOW;
429 }
430 }
431 else
432 {
433 /* SD 1.1 */
434 SDH_SDCommand(sdh, 0UL, 0UL); /* reset all cards */
435 for(i = 0x100UL; i > 0UL; i--) {}
436
437 i = SDH_SDCmdAndRsp(sdh, 55UL, 0x00UL, u32CmdTimeOut);
438 if(i == 2UL) /* MMC memory */
439 {
440 SDH_SDCommand(sdh, 0UL, 0UL); /* reset */
441 for(i = 0x100UL; i > 0UL; i--) {}
442
443 g_u8R3Flag = 1UL;
444
445 if(SDH_SDCmdAndRsp(sdh, 1UL, 0x40ff8000UL, u32CmdTimeOut) != 2UL) /* eMMC memory */
446 {
447 u32Resp = sdh->RESP0;
448 while(!(u32Resp & 0x00800000UL)) /* check if card is ready */
449 {
450 g_u8R3Flag = 1UL;
451
452 SDH_SDCmdAndRsp(sdh, 1UL, 0x40ff8000UL, u32CmdTimeOut); /* high voltage */
453 u32Resp = sdh->RESP0;
454 }
455
456 if(u32Resp & 0x00400000UL)
457 {
458 pSD->CardType = SDH_TYPE_EMMC;
459 }
460 else
461 {
462 pSD->CardType = SDH_TYPE_MMC;
463 }
464 }
465 else
466 {
467 pSD->CardType = SDH_TYPE_UNKNOWN;
468 return SDH_ERR_DEVICE;
469 }
470 }
471 else if(i == 0UL) /* SD Memory */
472 {
473 g_u8R3Flag = 1UL;
474 SDH_SDCmdAndRsp(sdh, 41UL, 0x00ff8000UL, u32CmdTimeOut); /* 3.0v-3.4v */
475 u32Resp = sdh->RESP0;
476 while(!(u32Resp & 0x00800000UL)) /* check if card is ready */
477 {
478 SDH_SDCmdAndRsp(sdh, 55UL, 0x00UL, u32CmdTimeOut);
479 g_u8R3Flag = 1UL;
480 SDH_SDCmdAndRsp(sdh, 41UL, 0x00ff8000UL, u32CmdTimeOut); /* 3.0v-3.4v */
481 u32Resp = sdh->RESP0;
482 }
483 pSD->CardType = SDH_TYPE_SD_LOW;
484 }
485 else
486 {
487 pSD->CardType = SDH_TYPE_UNKNOWN;
488 return SDH_INIT_ERROR;
489 }
490 }
491
492 /* CMD2, CMD3 */
493 if(pSD->CardType != SDH_TYPE_UNKNOWN)
494 {
495 SDH_SDCmdAndRsp2(sdh, 2UL, 0x00UL, au32CIDBuffer);
496 if((pSD->CardType == SDH_TYPE_MMC) || (pSD->CardType == SDH_TYPE_EMMC))
497 {
498 if((u32Status = SDH_SDCmdAndRsp(sdh, 3UL, 0x10000UL, 0UL)) != Successful) /* set RCA */
499 {
500 return u32Status;
501 }
502 pSD->RCA = 0x10000UL;
503 }
504 else
505 {
506 if((u32Status = SDH_SDCmdAndRsp(sdh, 3UL, 0x00UL, 0UL)) != Successful) /* get RCA */
507 {
508 return u32Status;
509 }
510 else
511 {
512 pSD->RCA = (sdh->RESP0 << 8) & 0xffff0000UL;
513 }
514 }
515 }
516
517 return Successful;
518 }
519
520
SDH_SwitchToHighSpeed(SDH_T * sdh,SDH_INFO_T * pSD)521 uint32_t SDH_SwitchToHighSpeed(SDH_T *sdh, SDH_INFO_T *pSD)
522 {
523 uint32_t volatile u32Status = 0UL;
524 uint16_t u16CurrentComsumption, u16BusyStatus0;
525
526 (void)pSD;
527 sdh->DMASA = (uint32_t)_SDH_ucSDHCBuffer; /* set DMA transfer starting address */
528 sdh->BLEN = 63UL; /* 512 bit */
529
530 if((u32Status = SDH_SDCmdAndRspDataIn(sdh, 6UL, 0x00ffff01UL)) != Successful)
531 {
532 return Fail;
533 }
534
535 u16CurrentComsumption = (uint16_t)(_SDH_ucSDHCBuffer[0] << 8);
536 u16CurrentComsumption |= (uint16_t)_SDH_ucSDHCBuffer[1];
537 if(!u16CurrentComsumption)
538 {
539 return Fail;
540 }
541
542 u16BusyStatus0 = (uint16_t)(_SDH_ucSDHCBuffer[28] << 8);
543 u16BusyStatus0 |= (uint16_t)_SDH_ucSDHCBuffer[29];
544
545 if(!u16BusyStatus0) /* function ready */
546 {
547 sdh->DMASA = (uint32_t)_SDH_ucSDHCBuffer; /* set DMA transfer starting address */
548 sdh->BLEN = 63UL; /* 512 bit */
549
550 if((u32Status = SDH_SDCmdAndRspDataIn(sdh, 6UL, 0x80ffff01UL)) != Successful)
551 {
552 return Fail;
553 }
554
555 /* function change timing: 8 clocks */
556 sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
557 while(sdh->CTL & SDH_CTL_CLK8OEN_Msk) {}
558
559 u16CurrentComsumption = (uint16_t)(_SDH_ucSDHCBuffer[0] << 8);
560 u16CurrentComsumption |= (uint16_t)_SDH_ucSDHCBuffer[1];
561 if(!u16CurrentComsumption)
562 {
563 return Fail;
564 }
565
566 return Successful;
567 }
568 else
569 {
570 return Fail;
571 }
572 }
573
574
SDH_SelectCardType(SDH_T * sdh)575 uint32_t SDH_SelectCardType(SDH_T *sdh)
576 {
577 uint32_t volatile u32Status = 0UL;
578 uint32_t u32Param;
579 SDH_INFO_T *pSD;
580
581 /* Only support SDH0 here*/
582 pSD = &SD0;
583
584 if((u32Status = SDH_SDCmdAndRsp(sdh, 7UL, pSD->RCA, 0UL)) != Successful)
585 {
586 return u32Status;
587 }
588
589 SDH_CheckRB(sdh);
590
591 /* if SD card set 4bit */
592 if(pSD->CardType == SDH_TYPE_SD_HIGH)
593 {
594 sdh->DMASA = (uint32_t)_SDH_ucSDHCBuffer; /* set DMA transfer starting address */
595 sdh->BLEN = 0x07UL; /* 64 bit */
596
597 if((u32Status = SDH_SDCmdAndRsp(sdh, 55UL, pSD->RCA, 0UL)) != Successful)
598 {
599 return u32Status;
600 }
601
602 sdh->DMACTL |= 0x2;
603 while(sdh->DMACTL & 0x2) {}
604
605 if((u32Status = SDH_SDCmdAndRspDataIn(sdh, 51UL, 0x00UL)) != Successful)
606 {
607 return u32Status;
608 }
609
610 if((_SDH_ucSDHCBuffer[0] & 0xfUL) == 0xfUL)
611 {
612 u32Status = SDH_SwitchToHighSpeed(sdh, pSD);
613 if(u32Status == Successful)
614 {
615 /* divider */
616 SDH_Set_clock(sdh, SDHC_FREQ);
617 }
618 }
619
620 if((u32Status = SDH_SDCmdAndRsp(sdh, 55UL, pSD->RCA, 0UL)) != Successful)
621 {
622 return u32Status;
623 }
624 if((u32Status = SDH_SDCmdAndRsp(sdh, 6UL, 0x02UL, 0UL)) != Successful) /* set bus width */
625 {
626 return u32Status;
627 }
628
629 sdh->CTL |= SDH_CTL_DBW_Msk;
630 }
631 else if(pSD->CardType == SDH_TYPE_SD_LOW)
632 {
633 sdh->DMASA = (uint32_t) _SDH_ucSDHCBuffer; /* set DMA transfer starting address */
634 sdh->BLEN = 0x07UL; /* 64 bit */
635
636 if((u32Status = SDH_SDCmdAndRsp(sdh, 55UL, pSD->RCA, 0UL)) != Successful)
637 {
638 return u32Status;
639 }
640 if((u32Status = SDH_SDCmdAndRspDataIn(sdh, 51UL, 0x00UL)) != Successful)
641 {
642 return u32Status;
643 }
644
645 /* set data bus width. ACMD6 for SD card, SDCR_DBW for host. */
646 if((u32Status = SDH_SDCmdAndRsp(sdh, 55UL, pSD->RCA, 0UL)) != Successful)
647 {
648 return u32Status;
649 }
650
651 if((u32Status = SDH_SDCmdAndRsp(sdh, 6UL, 0x02UL, 0UL)) != Successful) /* set bus width */
652 {
653 return u32Status;
654 }
655
656 sdh->CTL |= SDH_CTL_DBW_Msk;
657 }
658 else if((pSD->CardType == SDH_TYPE_MMC) || (pSD->CardType == SDH_TYPE_EMMC))
659 {
660
661 if(pSD->CardType == SDH_TYPE_MMC)
662 {
663 sdh->CTL &= ~SDH_CTL_DBW_Msk;
664 }
665
666 /* --- sent CMD6 to MMC card to set bus width to 4 bits mode */
667 /* set CMD6 argument Access field to 3, Index to 183, Value to 1 (4-bit mode) */
668 u32Param = (3UL << 24) | (183UL << 16) | (1UL << 8);
669 if((u32Status = SDH_SDCmdAndRsp(sdh, 6UL, u32Param, 0UL)) != Successful)
670 {
671 return u32Status;
672 }
673 SDH_CheckRB(sdh);
674
675 sdh->CTL |= SDH_CTL_DBW_Msk; /* set bus width to 4-bit mode for SD host controller */
676 }
677
678 if((u32Status = SDH_SDCmdAndRsp(sdh, 16UL, SDH_BLOCK_SIZE, 0UL)) != Successful) /* set block length */
679 {
680 return u32Status;
681 }
682 sdh->BLEN = SDH_BLOCK_SIZE - 1UL; /* set the block size */
683
684 SDH_SDCommand(sdh, 7UL, 0UL);
685 sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
686 while(sdh->CTL & SDH_CTL_CLK8OEN_Msk) {}
687
688 sdh->INTEN |= SDH_INTEN_BLKDIEN_Msk;
689
690 return Successful;
691 }
692
SDH_Get_SD_info(SDH_T * sdh)693 void SDH_Get_SD_info(SDH_T *sdh)
694 {
695 uint32_t u32RLen, u32CSize, u32Mult, u32Size;
696 uint32_t au32Buffer[4];
697 SDH_INFO_T *pSD;
698
699 /* Only support SDH0 here*/
700 pSD = &SD0;
701
702 SDH_SDCmdAndRsp2(sdh, 9UL, pSD->RCA, au32Buffer);
703
704 if((pSD->CardType == SDH_TYPE_MMC) || (pSD->CardType == SDH_TYPE_EMMC))
705 {
706 /* for MMC/eMMC card */
707 if((au32Buffer[0] & 0xc0000000UL) == 0xc0000000UL)
708 {
709 /* CSD_STRUCTURE [127:126] is 3 */
710 /* CSD version depend on EXT_CSD register in eMMC v4.4 for card size > 2GB */
711 SDH_SDCmdAndRsp(sdh, 7UL, pSD->RCA, 0UL);
712
713 sdh->DMASA = (uint32_t)_SDH_ucSDHCBuffer; /* set DMA transfer starting address */
714 sdh->BLEN = 511UL; /* read 512 bytes for EXT_CSD */
715
716 if(SDH_SDCmdAndRspDataIn(sdh, 8UL, 0x00UL) != Successful)
717 {
718 return;
719 }
720
721 SDH_SDCommand(sdh, 7UL, 0UL);
722 sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
723 while(sdh->CTL & SDH_CTL_CLK8OEN_Msk) {}
724
725 pSD->totalSectorN = (uint32_t)_SDH_ucSDHCBuffer[215] << 24;
726 pSD->totalSectorN |= (uint32_t)_SDH_ucSDHCBuffer[214] << 16;
727 pSD->totalSectorN |= (uint32_t)_SDH_ucSDHCBuffer[213] << 8;
728 pSD->totalSectorN |= (uint32_t)_SDH_ucSDHCBuffer[212];
729 pSD->diskSize = pSD->totalSectorN / 2UL;
730 }
731 else
732 {
733 /* CSD version v1.0/1.1/1.2 in eMMC v4.4 spec for card size <= 2GB */
734 u32RLen = (au32Buffer[1] & 0x000f0000UL) >> 16;
735 u32CSize = ((au32Buffer[1] & 0x000003ffUL) << 2) | ((au32Buffer[2] & 0xc0000000UL) >> 30);
736 u32Mult = (au32Buffer[2] & 0x00038000UL) >> 15;
737 u32Size = (u32CSize + 1UL) * (1UL << (u32Mult + 2UL)) * (1UL << u32RLen);
738
739 pSD->diskSize = u32Size / 1024UL;
740 pSD->totalSectorN = u32Size / 512UL;
741 }
742 }
743 else
744 {
745 if(au32Buffer[0] & 0xc0000000UL)
746 {
747 u32CSize = ((au32Buffer[1] & 0x0000003fUL) << 16) | ((au32Buffer[2] & 0xffff0000UL) >> 16);
748 u32Size = (u32CSize + 1UL) * 512UL; /* Kbytes */
749
750 pSD->diskSize = u32Size;
751 pSD->totalSectorN = u32Size << 1;
752 }
753 else
754 {
755 u32RLen = (au32Buffer[1] & 0x000f0000UL) >> 16;
756 u32CSize = ((au32Buffer[1] & 0x000003ffUL) << 2) | ((au32Buffer[2] & 0xc0000000UL) >> 30);
757 u32Mult = (au32Buffer[2] & 0x00038000UL) >> 15;
758 u32Size = (u32CSize + 1UL) * (1UL << (u32Mult + 2UL)) * (1UL << u32RLen);
759
760 pSD->diskSize = u32Size / 1024UL;
761 pSD->totalSectorN = u32Size / 512UL;
762 }
763 }
764 pSD->sectorSize = (int)512UL;
765 }
766
767 /** @endcond HIDDEN_SYMBOLS */
768
769
770 /**
771 * @brief This function use to reset SD function and select card detection source and pin.
772 *
773 * @param[in] sdh The pointer of the specified SDH module.
774 * @param[in] u32CardDetSrc Select card detection pin from GPIO or DAT3 pin. ( \ref CardDetect_From_GPIO / \ref CardDetect_From_DAT3)
775 *
776 * @return None
777 */
SDH_Open(SDH_T * sdh,uint32_t u32CardDetSrc)778 void SDH_Open(SDH_T *sdh, uint32_t u32CardDetSrc)
779 {
780 /* enable DMAC */
781 sdh->DMACTL = SDH_DMACTL_DMARST_Msk;
782 while(sdh->DMACTL & SDH_DMACTL_DMARST_Msk) {}
783
784 sdh->DMACTL = SDH_DMACTL_DMAEN_Msk;
785
786 /* Reset FMI */
787 sdh->GCTL = SDH_GCTL_GCTLRST_Msk | SDH_GCTL_SDEN_Msk; /* Start reset FMI controller. */
788 while(sdh->GCTL & SDH_GCTL_GCTLRST_Msk) {}
789
790 memset(&SD0, 0, sizeof(SDH_INFO_T));
791
792 /* enable SD */
793 sdh->GCTL = SDH_GCTL_SDEN_Msk;
794
795 if(u32CardDetSrc & CardDetect_From_DAT3)
796 {
797 sdh->INTEN &= ~SDH_INTEN_CDSRC_Msk;
798 }
799 else
800 {
801 sdh->INTEN |= SDH_INTEN_CDSRC_Msk;
802 }
803 sdh->INTEN |= SDH_INTEN_CDIEN_Msk;
804
805 sdh->CTL |= SDH_CTL_CTLRST_Msk; /* SD software reset */
806 while(sdh->CTL & SDH_CTL_CTLRST_Msk) {}
807
808 }
809
810 /**
811 * @brief This function use to initial SD card.
812 *
813 * @param[in] sdh The pointer of the specified SDH module.
814 *
815 * @return None
816 *
817 * @details This function is used to initial SD card.
818 * SD initial state needs 400KHz clock output, driver will use HIRC for SD initial clock source.
819 * And then switch back to the user's setting.
820 */
SDH_Probe(SDH_T * sdh)821 uint32_t SDH_Probe(SDH_T *sdh)
822 {
823 uint32_t u32Val;
824
825 /* Disable FMI/SD host interrupt */
826 sdh->GINTEN = 0UL;
827
828 sdh->CTL &= ~SDH_CTL_SDNWR_Msk;
829 sdh->CTL |= 0x09UL << SDH_CTL_SDNWR_Pos; /* set SDNWR = 9 */
830 sdh->CTL &= ~SDH_CTL_BLKCNT_Msk;
831 sdh->CTL |= 0x01UL << SDH_CTL_BLKCNT_Pos; /* set BLKCNT = 1 */
832 sdh->CTL &= ~SDH_CTL_DBW_Msk; /* SD 1-bit data bus */
833
834 if(!(SDH_CardDetection(sdh)))
835 {
836 return SDH_NO_SD_CARD;
837 }
838
839 if((u32Val = SDH_Init(sdh)) != 0UL)
840 {
841 return u32Val;
842 }
843
844 /* divider */
845 if(SD0.CardType == SDH_TYPE_MMC)
846 {
847 SDH_Set_clock(sdh, MMC_FREQ);
848 }
849 else
850 {
851 SDH_Set_clock(sdh, SD_FREQ);
852 }
853 SDH_Get_SD_info(sdh);
854
855 if((u32Val = SDH_SelectCardType(sdh)) != 0UL)
856 {
857 return u32Val;
858 }
859
860 return 0UL;
861 }
862
863 /**
864 * @brief This function use to read data from SD card.
865 *
866 * @param[in] sdh The pointer of the specified SDH module.
867 * @param[out] pu8BufAddr The buffer to receive the data from SD card.
868 * @param[in] u32StartSec The start read sector address.
869 * @param[in] u32SecCount The the read sector number of data
870 *
871 * @return None
872 */
SDH_Read(SDH_T * sdh,uint8_t * pu8BufAddr,uint32_t u32StartSec,uint32_t u32SecCount)873 uint32_t SDH_Read(SDH_T *sdh, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount)
874 {
875 uint32_t volatile u32IsSendCmd = (uint32_t)FALSE;
876 uint32_t volatile u32Reg;
877 uint32_t volatile u32Loop, u32Status;
878 uint32_t u32BlkSize = SDH_BLOCK_SIZE;
879
880 SDH_INFO_T *pSD;
881
882 /* Only support SDH0 here*/
883 pSD = &SD0;
884
885 /* --- check input parameters */
886 if(u32SecCount == 0UL)
887 {
888 return SDH_SELECT_ERROR;
889 }
890
891 if((u32Status = SDH_SDCmdAndRsp(sdh, 7UL, pSD->RCA, 0UL)) != Successful)
892 {
893 return u32Status;
894 }
895 SDH_CheckRB(sdh);
896
897 sdh->BLEN = u32BlkSize - 1UL; /* the actual byte count is equal to (SDBLEN+1) */
898
899 if((pSD->CardType == SDH_TYPE_SD_HIGH) || (pSD->CardType == SDH_TYPE_EMMC))
900 {
901 sdh->CMDARG = u32StartSec;
902 }
903 else
904 {
905 sdh->CMDARG = u32StartSec * u32BlkSize;
906 }
907
908 sdh->DMASA = (uint32_t)pu8BufAddr;
909
910 u32Loop = u32SecCount / 255UL;
911 while(u32Loop > 0UL)
912 {
913 g_u8SDDataReadyFlag = (uint8_t)FALSE;
914 u32Reg = sdh->CTL & ~SDH_CTL_CMDCODE_Msk;
915 u32Reg = u32Reg | 0xff0000UL; /* set BLK_CNT to 255 */
916 if(u32IsSendCmd == (uint32_t)FALSE)
917 {
918 sdh->CTL = u32Reg | (18UL << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk);
919 u32IsSendCmd = (uint32_t)TRUE;
920 }
921 else
922 {
923 sdh->CTL = u32Reg | SDH_CTL_DIEN_Msk;
924 }
925
926 while(!g_u8SDDataReadyFlag)
927 {
928 if(g_u8SDDataReadyFlag)
929 {
930 break;
931 }
932 if(pSD->IsCardInsert == (uint8_t)FALSE)
933 {
934 return SDH_NO_SD_CARD;
935 }
936 }
937
938 if(!(sdh->INTSTS & SDH_INTSTS_CRC7_Msk)) /* check CRC7 */
939 {
940 return SDH_CRC7_ERROR;
941 }
942
943 if(!(sdh->INTSTS & SDH_INTSTS_CRC16_Msk)) /* check CRC16 */
944 {
945 return SDH_CRC16_ERROR;
946 }
947 u32Loop--;
948 }
949
950 u32Loop = u32SecCount % 255UL;
951 if(u32Loop != 0UL)
952 {
953 uint32_t u32RegTmp;
954 g_u8SDDataReadyFlag = (uint8_t)FALSE;
955 u32Reg = sdh->CTL & (~SDH_CTL_CMDCODE_Msk);
956 u32Reg = u32Reg & (~SDH_CTL_BLKCNT_Msk);
957 u32RegTmp = (u32Loop << 16);
958 u32Reg |= u32RegTmp; /* setup SDCR_BLKCNT */
959
960 if(u32IsSendCmd == (uint32_t)FALSE)
961 {
962 sdh->CTL = u32Reg | (18UL << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk);
963 u32IsSendCmd = (uint32_t)TRUE;
964 }
965 else
966 {
967 sdh->CTL = u32Reg | SDH_CTL_DIEN_Msk;
968 }
969
970 while(!g_u8SDDataReadyFlag)
971 {
972 if(pSD->IsCardInsert == (uint8_t)FALSE)
973 {
974 return SDH_NO_SD_CARD;
975 }
976 }
977
978 if(!(sdh->INTSTS & SDH_INTSTS_CRC7_Msk)) /* check CRC7 */
979 {
980 return SDH_CRC7_ERROR;
981 }
982
983 if(!(sdh->INTSTS & SDH_INTSTS_CRC16_Msk)) /* check CRC16 */
984 {
985 return SDH_CRC16_ERROR;
986 }
987 }
988
989 if(SDH_SDCmdAndRsp(sdh, 12UL, 0UL, 0UL)) /* stop command */
990 {
991 return SDH_CRC7_ERROR;
992 }
993 SDH_CheckRB(sdh);
994
995 SDH_SDCommand(sdh, 7UL, 0UL);
996 sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
997 while(sdh->CTL & SDH_CTL_CLK8OEN_Msk) {}
998
999 return Successful;
1000 }
1001
1002 /**
1003 * @brief This function use to write data to SD card.
1004 *
1005 * @param[in] sdh The pointer of the specified SDH module.
1006 * @param[in] pu8BufAddr The buffer to send the data to SD card.
1007 * @param[in] u32StartSec The start write sector address.
1008 * @param[in] u32SecCount The the write sector number of data.
1009 *
1010 * @return \ref SDH_SELECT_ERROR : u32SecCount is zero. \n
1011 * \ref SDH_NO_SD_CARD : SD card be removed. \n
1012 * \ref SDH_CRC_ERROR : CRC error happen. \n
1013 * \ref SDH_CRC7_ERROR : CRC7 error happen. \n
1014 * \ref Successful : Write data to SD card success.
1015 */
SDH_Write(SDH_T * sdh,uint8_t * pu8BufAddr,uint32_t u32StartSec,uint32_t u32SecCount)1016 uint32_t SDH_Write(SDH_T *sdh, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount)
1017 {
1018 uint32_t volatile u32IsSendCmd = (uint32_t)FALSE;
1019 uint32_t volatile u32Reg;
1020 uint32_t volatile u32Loop, u32Status;
1021
1022 SDH_INFO_T *pSD;
1023
1024 /* Only support SDH0 here*/
1025 pSD = &SD0;
1026
1027 /* --- check input parameters */
1028 if(u32SecCount == 0UL)
1029 {
1030 return SDH_SELECT_ERROR;
1031 }
1032
1033 if((u32Status = SDH_SDCmdAndRsp(sdh, 7UL, pSD->RCA, 0UL)) != Successful)
1034 {
1035 return u32Status;
1036 }
1037
1038 SDH_CheckRB(sdh);
1039
1040 /* According to SD Spec v2.0, the write CMD block size MUST be 512, and the start address MUST be 512*n. */
1041 sdh->BLEN = SDH_BLOCK_SIZE - 1UL; /* set the block size */
1042
1043 if((pSD->CardType == SDH_TYPE_SD_HIGH) || (pSD->CardType == SDH_TYPE_EMMC))
1044 {
1045 sdh->CMDARG = u32StartSec;
1046 }
1047 else
1048 {
1049 sdh->CMDARG = u32StartSec * SDH_BLOCK_SIZE; /* set start address for SD CMD */
1050 }
1051
1052 sdh->DMASA = (uint32_t)pu8BufAddr;
1053 u32Loop = u32SecCount / 255UL; /* the maximum block count is 0xFF=255 for register SDCR[BLK_CNT] */
1054 while(u32Loop > 0UL)
1055 {
1056 g_u8SDDataReadyFlag = (uint8_t)FALSE;
1057 u32Reg = sdh->CTL & 0xff00c080UL;
1058 u32Reg = u32Reg | 0xff0000UL; /* set BLK_CNT to 0xFF=255 */
1059 if(!u32IsSendCmd)
1060 {
1061 sdh->CTL = u32Reg | (25UL << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DOEN_Msk);
1062 u32IsSendCmd = (uint32_t)TRUE;
1063 }
1064 else
1065 {
1066 sdh->CTL = u32Reg | SDH_CTL_DOEN_Msk;
1067 }
1068
1069 while(!g_u8SDDataReadyFlag)
1070 {
1071 if(pSD->IsCardInsert == (uint8_t)FALSE)
1072 {
1073 return SDH_NO_SD_CARD;
1074 }
1075 }
1076
1077 if((sdh->INTSTS & SDH_INTSTS_CRCIF_Msk) != 0UL) /* check CRC */
1078 {
1079 sdh->INTSTS = SDH_INTSTS_CRCIF_Msk;
1080 return SDH_CRC_ERROR;
1081 }
1082 u32Loop--;
1083 }
1084
1085 u32Loop = u32SecCount % 255UL;
1086 if(u32Loop != 0UL)
1087 {
1088 uint32_t u32RegTmp;
1089 g_u8SDDataReadyFlag = (uint8_t)FALSE;
1090 u32RegTmp = (u32Loop << 16);
1091 u32Reg = (sdh->CTL & 0xff00c080UL) | u32RegTmp;
1092 if(!u32IsSendCmd)
1093 {
1094 sdh->CTL = u32Reg | (25UL << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DOEN_Msk);
1095 u32IsSendCmd = (uint32_t)TRUE;
1096 }
1097 else
1098 {
1099 sdh->CTL = u32Reg | SDH_CTL_DOEN_Msk;
1100 }
1101
1102 while(!g_u8SDDataReadyFlag)
1103 {
1104 if(pSD->IsCardInsert == (uint8_t)FALSE)
1105 {
1106 return SDH_NO_SD_CARD;
1107 }
1108 }
1109
1110 if((sdh->INTSTS & SDH_INTSTS_CRCIF_Msk) != 0UL) /* check CRC */
1111 {
1112 sdh->INTSTS = SDH_INTSTS_CRCIF_Msk;
1113 return SDH_CRC_ERROR;
1114 }
1115 }
1116 sdh->INTSTS = SDH_INTSTS_CRCIF_Msk;
1117
1118 if(SDH_SDCmdAndRsp(sdh, 12UL, 0UL, 0UL)) /* stop command */
1119 {
1120 return SDH_CRC7_ERROR;
1121 }
1122 SDH_CheckRB(sdh);
1123
1124 SDH_SDCommand(sdh, 7UL, 0UL);
1125 sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
1126 while(sdh->CTL & SDH_CTL_CLK8OEN_Msk) {}
1127
1128 return Successful;
1129 }
1130
1131
1132 /**@}*/ /* end of group SDH_EXPORTED_FUNCTIONS */
1133
1134 /**@}*/ /* end of group SDH_Driver */
1135
1136 /**@}*/ /* end of group Standard_Driver */
1137