1 /**************************************************************************//**
2 * @file SDH.c
3 * @version V1.00
4 * @brief SDH driver source file
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 * @copyright (C) 2021 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 /** @addtogroup Standard_Driver Standard Driver
15 @{
16 */
17
18 /** @addtogroup SDH_Driver SDH Driver
19 @{
20 */
21
22 /** @addtogroup SDH_EXPORTED_FUNCTIONS SDH Exported Functions
23 @{
24 */
25 #define SDH_BLOCK_SIZE 512ul
26
27 /** @cond HIDDEN_SYMBOLS */
28
29 /* global variables */
30 /* For response R3 (such as ACMD41, CRC-7 is invalid; but SD controller will still */
31 /* calculate CRC-7 and get an error result, software should ignore this error and clear SDISR [CRC_IF] flag */
32 /* _sd_uR3_CMD is the flag for it. 1 means software should ignore CRC-7 error */
33
34 int32_t g_SDH_i32ErrCode = 0; /*!< SDH global error code */
35 static uint32_t _SDH0_ReferenceClock, _SDH1_ReferenceClock;
36
37 #ifdef __ICCARM__
38 #pragma data_alignment = 4
39 static uint8_t _SDH0_ucSDHCBuffer[512];
40 static uint8_t _SDH1_ucSDHCBuffer[512];
41 #else
42 static uint8_t _SDH0_ucSDHCBuffer[512] __attribute__((aligned(4)));
43 static uint8_t _SDH1_ucSDHCBuffer[512] __attribute__((aligned(4)));
44 #endif
45
46 SDH_INFO_T SD0, SD1;
47
SDH_CheckRB(SDH_T * sdh)48 void SDH_CheckRB(SDH_T *sdh)
49 {
50 uint32_t u32TimeOutCount1, u32TimeOutCount2;
51
52 g_SDH_i32ErrCode = 0;
53 u32TimeOutCount2 = SDH_TIMEOUT_CNT;
54 while(1)
55 {
56 sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
57 u32TimeOutCount1 = SDH_TIMEOUT_CNT;
58 while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk)
59 {
60 if(--u32TimeOutCount1 == 0)
61 {
62 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
63 break;
64 }
65 }
66 if ((sdh->INTSTS & SDH_INTSTS_DAT0STS_Msk) == SDH_INTSTS_DAT0STS_Msk)
67 {
68 break;
69 }
70 if(--u32TimeOutCount2 == 0)
71 {
72 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
73 break;
74 }
75 }
76 }
77
78
SDH_SDCommand(SDH_T * sdh,uint32_t ucCmd,uint32_t uArg)79 uint32_t SDH_SDCommand(SDH_T *sdh, uint32_t ucCmd, uint32_t uArg)
80 {
81 volatile uint32_t buf, val = 0ul;
82 SDH_INFO_T *pSD;
83 uint32_t u32TimeOutCount = SDH_TIMEOUT_CNT;
84
85 g_SDH_i32ErrCode = 0;
86
87 if (sdh == SDH0)
88 {
89 pSD = &SD0;
90 }
91 else
92 {
93 pSD = &SD1;
94 }
95
96 sdh->CMDARG = uArg;
97 buf = (sdh->CTL&(~SDH_CTL_CMDCODE_Msk))|(ucCmd << 8ul)|(SDH_CTL_COEN_Msk);
98 sdh->CTL = buf;
99
100 while ((sdh->CTL & SDH_CTL_COEN_Msk) == SDH_CTL_COEN_Msk)
101 {
102 if (pSD->IsCardInsert == 0ul)
103 {
104 val = SDH_NO_SD_CARD;
105 }
106 if(--u32TimeOutCount == 0)
107 {
108 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
109 break;
110 }
111 }
112 return val;
113 }
114
115
SDH_SDCmdAndRsp(SDH_T * sdh,uint32_t ucCmd,uint32_t uArg,uint32_t ntickCount)116 uint32_t SDH_SDCmdAndRsp(SDH_T *sdh, uint32_t ucCmd, uint32_t uArg, uint32_t ntickCount)
117 {
118 volatile uint32_t buf;
119 SDH_INFO_T *pSD;
120 uint32_t u32TimeOutCount = SDH_TIMEOUT_CNT;
121
122 g_SDH_i32ErrCode = 0;
123
124 if (sdh == SDH0)
125 {
126 pSD = &SD0;
127 }
128 else
129 {
130 pSD = &SD1;
131 }
132
133 sdh->CMDARG = uArg;
134 buf = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | (ucCmd << 8ul) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk);
135 sdh->CTL = buf;
136
137 if (ntickCount > 0ul)
138 {
139 while ((sdh->CTL & SDH_CTL_RIEN_Msk) == SDH_CTL_RIEN_Msk)
140 {
141 if(ntickCount-- == 0ul)
142 {
143 sdh->CTL |= SDH_CTL_CTLRST_Msk; /* reset SD engine */
144 return 2ul;
145 }
146 if (pSD->IsCardInsert == FALSE)
147 {
148 return SDH_NO_SD_CARD;
149 }
150 }
151 }
152 else
153 {
154 while ((sdh->CTL & SDH_CTL_RIEN_Msk) == SDH_CTL_RIEN_Msk)
155 {
156 if (pSD->IsCardInsert == FALSE)
157 {
158 return SDH_NO_SD_CARD;
159 }
160 if(--u32TimeOutCount == 0)
161 {
162 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
163 break;
164 }
165 }
166 }
167
168 if (pSD->R7Flag)
169 {
170 uint32_t tmp0 = 0ul, tmp1= 0ul;
171 tmp1 = sdh->RESP1 & 0xfful;
172 tmp0 = sdh->RESP0 & 0xful;
173 if ((tmp1 != 0x55ul) && (tmp0 != 0x01ul))
174 {
175 pSD->R7Flag = 0ul;
176 return SDH_CMD8_ERROR;
177 }
178 }
179
180 if (!pSD->R3Flag)
181 {
182 if ((sdh->INTSTS & SDH_INTSTS_CRC7_Msk) == SDH_INTSTS_CRC7_Msk) /* check CRC7 */
183 {
184 return Successful;
185 }
186 else
187 {
188 return SDH_CRC7_ERROR;
189 }
190 }
191 else
192 {
193 /* ignore CRC error for R3 case */
194 pSD->R3Flag = 0ul;
195 sdh->INTSTS = SDH_INTSTS_CRCIF_Msk;
196 return Successful;
197 }
198 }
199
200
SDH_Swap32(uint32_t val)201 uint32_t SDH_Swap32(uint32_t val)
202 {
203 uint32_t buf;
204
205 buf = val;
206 val <<= 24;
207 val |= (buf<<8) & 0xff0000ul;
208 val |= (buf>>8) & 0xff00ul;
209 val |= (buf>>24)& 0xfful;
210 return val;
211 }
212
213 /* Get 16 bytes CID or CSD */
SDH_SDCmdAndRsp2(SDH_T * sdh,uint32_t ucCmd,uint32_t uArg,uint32_t puR2ptr[])214 uint32_t SDH_SDCmdAndRsp2(SDH_T *sdh, uint32_t ucCmd, uint32_t uArg, uint32_t puR2ptr[])
215 {
216 uint32_t i, buf;
217 uint32_t tmpBuf[5];
218 SDH_INFO_T *pSD;
219 uint32_t u32TimeOutCount = SDH_TIMEOUT_CNT;
220
221 g_SDH_i32ErrCode = 0;
222
223 if (sdh == SDH0)
224 {
225 pSD = &SD0;
226 }
227 else
228 {
229 pSD = &SD1;
230 }
231
232 sdh->CMDARG = uArg;
233 buf = (sdh->CTL&(~SDH_CTL_CMDCODE_Msk))|(ucCmd << 8)|(SDH_CTL_COEN_Msk | SDH_CTL_R2EN_Msk);
234 sdh->CTL = buf;
235
236 while ((sdh->CTL & SDH_CTL_R2EN_Msk) == SDH_CTL_R2EN_Msk)
237 {
238 if (pSD->IsCardInsert == FALSE)
239 {
240 return SDH_NO_SD_CARD;
241 }
242 if(--u32TimeOutCount == 0)
243 {
244 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
245 break;
246 }
247 }
248
249 if ((sdh->INTSTS & SDH_INTSTS_CRC7_Msk) == SDH_INTSTS_CRC7_Msk)
250 {
251 for (i=0ul; i<5ul; i++)
252 {
253 tmpBuf[i] = SDH_Swap32(sdh->FB[i]);
254 }
255 for (i=0ul; i<4ul; i++)
256 {
257 puR2ptr[i] = ((tmpBuf[i] & 0x00fffffful)<<8) | ((tmpBuf[i+1ul] & 0xff000000ul)>>24);
258 }
259 }
260 else
261 {
262 return SDH_CRC7_ERROR;
263 }
264 return Successful;
265 }
266
267
SDH_SDCmdAndRspDataIn(SDH_T * sdh,uint32_t ucCmd,uint32_t uArg)268 uint32_t SDH_SDCmdAndRspDataIn(SDH_T *sdh, uint32_t ucCmd, uint32_t uArg)
269 {
270 volatile uint32_t buf;
271 SDH_INFO_T *pSD;
272 uint32_t u32TimeOutCount;
273
274 g_SDH_i32ErrCode = 0;
275
276 if (sdh == SDH0)
277 {
278 pSD = &SD0;
279 }
280 else
281 {
282 pSD = &SD1;
283 }
284
285 sdh->CMDARG = uArg;
286 buf = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk))|(ucCmd << 8ul)|
287 (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk);
288
289 sdh->CTL = buf;
290
291 u32TimeOutCount = SDH_TIMEOUT_CNT;
292 while ((sdh->CTL & SDH_CTL_RIEN_Msk) == SDH_CTL_RIEN_Msk)
293 {
294 if (pSD->IsCardInsert == FALSE)
295 {
296 return SDH_NO_SD_CARD;
297 }
298 if(--u32TimeOutCount == 0)
299 {
300 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
301 break;
302 }
303 }
304
305 u32TimeOutCount = SDH_TIMEOUT_CNT;
306 while ((sdh->CTL & SDH_CTL_DIEN_Msk) == SDH_CTL_DIEN_Msk)
307 {
308 if (pSD->IsCardInsert == FALSE)
309 {
310 return SDH_NO_SD_CARD;
311 }
312 if(--u32TimeOutCount == 0)
313 {
314 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
315 break;
316 }
317 }
318
319 if ((sdh->INTSTS & SDH_INTSTS_CRC7_Msk) != SDH_INTSTS_CRC7_Msk)
320 {
321 /* check CRC7 */
322 return SDH_CRC7_ERROR;
323 }
324
325 if ((sdh->INTSTS & SDH_INTSTS_CRC16_Msk) != SDH_INTSTS_CRC16_Msk)
326 {
327 /* check CRC16 */
328 return SDH_CRC16_ERROR;
329 }
330 return 0ul;
331 }
332
333 /* there are 8 bits for divider0, maximum is 256 */
334 #define SDH_CLK_DIV0_MAX 256ul
335
SDH_Set_clock(SDH_T * sdh,uint32_t sd_clock_khz)336 void SDH_Set_clock(SDH_T *sdh, uint32_t sd_clock_khz)
337 {
338 uint32_t rate, div1;
339 static uint32_t u32SD_ClkSrc = 0ul, u32SD_PwrCtl = 0ul;
340
341 uint32_t u32RegLockLevel = SYS_IsRegLocked();
342 if (u32RegLockLevel)
343 {
344 SYS_UnlockReg();
345 }
346
347 /* initial state, clock source use HIRC */
348 if (sd_clock_khz <= 400ul)
349 {
350 u32SD_PwrCtl = CLK->PWRCTL;
351 if ((u32SD_PwrCtl & CLK_PWRCTL_HIRCEN_Msk) != 0x4ul)
352 {
353 CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
354 }
355
356 if (sdh == SDH0)
357 {
358 u32SD_ClkSrc = (CLK->CLKSEL0 & CLK_CLKSEL0_SDH0SEL_Msk);
359 CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_SDH0SEL_Msk) | CLK_CLKSEL0_SDH0SEL_HIRC;
360 _SDH0_ReferenceClock = (__HIRC / 1000ul);
361 }
362 else
363 {
364 u32SD_ClkSrc = (CLK->CLKSEL0 & CLK_CLKSEL0_SDH1SEL_Msk);
365 CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_SDH1SEL_Msk) | CLK_CLKSEL0_SDH1SEL_HIRC;
366 _SDH1_ReferenceClock = (__HIRC / 1000ul);
367 }
368 }
369 /* transfer state, clock source use sys_init() */
370 else
371 {
372 CLK->PWRCTL = u32SD_PwrCtl;
373 if (sdh == SDH0)
374 {
375 CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_SDH0SEL_Msk) | u32SD_ClkSrc;
376 if(u32SD_ClkSrc == CLK_CLKSEL0_SDH0SEL_HXT)
377 {
378 _SDH0_ReferenceClock = (CLK_GetHXTFreq() / 1000ul);
379 }
380 else if(u32SD_ClkSrc == CLK_CLKSEL0_SDH0SEL_HIRC)
381 {
382 _SDH0_ReferenceClock = (__HIRC / 1000ul);
383 }
384 else if(u32SD_ClkSrc == CLK_CLKSEL0_SDH0SEL_PLL_DIV2)
385 {
386 _SDH0_ReferenceClock = ((CLK_GetPLLClockFreq()>>1) / 1000ul);
387 }
388 else if(u32SD_ClkSrc == CLK_CLKSEL0_SDH0SEL_HCLK)
389 {
390 _SDH0_ReferenceClock = (CLK_GetHCLKFreq() / 1000ul);
391 }
392 }
393 else
394 {
395 CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_SDH1SEL_Msk) | u32SD_ClkSrc;
396 if(u32SD_ClkSrc == CLK_CLKSEL0_SDH1SEL_HXT)
397 {
398 _SDH1_ReferenceClock = (CLK_GetHXTFreq() / 1000ul);
399 }
400 else if(u32SD_ClkSrc == CLK_CLKSEL0_SDH1SEL_HIRC)
401 {
402 _SDH1_ReferenceClock = (__HIRC / 1000ul);
403 }
404 else if(u32SD_ClkSrc == CLK_CLKSEL0_SDH1SEL_PLL_DIV2)
405 {
406 _SDH1_ReferenceClock = ((CLK_GetPLLClockFreq()>>1) / 1000ul);
407 }
408 else if(u32SD_ClkSrc == CLK_CLKSEL0_SDH1SEL_HCLK)
409 {
410 _SDH1_ReferenceClock = (CLK_GetHCLKFreq() / 1000ul);
411 }
412 }
413
414 if(sd_clock_khz >= 50000ul)
415 {
416 sd_clock_khz = 50000ul;
417 }
418 }
419 if (sdh == SDH0)
420 {
421 rate = _SDH0_ReferenceClock / sd_clock_khz;
422
423 /* choose slower clock if system clock cannot divisible by wanted clock */
424 if ((_SDH0_ReferenceClock % sd_clock_khz) != 0ul)
425 {
426 rate++;
427 }
428 }
429 else
430 {
431 rate = _SDH1_ReferenceClock / sd_clock_khz;
432
433 /* choose slower clock if system clock cannot divisible by wanted clock */
434 if ((_SDH1_ReferenceClock % sd_clock_khz) != 0ul)
435 {
436 rate++;
437 }
438 }
439
440 if(rate >= SDH_CLK_DIV0_MAX)
441 {
442 rate = SDH_CLK_DIV0_MAX;
443 }
444
445 /*--- calculate the second divider CLKDIV0[SDHOST_N]*/
446 div1 = (rate - 1ul) & 0xFFul;
447
448 /*--- setup register */
449 if (sdh == SDH0)
450 {
451 CLK->CLKDIV0 &= ~CLK_CLKDIV0_SDH0DIV_Msk;
452 CLK->CLKDIV0 |= (div1 << CLK_CLKDIV0_SDH0DIV_Pos);
453 }
454 else
455 {
456 CLK->CLKDIV3 &= ~CLK_CLKDIV3_SDH1DIV_Msk;
457 CLK->CLKDIV3 |= (div1 << CLK_CLKDIV3_SDH1DIV_Pos);
458 }
459
460 if (u32RegLockLevel)
461 {
462 SYS_LockReg();
463 }
464
465 return;
466 }
467
SDH_CardDetection(SDH_T * sdh)468 uint32_t SDH_CardDetection(SDH_T *sdh)
469 {
470 uint32_t i, val = TRUE;
471 SDH_INFO_T *pSD;
472
473 if (sdh == SDH0)
474 {
475 pSD = &SD0;
476 }
477 else
478 {
479 pSD = &SD1;
480 }
481
482
483 if ((sdh->INTEN & SDH_INTEN_CDSRC_Msk) == SDH_INTEN_CDSRC_Msk) /* Card detect pin from GPIO */
484 {
485 if ((sdh->INTSTS & SDH_INTSTS_CDSTS_Msk) == SDH_INTSTS_CDSTS_Msk) /* Card remove */
486 {
487 pSD->IsCardInsert = (uint8_t)FALSE;
488 val = FALSE;
489 }
490 else
491 {
492 pSD->IsCardInsert = (uint8_t)TRUE;
493 }
494 }
495 else if ((sdh->INTEN & SDH_INTEN_CDSRC_Msk) != SDH_INTEN_CDSRC_Msk)
496 {
497 sdh->CTL |= SDH_CTL_CLKKEEP_Msk;
498 for(i= 0ul; i < 5000ul; i++)
499 {
500 }
501
502 if ((sdh->INTSTS & SDH_INTSTS_CDSTS_Msk) == SDH_INTSTS_CDSTS_Msk) /* Card insert */
503 {
504 pSD->IsCardInsert = (uint8_t)TRUE;
505 }
506 else
507 {
508 pSD->IsCardInsert = (uint8_t)FALSE;
509 val = FALSE;
510 }
511
512 sdh->CTL &= ~SDH_CTL_CLKKEEP_Msk;
513 }
514
515 return val;
516 }
517
SDH_Init(SDH_T * sdh)518 uint32_t SDH_Init(SDH_T *sdh)
519 {
520 uint32_t volatile i, status;
521 uint32_t resp;
522 uint32_t CIDBuffer[4];
523 uint32_t volatile u32CmdTimeOut;
524 SDH_INFO_T *pSD;
525 uint32_t u32TimeOutCount;
526
527 g_SDH_i32ErrCode = 0;
528
529 if (sdh == SDH0)
530 {
531 pSD = &SD0;
532 }
533 else
534 {
535 pSD = &SD1;
536 }
537
538 /* set the clock to 300KHz */
539 SDH_Set_clock(sdh, 300ul);
540
541 /* power ON 74 clock */
542 sdh->CTL |= SDH_CTL_CLK74OEN_Msk;
543
544 u32TimeOutCount = SDH_TIMEOUT_CNT;
545 while ((sdh->CTL & SDH_CTL_CLK74OEN_Msk) == SDH_CTL_CLK74OEN_Msk)
546 {
547 if (pSD->IsCardInsert == FALSE)
548 {
549 return SDH_NO_SD_CARD;
550 }
551 if(--u32TimeOutCount == 0)
552 {
553 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
554 break;
555 }
556 }
557
558 SDH_SDCommand(sdh, 0ul, 0ul); /* reset all cards */
559 for (i=0x1000ul; i>0ul; i--)
560 {
561 }
562
563 /* initial SDHC */
564 pSD->R7Flag = 1ul;
565 u32CmdTimeOut = 0xFFFFFul;
566
567 i = SDH_SDCmdAndRsp(sdh, 8ul, 0x00000155ul, u32CmdTimeOut);
568 if (i == Successful)
569 {
570 /* SD 2.0 */
571 SDH_SDCmdAndRsp(sdh, 55ul, 0x00ul, u32CmdTimeOut);
572 pSD->R3Flag = 1ul;
573 SDH_SDCmdAndRsp(sdh, 41ul, 0x40ff8000ul, u32CmdTimeOut); /* 2.7v-3.6v */
574 resp = sdh->RESP0;
575
576 u32TimeOutCount = SDH_TIMEOUT_CNT;
577 while ((resp & 0x00800000ul) != 0x00800000ul) /* check if card is ready */
578 {
579 SDH_SDCmdAndRsp(sdh, 55ul, 0x00ul, u32CmdTimeOut);
580 pSD->R3Flag = 1ul;
581 SDH_SDCmdAndRsp(sdh, 41ul, 0x40ff8000ul, u32CmdTimeOut); /* 3.0v-3.4v */
582 resp = sdh->RESP0;
583 if(--u32TimeOutCount == 0)
584 {
585 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
586 break;
587 }
588 }
589 if ((resp & 0x00400000ul) == 0x00400000ul)
590 {
591 pSD->CardType = SDH_TYPE_SD_HIGH;
592 }
593 else
594 {
595 pSD->CardType = SDH_TYPE_SD_LOW;
596 }
597 }
598 else
599 {
600 /* SD 1.1 */
601 SDH_SDCommand(sdh, 0ul, 0ul); /* reset all cards */
602 for (i=0x100ul; i>0ul; i--)
603 {
604 }
605
606 i = SDH_SDCmdAndRsp(sdh, 55ul, 0x00ul, u32CmdTimeOut);
607 if (i == 2ul) /* MMC memory */
608 {
609
610 SDH_SDCommand(sdh, 0ul, 0ul); /* reset */
611 for (i=0x100ul; i>0ul; i--)
612 {
613 }
614
615 pSD->R3Flag = 1ul;
616
617 if (SDH_SDCmdAndRsp(sdh, 1ul, 0x40ff8000ul, u32CmdTimeOut) != 2ul) /* eMMC memory */
618 {
619 resp = sdh->RESP0;
620 u32TimeOutCount = SDH_TIMEOUT_CNT;
621 while ((resp & 0x00800000ul) != 0x00800000ul)
622 {
623 /* check if card is ready */
624 pSD->R3Flag = 1ul;
625
626 SDH_SDCmdAndRsp(sdh, 1ul, 0x40ff8000ul, u32CmdTimeOut); /* high voltage */
627 resp = sdh->RESP0;
628
629 if(--u32TimeOutCount == 0)
630 {
631 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
632 break;
633 }
634 }
635
636 if ((resp & 0x00400000ul) == 0x00400000ul)
637 {
638 pSD->CardType = SDH_TYPE_EMMC;
639 }
640 else
641 {
642 pSD->CardType = SDH_TYPE_MMC;
643 }
644 }
645 else
646 {
647 pSD->CardType = SDH_TYPE_UNKNOWN;
648 return SDH_ERR_DEVICE;
649 }
650 }
651 else if (i == 0ul) /* SD Memory */
652 {
653 pSD->R3Flag = 1ul;
654 SDH_SDCmdAndRsp(sdh, 41ul, 0x00ff8000ul, u32CmdTimeOut); /* 3.0v-3.4v */
655 resp = sdh->RESP0;
656 u32TimeOutCount = SDH_TIMEOUT_CNT;
657 while ((resp & 0x00800000ul) != 0x00800000ul) /* check if card is ready */
658 {
659 SDH_SDCmdAndRsp(sdh, 55ul, 0x00ul, u32CmdTimeOut);
660 pSD->R3Flag = 1ul;
661 SDH_SDCmdAndRsp(sdh, 41ul, 0x00ff8000ul, u32CmdTimeOut); /* 3.0v-3.4v */
662 resp = sdh->RESP0;
663 if(--u32TimeOutCount == 0)
664 {
665 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
666 break;
667 }
668 }
669 pSD->CardType = SDH_TYPE_SD_LOW;
670 }
671 else
672 {
673 pSD->CardType = SDH_TYPE_UNKNOWN;
674 return SDH_INIT_ERROR;
675 }
676 }
677
678 if (pSD->CardType != SDH_TYPE_UNKNOWN)
679 {
680 SDH_SDCmdAndRsp2(sdh, 2ul, 0x00ul, CIDBuffer);
681 if ((pSD->CardType == SDH_TYPE_MMC) || (pSD->CardType == SDH_TYPE_EMMC))
682 {
683 if ((status = SDH_SDCmdAndRsp(sdh, 3ul, 0x10000ul, 0ul)) != Successful) /* set RCA */
684 {
685 return status;
686 }
687 pSD->RCA = 0x10000ul;
688 }
689 else
690 {
691 if ((status = SDH_SDCmdAndRsp(sdh, 3ul, 0x00ul, 0ul)) != Successful) /* get RCA */
692 {
693 return status;
694 }
695 else
696 {
697 pSD->RCA = (sdh->RESP0 << 8) & 0xffff0000;
698 }
699 }
700 }
701 return Successful;
702 }
703
704
SDH_SwitchToHighSpeed(SDH_T * sdh,SDH_INFO_T * pSD)705 uint32_t SDH_SwitchToHighSpeed(SDH_T *sdh, SDH_INFO_T *pSD)
706 {
707 uint32_t volatile status=0ul;
708 uint16_t current_comsumption, busy_status0;
709 uint32_t u32TimeOutCount = SDH_TIMEOUT_CNT;
710
711 g_SDH_i32ErrCode = 0;
712
713 sdh->DMASA = (uint32_t)pSD->dmabuf;
714 sdh->BLEN = 63ul;
715
716 if ((status = SDH_SDCmdAndRspDataIn(sdh, 6ul, 0x00ffff01ul)) != Successful)
717 {
718 return Fail;
719 }
720
721 current_comsumption = (uint16_t)(*pSD->dmabuf) << 8;
722 current_comsumption |= (uint16_t)(*(pSD->dmabuf + 1));
723 if (!current_comsumption)
724 {
725 return Fail;
726 }
727
728 busy_status0 = (uint16_t)(*(pSD->dmabuf + 28)) << 8;
729 busy_status0 |= (uint16_t)(*(pSD->dmabuf + 29));
730
731 if (!busy_status0) /* function ready */
732 {
733 sdh->DMASA = (uint32_t)pSD->dmabuf;
734 sdh->BLEN = 63ul; /* 512 bit */
735
736 if ((status = SDH_SDCmdAndRspDataIn(sdh, 6ul, 0x80ffff01ul)) != Successful)
737 {
738 return Fail;
739 }
740
741 /* function change timing: 8 clocks */
742 sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
743 while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk)
744 {
745 if(--u32TimeOutCount == 0)
746 {
747 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
748 break;
749 }
750 }
751
752 current_comsumption = (uint16_t)(*pSD->dmabuf) << 8;
753 current_comsumption |= (uint16_t)(*(pSD->dmabuf + 1));
754 if (!current_comsumption)
755 {
756 return Fail;
757 }
758
759 return Successful;
760 }
761 else
762 {
763 return Fail;
764 }
765 }
766
767
SDH_SelectCardType(SDH_T * sdh)768 uint32_t SDH_SelectCardType(SDH_T *sdh)
769 {
770 uint32_t volatile status=0ul;
771 uint32_t param;
772 SDH_INFO_T *pSD;
773 uint32_t u32TimeOutCount;
774
775 g_SDH_i32ErrCode = 0;
776
777 if (sdh == SDH0)
778 {
779 pSD = &SD0;
780 }
781 else
782 {
783 pSD = &SD1;
784 }
785
786 if ((status = SDH_SDCmdAndRsp(sdh, 7ul, pSD->RCA, 0ul)) != Successful)
787 {
788 return status;
789 }
790
791 SDH_CheckRB(sdh);
792
793 /* if SD card set 4bit */
794 if (pSD->CardType == SDH_TYPE_SD_HIGH)
795 {
796 sdh->DMASA = (uint32_t)pSD->dmabuf;
797 sdh->BLEN = 0x07ul; /* 64 bit */
798 sdh->DMACTL |= SDH_DMACTL_DMARST_Msk;
799 u32TimeOutCount = SDH_TIMEOUT_CNT;
800 while ((sdh->DMACTL & SDH_DMACTL_DMARST_Msk) == 0x2)
801 {
802 if(--u32TimeOutCount == 0)
803 {
804 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
805 break;
806 }
807 }
808
809 if ((status = SDH_SDCmdAndRsp(sdh, 55ul, pSD->RCA, 0ul)) != Successful)
810 {
811 return status;
812 }
813 if ((status = SDH_SDCmdAndRspDataIn(sdh, 51ul, 0x00ul)) != Successful)
814 {
815 return status;
816 }
817
818 if ((*pSD->dmabuf & 0xful) == 0x2ul)
819 {
820 status = SDH_SwitchToHighSpeed(sdh, pSD);
821 if (status == Successful)
822 {
823 /* divider */
824 SDH_Set_clock(sdh, SDHC_FREQ);
825 }
826 }
827
828 if ((status = SDH_SDCmdAndRsp(sdh, 55ul, pSD->RCA, 0ul)) != Successful)
829 {
830 return status;
831 }
832 if ((status = SDH_SDCmdAndRsp(sdh, 6ul, 0x02ul, 0ul)) != Successful) /* set bus width */
833 {
834 return status;
835 }
836
837 sdh->CTL |= SDH_CTL_DBW_Msk;
838 }
839 else if (pSD->CardType == SDH_TYPE_SD_LOW)
840 {
841 sdh->DMASA = (uint32_t)pSD->dmabuf;;
842 sdh->BLEN = 0x07ul;
843
844 if ((status = SDH_SDCmdAndRsp(sdh, 55ul, pSD->RCA, 0ul)) != Successful)
845 {
846 return status;
847 }
848 if ((status = SDH_SDCmdAndRspDataIn(sdh, 51ul, 0x00ul)) != Successful)
849 {
850 return status;
851 }
852
853 /* set data bus width. ACMD6 for SD card, SDCR_DBW for host. */
854 if ((status = SDH_SDCmdAndRsp(sdh, 55ul, pSD->RCA, 0ul)) != Successful)
855 {
856 return status;
857 }
858
859 if ((status = SDH_SDCmdAndRsp(sdh, 6ul, 0x02ul, 0ul)) != Successful)
860 {
861 return status;
862 }
863
864 sdh->CTL |= SDH_CTL_DBW_Msk;
865 }
866 else if ((pSD->CardType == SDH_TYPE_MMC) ||(pSD->CardType == SDH_TYPE_EMMC))
867 {
868
869 if(pSD->CardType == SDH_TYPE_MMC)
870 {
871 sdh->CTL &= ~SDH_CTL_DBW_Msk;
872 }
873
874 /*--- sent CMD6 to MMC card to set bus width to 4 bits mode */
875 /* set CMD6 argument Access field to 3, Index to 183, Value to 1 (4-bit mode) */
876 param = (3ul << 24) | (183ul << 16) | (1ul << 8);
877 if ((status = SDH_SDCmdAndRsp(sdh, 6ul, param, 0ul)) != Successful)
878 {
879 return status;
880 }
881 SDH_CheckRB(sdh);
882
883 sdh->CTL |= SDH_CTL_DBW_Msk; /* set bus width to 4-bit mode for SD host controller */
884
885 }
886
887 if ((status = SDH_SDCmdAndRsp(sdh, 16ul, SDH_BLOCK_SIZE, 0ul)) != Successful)
888 {
889 return status;
890 }
891 sdh->BLEN = SDH_BLOCK_SIZE - 1ul;
892
893 SDH_SDCommand(sdh, 7ul, 0ul);
894 sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
895 u32TimeOutCount = SDH_TIMEOUT_CNT;
896 while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk)
897 {
898 if(--u32TimeOutCount == 0)
899 {
900 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
901 break;
902 }
903 }
904
905 sdh->INTEN |= SDH_INTEN_BLKDIEN_Msk;
906
907 return Successful;
908 }
909
SDH_Get_SD_info(SDH_T * sdh)910 void SDH_Get_SD_info(SDH_T *sdh)
911 {
912 unsigned int R_LEN, C_Size, MULT, size;
913 uint32_t Buffer[4];
914 //unsigned char *ptr;
915 SDH_INFO_T *pSD;
916 uint32_t u32TimeOutCount = SDH_TIMEOUT_CNT;
917
918 g_SDH_i32ErrCode = 0;
919
920 if (sdh == SDH0)
921 {
922 pSD = &SD0;
923 }
924 else
925 {
926 pSD = &SD1;
927 }
928
929 SDH_SDCmdAndRsp2(sdh, 9ul, pSD->RCA, Buffer);
930
931 if ((pSD->CardType == SDH_TYPE_MMC) || (pSD->CardType == SDH_TYPE_EMMC))
932 {
933 /* for MMC/eMMC card */
934 if ((Buffer[0] & 0xc0000000) == 0xc0000000)
935 {
936 /* CSD_STRUCTURE [127:126] is 3 */
937 /* CSD version depend on EXT_CSD register in eMMC v4.4 for card size > 2GB */
938 SDH_SDCmdAndRsp(sdh, 7ul, pSD->RCA, 0ul);
939
940 //ptr = (uint8_t *)((uint32_t)_SDH_ucSDHCBuffer );
941 sdh->DMASA = (uint32_t)pSD->dmabuf;;
942 sdh->BLEN = 511ul; /* read 512 bytes for EXT_CSD */
943
944 if (SDH_SDCmdAndRspDataIn(sdh, 8ul, 0x00ul) == Successful)
945 {
946 SDH_SDCommand(sdh, 7ul, 0ul);
947 sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
948 while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk)
949 {
950 if(--u32TimeOutCount == 0)
951 {
952 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
953 break;
954 }
955 }
956
957 pSD->totalSectorN = (uint32_t)(*(pSD->dmabuf+215))<<24;
958 pSD->totalSectorN |= (uint32_t)(*(pSD->dmabuf+214))<<16;
959 pSD->totalSectorN |= (uint32_t)(*(pSD->dmabuf+213))<<8;
960 pSD->totalSectorN |= (uint32_t)(*(pSD->dmabuf+212));
961 pSD->diskSize = pSD->totalSectorN / 2ul;
962 }
963 }
964 else
965 {
966 /* CSD version v1.0/1.1/1.2 in eMMC v4.4 spec for card size <= 2GB */
967 R_LEN = (Buffer[1] & 0x000f0000ul) >> 16;
968 C_Size = ((Buffer[1] & 0x000003fful) << 2) | ((Buffer[2] & 0xc0000000ul) >> 30);
969 MULT = (Buffer[2] & 0x00038000ul) >> 15;
970 size = (C_Size+1ul) * (1ul<<(MULT+2ul)) * (1ul<<R_LEN);
971
972 pSD->diskSize = size / 1024ul;
973 pSD->totalSectorN = size / 512ul;
974 }
975 }
976 else
977 {
978 if ((Buffer[0] & 0xc0000000) != 0x0ul)
979 {
980 C_Size = ((Buffer[1] & 0x0000003ful) << 16) | ((Buffer[2] & 0xffff0000ul) >> 16);
981 size = (C_Size+1ul) * 512ul; /* Kbytes */
982
983 pSD->diskSize = size;
984 pSD->totalSectorN = size << 1;
985 }
986 else
987 {
988 R_LEN = (Buffer[1] & 0x000f0000ul) >> 16;
989 C_Size = ((Buffer[1] & 0x000003fful) << 2) | ((Buffer[2] & 0xc0000000ul) >> 30);
990 MULT = (Buffer[2] & 0x00038000ul) >> 15;
991 size = (C_Size+1ul) * (1ul<<(MULT+2ul)) * (1ul<<R_LEN);
992
993 pSD->diskSize = size / 1024ul;
994 pSD->totalSectorN = size / 512ul;
995 }
996 }
997 pSD->sectorSize = (int)512;
998 }
999
1000 /** @endcond HIDDEN_SYMBOLS */
1001
1002
1003 /**
1004 * @brief This function use to reset SD function and select card detection source and pin.
1005 *
1006 * @param[in] sdh Select SDH0 or SDH1.
1007 * @param[in] u32CardDetSrc Select card detection pin from GPIO or DAT3 pin. ( \ref CardDetect_From_GPIO / \ref CardDetect_From_DAT3)
1008 *
1009 * @return None
1010 */
SDH_Open(SDH_T * sdh,uint32_t u32CardDetSrc)1011 void SDH_Open(SDH_T *sdh, uint32_t u32CardDetSrc)
1012 {
1013 uint32_t u32TimeOutCount;
1014
1015 g_SDH_i32ErrCode = 0;
1016
1017 sdh->DMACTL = SDH_DMACTL_DMARST_Msk;
1018 u32TimeOutCount = SDH_TIMEOUT_CNT;
1019 while ((sdh->DMACTL & SDH_DMACTL_DMARST_Msk) == SDH_DMACTL_DMARST_Msk)
1020 {
1021 if(--u32TimeOutCount == 0)
1022 {
1023 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
1024 break;
1025 }
1026 }
1027
1028 sdh->DMACTL = SDH_DMACTL_DMAEN_Msk;
1029
1030 sdh->GCTL = SDH_GCTL_GCTLRST_Msk | SDH_GCTL_SDEN_Msk;
1031 u32TimeOutCount = SDH_TIMEOUT_CNT;
1032 while ((sdh->GCTL & SDH_GCTL_GCTLRST_Msk) == SDH_GCTL_GCTLRST_Msk)
1033 {
1034 if(--u32TimeOutCount == 0)
1035 {
1036 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
1037 break;
1038 }
1039 }
1040
1041 if (sdh == SDH0)
1042 {
1043 NVIC_EnableIRQ(SDH0_IRQn);
1044 memset(&SD0, 0, sizeof(SDH_INFO_T));
1045 SD0.dmabuf = _SDH0_ucSDHCBuffer;
1046 }
1047 else if (sdh == SDH1)
1048 {
1049 NVIC_EnableIRQ(SDH1_IRQn);
1050 memset(&SD1, 0, sizeof(SDH_INFO_T));
1051 SD1.dmabuf = _SDH1_ucSDHCBuffer;
1052 }
1053 else
1054 {
1055 }
1056
1057 sdh->GCTL = SDH_GCTL_SDEN_Msk;
1058
1059 if ((u32CardDetSrc & CardDetect_From_DAT3) == CardDetect_From_DAT3)
1060 {
1061 sdh->INTEN &= ~SDH_INTEN_CDSRC_Msk;
1062 }
1063 else
1064 {
1065 sdh->INTEN |= SDH_INTEN_CDSRC_Msk;
1066 }
1067 sdh->INTEN |= SDH_INTEN_CDIEN_Msk;
1068
1069 sdh->CTL |= SDH_CTL_CTLRST_Msk;
1070 u32TimeOutCount = SDH_TIMEOUT_CNT;
1071 while ((sdh->CTL & SDH_CTL_CTLRST_Msk) == SDH_CTL_CTLRST_Msk)
1072 {
1073 if(--u32TimeOutCount == 0)
1074 {
1075 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
1076 break;
1077 }
1078 }
1079 }
1080
1081 /**
1082 * @brief This function use to initial SD card.
1083 *
1084 * @param[in] sdh Select SDH0 or SDH1.
1085 *
1086 * @return None
1087 *
1088 * @details This function is used to initial SD card.
1089 * SD initial state needs 400KHz clock output, driver will use HIRC for SD initial clock source.
1090 * And then switch back to the user's setting.
1091 */
SDH_Probe(SDH_T * sdh)1092 uint32_t SDH_Probe(SDH_T *sdh)
1093 {
1094 uint32_t val;
1095
1096 sdh->GINTEN = 0ul;
1097 sdh->CTL &= ~SDH_CTL_SDNWR_Msk;
1098 sdh->CTL |= 0x09ul << SDH_CTL_SDNWR_Pos; /* set SDNWR = 9 */
1099 sdh->CTL &= ~SDH_CTL_BLKCNT_Msk;
1100 sdh->CTL |= 0x01ul << SDH_CTL_BLKCNT_Pos; /* set BLKCNT = 1 */
1101 sdh->CTL &= ~SDH_CTL_DBW_Msk; /* SD 1-bit data bus */
1102
1103 if(!(SDH_CardDetection(sdh)))
1104 {
1105 return SDH_NO_SD_CARD;
1106 }
1107
1108 if ((val = SDH_Init(sdh)) != 0ul)
1109 {
1110 return val;
1111 }
1112
1113 /* divider */
1114 if ((SD0.CardType == SDH_TYPE_MMC) || (SD1.CardType == SDH_TYPE_MMC))
1115 {
1116 SDH_Set_clock(sdh, MMC_FREQ);
1117 }
1118 else
1119 {
1120 SDH_Set_clock(sdh, SD_FREQ);
1121 }
1122 SDH_Get_SD_info(sdh);
1123
1124 if ((val = SDH_SelectCardType(sdh)) != 0ul)
1125 {
1126 return val;
1127 }
1128
1129 return 0ul;
1130 }
1131
1132 /**
1133 * @brief This function use to read data from SD card.
1134 *
1135 * @param[in] sdh Select SDH0 or SDH1.
1136 * @param[out] pu8BufAddr The buffer to receive the data from SD card.
1137 * @param[in] u32StartSec The start read sector address.
1138 * @param[in] u32SecCount The the read sector number of data
1139 *
1140 * @return None
1141 */
SDH_Read(SDH_T * sdh,uint8_t * pu8BufAddr,uint32_t u32StartSec,uint32_t u32SecCount)1142 uint32_t SDH_Read(SDH_T *sdh, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount)
1143 {
1144 uint32_t volatile bIsSendCmd = FALSE, buf;
1145 uint32_t volatile reg;
1146 uint32_t volatile i, loop, status;
1147 uint32_t blksize = SDH_BLOCK_SIZE;
1148 uint32_t u32TimeOutCount;
1149
1150 SDH_INFO_T *pSD;
1151
1152 g_SDH_i32ErrCode = 0;
1153
1154 if (sdh == SDH0)
1155 {
1156 pSD = &SD0;
1157 }
1158 else
1159 {
1160 pSD = &SD1;
1161 }
1162
1163 if (u32SecCount == 0ul)
1164 {
1165 return SDH_SELECT_ERROR;
1166 }
1167
1168 if ((status = SDH_SDCmdAndRsp(sdh, 7ul, pSD->RCA, 0ul)) != Successful)
1169 {
1170 return status;
1171 }
1172 SDH_CheckRB(sdh);
1173
1174 sdh->BLEN = blksize - 1ul; /* the actual byte count is equal to (SDBLEN+1) */
1175
1176 if ( (pSD->CardType == SDH_TYPE_SD_HIGH) || (pSD->CardType == SDH_TYPE_EMMC) )
1177 {
1178 sdh->CMDARG = u32StartSec;
1179 }
1180 else
1181 {
1182 sdh->CMDARG = u32StartSec * blksize;
1183 }
1184
1185 sdh->DMASA = (uint32_t)pu8BufAddr;
1186
1187 loop = u32SecCount / 255ul;
1188 for (i=0ul; i<loop; i++)
1189 {
1190 pSD->DataReadyFlag = (uint8_t)FALSE;
1191 reg = sdh->CTL & ~SDH_CTL_CMDCODE_Msk;
1192 reg = reg | 0xff0000ul; /* set BLK_CNT to 255 */
1193 if (bIsSendCmd == FALSE)
1194 {
1195 sdh->CTL = reg|(18ul << 8)|(SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk);
1196 bIsSendCmd = TRUE;
1197 }
1198 else
1199 {
1200 sdh->CTL = reg | SDH_CTL_DIEN_Msk;
1201 }
1202
1203 u32TimeOutCount = SDH_TIMEOUT_CNT;
1204 while(!pSD->DataReadyFlag)
1205 {
1206 if(pSD->DataReadyFlag)
1207 {
1208 break;
1209 }
1210 if (pSD->IsCardInsert == FALSE)
1211 {
1212 return SDH_NO_SD_CARD;
1213 }
1214 if(--u32TimeOutCount == 0)
1215 {
1216 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
1217 break;
1218 }
1219 }
1220
1221 if ((sdh->INTSTS & SDH_INTSTS_CRC7_Msk) != SDH_INTSTS_CRC7_Msk) /* check CRC7 */
1222 {
1223 return SDH_CRC7_ERROR;
1224 }
1225
1226 if ((sdh->INTSTS & SDH_INTSTS_CRC16_Msk) != SDH_INTSTS_CRC16_Msk) /* check CRC16 */
1227 {
1228 return SDH_CRC16_ERROR;
1229 }
1230 }
1231
1232 loop = u32SecCount % 255ul;
1233 if (loop != 0ul)
1234 {
1235 pSD->DataReadyFlag = (uint8_t)FALSE;
1236 reg = sdh->CTL & (~SDH_CTL_CMDCODE_Msk);
1237 reg = reg & (~SDH_CTL_BLKCNT_Msk);
1238 reg |= (loop << 16); /* setup SDCR_BLKCNT */
1239
1240 if (bIsSendCmd == FALSE)
1241 {
1242 sdh->CTL = reg|(18ul << 8)|(SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk);
1243 bIsSendCmd = TRUE;
1244 }
1245 else
1246 {
1247 sdh->CTL = reg | SDH_CTL_DIEN_Msk;
1248 }
1249
1250 u32TimeOutCount = SDH_TIMEOUT_CNT;
1251 while(!pSD->DataReadyFlag)
1252 {
1253 if (pSD->IsCardInsert == FALSE)
1254 {
1255 return SDH_NO_SD_CARD;
1256 }
1257 if(--u32TimeOutCount == 0)
1258 {
1259 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
1260 break;
1261 }
1262 }
1263
1264 if ((sdh->INTSTS & SDH_INTSTS_CRC7_Msk) != SDH_INTSTS_CRC7_Msk) /* check CRC7 */
1265 {
1266 return SDH_CRC7_ERROR;
1267 }
1268
1269 if ((sdh->INTSTS & SDH_INTSTS_CRC16_Msk) != SDH_INTSTS_CRC16_Msk) /* check CRC16 */
1270 {
1271 return SDH_CRC16_ERROR;
1272 }
1273 }
1274
1275 if (SDH_SDCmdAndRsp(sdh, 12ul, 0ul, 0ul)) /* stop command */
1276 {
1277 return SDH_CRC7_ERROR;
1278 }
1279 SDH_CheckRB(sdh);
1280
1281 SDH_SDCommand(sdh, 7ul, 0ul);
1282 sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
1283 u32TimeOutCount = SDH_TIMEOUT_CNT;
1284 while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk)
1285 {
1286 if(--u32TimeOutCount == 0)
1287 {
1288 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
1289 break;
1290 }
1291 }
1292
1293 return Successful;
1294 }
1295
1296
1297 /**
1298 * @brief This function use to write data to SD card.
1299 *
1300 * @param[in] sdh Select SDH0 or SDH1.
1301 * @param[in] pu8BufAddr The buffer to send the data to SD card.
1302 * @param[in] u32StartSec The start write sector address.
1303 * @param[in] u32SecCount The the write sector number of data.
1304 *
1305 * @return \ref SDH_SELECT_ERROR : u32SecCount is zero. \n
1306 * \ref SDH_NO_SD_CARD : SD card be removed. \n
1307 * \ref SDH_CRC_ERROR : CRC error happen. \n
1308 * \ref SDH_CRC7_ERROR : CRC7 error happen. \n
1309 * \ref Successful : Write data to SD card success.
1310 */
SDH_Write(SDH_T * sdh,uint8_t * pu8BufAddr,uint32_t u32StartSec,uint32_t u32SecCount)1311 uint32_t SDH_Write(SDH_T *sdh, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount)
1312 {
1313 uint32_t volatile bIsSendCmd = FALSE;
1314 uint32_t volatile reg;
1315 uint32_t volatile i, loop, status;
1316 uint32_t u32TimeOutCount;
1317
1318 SDH_INFO_T *pSD;
1319
1320 g_SDH_i32ErrCode = 0;
1321
1322 if (sdh == SDH0)
1323 {
1324 pSD = &SD0;
1325 }
1326 else
1327 {
1328 pSD = &SD1;
1329 }
1330
1331 if (u32SecCount == 0ul)
1332 {
1333 return SDH_SELECT_ERROR;
1334 }
1335
1336 if ((status = SDH_SDCmdAndRsp(sdh, 7ul, pSD->RCA, 0ul)) != Successful)
1337 {
1338 return status;
1339 }
1340
1341 SDH_CheckRB(sdh);
1342
1343 /* According to SD Spec v2.0, the write CMD block size MUST be 512, and the start address MUST be 512*n. */
1344 sdh->BLEN = SDH_BLOCK_SIZE - 1ul;
1345
1346 if ((pSD->CardType == SDH_TYPE_SD_HIGH) || (pSD->CardType == SDH_TYPE_EMMC))
1347 {
1348 sdh->CMDARG = u32StartSec;
1349 }
1350 else
1351 {
1352 sdh->CMDARG = u32StartSec * SDH_BLOCK_SIZE; /* set start address for SD CMD */
1353 }
1354
1355 sdh->DMASA = (uint32_t)pu8BufAddr;
1356 loop = u32SecCount / 255ul; /* the maximum block count is 0xFF=255 for register SDCR[BLK_CNT] */
1357 for (i=0ul; i<loop; i++)
1358 {
1359 pSD->DataReadyFlag = (uint8_t)FALSE;
1360 reg = sdh->CTL & 0xff00c080;
1361 reg = reg | 0xff0000ul; /* set BLK_CNT to 0xFF=255 */
1362 if (!bIsSendCmd)
1363 {
1364 sdh->CTL = reg|(25ul << 8)|(SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DOEN_Msk);
1365 bIsSendCmd = TRUE;
1366 }
1367 else
1368 {
1369 sdh->CTL = reg | SDH_CTL_DOEN_Msk;
1370 }
1371
1372 u32TimeOutCount = SDH_TIMEOUT_CNT;
1373 while(!pSD->DataReadyFlag)
1374 {
1375 if (pSD->IsCardInsert == FALSE)
1376 {
1377 return SDH_NO_SD_CARD;
1378 }
1379 if(--u32TimeOutCount == 0)
1380 {
1381 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
1382 break;
1383 }
1384 }
1385
1386 if ((sdh->INTSTS & SDH_INTSTS_CRCIF_Msk) != 0ul)
1387 {
1388 sdh->INTSTS = SDH_INTSTS_CRCIF_Msk;
1389 return SDH_CRC_ERROR;
1390 }
1391 }
1392
1393 loop = u32SecCount % 255ul;
1394 if (loop != 0ul)
1395 {
1396 pSD->DataReadyFlag = (uint8_t)FALSE;
1397 reg = (sdh->CTL & 0xff00c080) | (loop << 16);
1398 if (!bIsSendCmd)
1399 {
1400 sdh->CTL = reg|(25ul << 8)|(SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DOEN_Msk);
1401 bIsSendCmd = TRUE;
1402 }
1403 else
1404 {
1405 sdh->CTL = reg | SDH_CTL_DOEN_Msk;
1406 }
1407
1408 u32TimeOutCount = SDH_TIMEOUT_CNT;
1409 while(!pSD->DataReadyFlag)
1410 {
1411 if (pSD->IsCardInsert == FALSE)
1412 {
1413 return SDH_NO_SD_CARD;
1414 }
1415 if(--u32TimeOutCount == 0)
1416 {
1417 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
1418 break;
1419 }
1420 }
1421
1422 if ((sdh->INTSTS & SDH_INTSTS_CRCIF_Msk) != 0ul)
1423 {
1424 sdh->INTSTS = SDH_INTSTS_CRCIF_Msk;
1425 return SDH_CRC_ERROR;
1426 }
1427 }
1428 sdh->INTSTS = SDH_INTSTS_CRCIF_Msk;
1429
1430 if (SDH_SDCmdAndRsp(sdh, 12ul, 0ul, 0ul)) /* stop command */
1431 {
1432 return SDH_CRC7_ERROR;
1433 }
1434 SDH_CheckRB(sdh);
1435
1436 SDH_SDCommand(sdh, 7ul, 0ul);
1437 sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
1438 u32TimeOutCount = SDH_TIMEOUT_CNT;
1439 while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk)
1440 {
1441 if(--u32TimeOutCount == 0)
1442 {
1443 g_SDH_i32ErrCode = SDH_ERR_TIMEOUT;
1444 break;
1445 }
1446 }
1447
1448 return Successful;
1449 }
1450
1451 /*@}*/ /* end of group SDH_EXPORTED_FUNCTIONS */
1452
1453 /*@}*/ /* end of group SDH_Driver */
1454
1455 /*@}*/ /* end of group Standard_Driver */
1456