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