NUC472_NUC442_BSP V3.03.005
The Board Support Package for NUC472/NUC442
sd.c
Go to the documentation of this file.
1/**************************************************************************/
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include "NUC472_442.h"
16
29#define SD_BLOCK_SIZE 512
30
32
33// global variables
34// For response R3 (such as ACMD41, CRC-7 is invalid; but SD controller will still
35// calculate CRC-7 and get an error result, software should ignore this error and clear SDISR [CRC_IF] flag
36// _sd_uR3_CMD is the flag for it. 1 means software should ignore CRC-7 error
37uint32_t _sd_uR3_CMD=0;
38uint32_t _sd_uR7_CMD=0;
39uint8_t volatile _sd_SDDataReady = FALSE;
40
41uint8_t *_sd_pSDHCBuffer;
42uint32_t _sd_ReferenceClock;
43
44#ifdef __ICCARM__
45#pragma data_alignment = 4
46static uint8_t _sd_ucSDHCBuffer[512];
47#else
48static uint8_t _sd_ucSDHCBuffer[512] __attribute__((aligned(4)));
49#endif
50
51int sd0_ok = 0;
52int sd1_ok = 0;
53
54uint8_t pSD0_offset = 0;
55uint8_t pSD1_offset = 0;
56
57DISK_DATA_T SD_DiskInfo0;
58DISK_DATA_T SD_DiskInfo1;
59
60SD_INFO_T SD0;
61SD_INFO_T SD1;
62
63uint32_t SD_CheckRB()
64{
65 while(1)
66 {
67 SD->CTL |= SDH_CTL_CLK8OEN_Msk;
68 while(SD->CTL & SDH_CTL_CLK8OEN_Msk);
69 if (SD->INTSTS & SDH_INTSTS_DAT0STS_Msk)
70 return 0;
71 if (SD0.IsCardInsert == FALSE)
72 {
73 return SD_NO_SD_CARD;
74 }
75 }
76}
77
78
79int SD_SDCommand(SD_INFO_T *pSD, uint8_t ucCmd, uint32_t uArg)
80{
81 volatile int buf;
82
83 SD->CMDARG = uArg;
84 buf = (SD->CTL&(~SDH_CTL_CMDCODE_Msk))|(ucCmd << 8)|(SDH_CTL_COEN_Msk);
85 SD->CTL = buf;
86
87 while(SD->CTL & SDH_CTL_COEN_Msk)
88 {
89 if (pSD->IsCardInsert == FALSE)
90 return SD_NO_SD_CARD;
91 }
92 return Successful;
93}
94
95
96int SD_SDCmdAndRsp(SD_INFO_T *pSD, uint8_t ucCmd, uint32_t uArg, int ntickCount)
97{
98 volatile int buf;
99
100 SD->CMDARG = uArg;
101 buf = (SD->CTL&(~SDH_CTL_CMDCODE_Msk))|(ucCmd << 8)|(SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk);
102 SD->CTL = buf;
103
104 if (ntickCount > 0)
105 {
106 while(SD->CTL & SDH_CTL_RIEN_Msk)
107 {
108 if(ntickCount-- == 0)
109 {
110 SD->CTL |= SDH_CTL_CTLRST_Msk; // reset SD engine
111 return 2;
112 }
113 if (pSD->IsCardInsert == FALSE)
114 return SD_NO_SD_CARD;
115 if (SD->INTSTS & SDH_INTSTS_CDSTS0_Msk)
116 {
117 return SD_NO_SD_CARD;
118 }
119 }
120 }
121 else
122 {
123 while(SD->CTL & SDH_CTL_RIEN_Msk)
124 {
125 if (pSD->IsCardInsert == FALSE)
126 return SD_NO_SD_CARD;
127 if (SD->INTSTS & SDH_INTSTS_CDSTS0_Msk)
128 {
129 return SD_NO_SD_CARD;
130 }
131 }
132 }
133
134 if (_sd_uR7_CMD)
135 {
136 if (((SD->RESP1 & 0xff) != 0x55) && ((SD->RESP0 & 0xf) != 0x01))
137 {
138 _sd_uR7_CMD = 0;
139 return SD_CMD8_ERROR;
140 }
141 }
142
143 if (!_sd_uR3_CMD)
144 {
145 if (SD->INTSTS & SDH_INTSTS_CRC7_Msk) // check CRC7
146 return Successful;
147 else
148 {
149 return SD_CRC7_ERROR;
150 }
151 }
152 else // ignore CRC error for R3 case
153 {
154 _sd_uR3_CMD = 0;
155 SD->INTSTS = SDH_INTSTS_CRCIF_Msk;
156 return Successful;
157 }
158}
159
160
161int SD_Swap32(int val)
162{
163#if 1
164 int buf;
165
166 buf = val;
167 val <<= 24;
168 val |= (buf<<8)&0xff0000;
169 val |= (buf>>8)&0xff00;
170 val |= (buf>>24)&0xff;
171 return val;
172
173#else
174 return ((val<<24) | ((val<<8)&0xff0000) | ((val>>8)&0xff00) | (val>>24));
175#endif
176}
177
178// Get 16 bytes CID or CSD
179int SD_SDCmdAndRsp2(SD_INFO_T *pSD, uint8_t ucCmd, uint32_t uArg, uint32_t *puR2ptr)
180{
181 unsigned int i, buf;
182 unsigned int tmpBuf[5];
183
184 SD->CMDARG = uArg;
185 buf = (SD->CTL&(~SDH_CTL_CMDCODE_Msk))|(ucCmd << 8)|(SDH_CTL_COEN_Msk | SDH_CTL_R2EN_Msk);
186 SD->CTL = buf;
187
188 while(SD->CTL & SDH_CTL_R2EN_Msk)
189 {
190 if (pSD->IsCardInsert == FALSE)
191 return SD_NO_SD_CARD;
192 if (SD->INTSTS & SDH_INTSTS_CDSTS0_Msk)
193 {
194 return SD_NO_SD_CARD;
195 }
196 }
197
198 if (SD->INTSTS & SDH_INTSTS_CRC7_Msk)
199 {
200 for (i=0; i<5; i++)
201 {
202 tmpBuf[i] = SD_Swap32(*(int*)(SD_BASE+i*4));
203 }
204 for (i=0; i<4; i++)
205 *puR2ptr++ = ((tmpBuf[i] & 0x00ffffff)<<8) | ((tmpBuf[i+1] & 0xff000000)>>24);
206 return Successful;
207 }
208 else
209 return SD_CRC7_ERROR;
210}
211
212
213int SD_SDCmdAndRspDataIn(SD_INFO_T *pSD, uint8_t ucCmd, uint32_t uArg)
214{
215 volatile int buf;
216
217 SD->CMDARG = uArg;
218 buf = (SD->CTL&(~SDH_CTL_CMDCODE_Msk))|(ucCmd << 8)|
220
221 SD->CTL = buf;
222
223 while (SD->CTL & SDH_CTL_RIEN_Msk)
224 {
225 if (pSD->IsCardInsert == FALSE)
226 return SD_NO_SD_CARD;
227 if (SD->INTSTS & SDH_INTSTS_CDSTS0_Msk)
228 {
229 return SD_NO_SD_CARD;
230 }
231 }
232
233 while (SD->CTL & SDH_CTL_DIEN_Msk)
234 {
235 if (pSD->IsCardInsert == FALSE)
236 return SD_NO_SD_CARD;
237 if (SD->INTSTS & SDH_INTSTS_CDSTS0_Msk)
238 {
239 return SD_NO_SD_CARD;
240 }
241 }
242
243 if (!(SD->INTSTS & SDH_INTSTS_CRC7_Msk)) // check CRC7
244 {
245 return SD_CRC7_ERROR;
246 }
247
248 if (!(SD->INTSTS & SDH_INTSTS_CRC16_Msk)) // check CRC16
249 {
250 return SD_CRC16_ERROR;
251 }
252 return Successful;
253}
254
255// there are 8 bits for divider0, maximum is 256
256#define SD_CLK_DIV0_MAX 256
257
258void SD_Set_clock(uint32_t sd_clock_khz)
259{
260 uint32_t rate, div1, i;
261 uint32_t u32SD_ClkSrc;
262
263 if(sd_clock_khz >= 24000)
264 {
265 sd_clock_khz = 24000;
266 }
267
268 u32SD_ClkSrc = (CLK->CLKSEL0 & CLK_CLKSEL0_SDHSEL_Msk);
269
270 if(u32SD_ClkSrc == CLK_CLKSEL0_SDHSEL_HXT)
271 _sd_ReferenceClock = (CLK_GetHXTFreq() / 1000);
272 else if(u32SD_ClkSrc == CLK_CLKSEL0_SDHSEL_HIRC)
273 _sd_ReferenceClock = (__HIRC / 1000);
274 else if(u32SD_ClkSrc == CLK_CLKSEL0_SDHSEL_PLL)
275 _sd_ReferenceClock = (CLK_GetPLLClockFreq() / 1000);
276 else if(u32SD_ClkSrc == CLK_CLKSEL0_SDHSEL_HCLK)
277 _sd_ReferenceClock = (CLK_GetHCLKFreq() / 1000);
278
279 rate = _sd_ReferenceClock / sd_clock_khz;
280
281 // choose slower clock if system clock cannot divisible by wanted clock
282 if (_sd_ReferenceClock % sd_clock_khz != 0)
283 rate++;
284
285 if(rate >= SD_CLK_DIV0_MAX)
286 {
287 rate = SD_CLK_DIV0_MAX;
288 }
289
290 //--- calculate the second divider CLKDIV0[SDHOST_N]
291 div1 = ((rate -1) & 0xFF);
292
293 //--- setup register
294 CLK->CLKDIV0 &= ~CLK_CLKDIV0_SDHDIV_Msk;
295 CLK->CLKDIV0 |= (div1 << CLK_CLKDIV0_SDHDIV_Pos);
296
297 for(i=0; i<1000; i++); // waiting for clock become stable
298 return;
299}
300
301void SD_CardSelect(int cardSel)
302{
303 if(cardSel == 0)
304 {
305 SD->CTL |= (SD->CTL & ~SDH_CTL_SDPORT_Msk);
306 }
307 else if(cardSel == 1)
308 {
309 SD->CTL |= ((SD->CTL & ~SDH_CTL_SDPORT_Msk) | (1 << SDH_CTL_SDPORT_Pos));
310 }
311}
312
313uint32_t SD_CardDetection(uint32_t u32CardNum)
314{
315 uint32_t i;
316
317 if (u32CardNum == SD_PORT0)
318 {
319 if(SD->INTEN & SDH_INTEN_CDSRC0_Msk) // Card detect pin from GPIO
320 {
321 if(SD->INTSTS & SDH_INTSTS_CDSTS0_Msk) // Card remove
322 {
323 SD0.IsCardInsert = FALSE;
324 return FALSE;
325 }
326 else
327 SD0.IsCardInsert = TRUE;
328 }
329 else if(!(SD->INTEN & SDH_INTEN_CDSRC0_Msk))
330 {
331 SD->CTL |= SDH_CTL_CLKKEEP0_Msk;
332 for(i= 0; i < 5000; i++);
333
334 if(SD->INTSTS & SDH_INTSTS_CDSTS0_Msk) // Card insert
335 SD0.IsCardInsert = TRUE;
336 else
337 {
338 SD0.IsCardInsert = FALSE;
339 return FALSE;
340 }
341
342 SD->CTL &= ~SDH_CTL_CLKKEEP0_Msk;
343 }
344
345 }
346 else if (u32CardNum == SD_PORT1)
347 {
348 if(SD->INTEN & SDH_INTEN_CDSRC1_Msk) // Card detect pin from GPIO
349 {
350 if(SD->INTSTS & SDH_INTSTS_CDSTS1_Msk) // Card remove
351 {
352 SD1.IsCardInsert = FALSE;
353 return FALSE;
354 }
355 else
356 SD1.IsCardInsert = TRUE;
357 }
358 else if(!(SD->INTEN & SDH_INTEN_CDSRC1_Msk))
359 {
360 SD->CTL |= SDH_CTL_CLKKEEP1_Msk;
361 for(i= 0; i < 5000; i++);
362
363 if(SD->INTSTS & SDH_INTSTS_CDSTS1_Msk) // Card insert
364 SD1.IsCardInsert = TRUE;
365 else
366 {
367 SD1.IsCardInsert = FALSE;
368 return FALSE;
369 }
370
371 SD->CTL &= ~SDH_CTL_CLKKEEP1_Msk;
372 }
373
374 }
375
376 return TRUE;
377}
378
379
380// Initial
381int SD_Init(SD_INFO_T *pSD)
382{
383 int volatile i, status;
384 unsigned int resp;
385 uint32_t CIDBuffer[4];
386 unsigned int volatile u32CmdTimeOut;
387
388 // set the clock to 200KHz
389 //SD_Set_clock(200);
390 SD_Set_clock(100);
391
392 // power ON 74 clock
393 SD->CTL |= SDH_CTL_CLK74OEN_Msk;
394
395 while(SD->CTL & SDH_CTL_CLK74OEN_Msk)
396 {
397 if (pSD->IsCardInsert == FALSE)
398 return SD_NO_SD_CARD;
399 }
400
401 SD_SDCommand(pSD, 0, 0); // reset all cards
402 for (i=0x1000; i>0; i--);
403
404 // initial SDHC
405 _sd_uR7_CMD = 1;
406 //u32CmdTimeOut = 5000;
407 u32CmdTimeOut = 0xFFFFF;
408 //u32CmdTimeOut = 0;
409
410 i = SD_SDCmdAndRsp(pSD, 8, 0x00000155, u32CmdTimeOut);
411 if (i == Successful)
412 {
413 // SD 2.0
414 SD_SDCmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut);
415 _sd_uR3_CMD = 1;
416 SD_SDCmdAndRsp(pSD, 41, 0x40ff8000, u32CmdTimeOut); // 2.7v-3.6v
417 resp = SD->RESP0;
418
419 while (!(resp & 0x00800000)) // check if card is ready
420 {
421 SD_SDCmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut);
422 _sd_uR3_CMD = 1;
423 SD_SDCmdAndRsp(pSD, 41, 0x40ff8000, u32CmdTimeOut); // 3.0v-3.4v
424 resp = SD->RESP0;
425 }
426 if (resp & 0x00400000)
428 else
430 }
431 else
432 {
433 // SD 1.1
434 SD_SDCommand(pSD, 0, 0); // reset all cards
435 for (i=0x100; i>0; i--);
436
437 i = SD_SDCmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut);
438 if (i == 2) // MMC memory
439 {
440
441 SD_SDCommand(pSD, 0, 0); // reset
442 for (i=0x100; i>0; i--);
443
444 _sd_uR3_CMD = 1;
445
446 if (SD_SDCmdAndRsp(pSD, 1, 0x40ff8000, u32CmdTimeOut) != 2) // eMMC memory
447 {
448 resp = SD->RESP0;
449 while (!(resp & 0x00800000)) // check if card is ready
450 {
451 _sd_uR3_CMD = 1;
452
453 SD_SDCmdAndRsp(pSD, 1, 0x40ff8000, u32CmdTimeOut); // high voltage
454 resp = SD->RESP0;
455 }
456
457 if(resp & 0x00400000)
458 pSD->CardType = SD_TYPE_EMMC;
459 else
460 pSD->CardType = SD_TYPE_MMC;
461 }
462 else
463 {
465 return SD_ERR_DEVICE;
466 }
467 }
468 else if (i == 0) // SD Memory
469 {
470 _sd_uR3_CMD = 1;
471 SD_SDCmdAndRsp(pSD, 41, 0x00ff8000, u32CmdTimeOut); // 3.0v-3.4v
472 resp = SD->RESP0;
473 while (!(resp & 0x00800000)) // check if card is ready
474 {
475 SD_SDCmdAndRsp(pSD, 55, 0x00,u32CmdTimeOut);
476 _sd_uR3_CMD = 1;
477 SD_SDCmdAndRsp(pSD, 41, 0x00ff8000, u32CmdTimeOut); // 3.0v-3.4v
478 resp = SD->RESP0;
479 }
481 }
482 else
483 {
485 return SD_INIT_ERROR;
486 }
487 }
488
489 // CMD2, CMD3
490 if (pSD->CardType != SD_TYPE_UNKNOWN)
491 {
492 SD_SDCmdAndRsp2(pSD, 2, 0x00, CIDBuffer);
493 if ((pSD->CardType == SD_TYPE_MMC) || (pSD->CardType == SD_TYPE_EMMC))
494 {
495 if ((status = SD_SDCmdAndRsp(pSD, 3, 0x10000, 0)) != Successful) // set RCA
496 return status;
497 pSD->RCA = 0x10000;
498 }
499 else
500 {
501 if ((status = SD_SDCmdAndRsp(pSD, 3, 0x00, 0)) != Successful) // get RCA
502 return status;
503 else
504 pSD->RCA = (SD->RESP0 << 8) & 0xffff0000;
505 }
506 }
507
508 return Successful;
509}
510
511
512int SD_SwitchToHighSpeed(SD_INFO_T *pSD)
513{
514 int volatile status=0;
515 uint16_t current_comsumption, busy_status0;
516
517 SD->DMASA = (uint32_t)_sd_pSDHCBuffer; // set DMA transfer starting address
518 SD->BLEN = 63; // 512 bit
519
520 if ((status = SD_SDCmdAndRspDataIn(pSD, 6, 0x00ffff01)) != Successful)
521 return Fail;
522
523 current_comsumption = _sd_pSDHCBuffer[0]<<8 | _sd_pSDHCBuffer[1];
524 if (!current_comsumption)
525 return Fail;
526
527 busy_status0 = _sd_pSDHCBuffer[28]<<8 | _sd_pSDHCBuffer[29];
528
529 if (!busy_status0) // function ready
530 {
531 SD->DMASA = (uint32_t)_sd_pSDHCBuffer; // set DMA transfer starting address
532 SD->BLEN = 63; // 512 bit
533
534 if ((status = SD_SDCmdAndRspDataIn(pSD, 6, 0x80ffff01)) != Successful)
535 return Fail;
536
537 // function change timing: 8 clocks
538 SD->CTL |= SDH_CTL_CLK8OEN_Msk;
539 while(SD->CTL & SDH_CTL_CLK8OEN_Msk)
540 {
541 if (SD->INTSTS & SDH_INTSTS_CDSTS0_Msk)
542 {
543 return SD_NO_SD_CARD;
544 }
545 }
546
547 current_comsumption = _sd_pSDHCBuffer[0]<<8 | _sd_pSDHCBuffer[1];
548 if (!current_comsumption)
549 return Fail;
550
551 return Successful;
552 }
553 else
554 return Fail;
555}
556
557
558int SD_SelectCardType(SD_INFO_T *pSD)
559{
560 int volatile status=0;
561 unsigned int arg;
562
563 if ((status = SD_SDCmdAndRsp(pSD, 7, pSD->RCA, 0)) != Successful)
564 return status;
565
566 SD_CheckRB();
567
568 // if SD card set 4bit
569 if (pSD->CardType == SD_TYPE_SD_HIGH)
570 {
571 _sd_pSDHCBuffer = (uint8_t *)((uint32_t)_sd_ucSDHCBuffer);
572 SD->DMASA = (uint32_t)_sd_pSDHCBuffer; // set DMA transfer starting address
573 SD->BLEN = 0x07; // 64 bit
574
575 if ((status = SD_SDCmdAndRsp(pSD, 55, pSD->RCA, 0)) != Successful)
576 return status;
577 if ((status = SD_SDCmdAndRspDataIn(pSD, 51, 0x00)) != Successful)
578 return status;
579
580 if ((_sd_ucSDHCBuffer[0] & 0xf) == 0x2)
581 {
582 status = SD_SwitchToHighSpeed(pSD);
583 if (status == Successful)
584 {
585 /* divider */
586 SD_Set_clock(SDHC_FREQ);
587 }
588 }
589
590 if ((status = SD_SDCmdAndRsp(pSD, 55, pSD->RCA, 0)) != Successful)
591 return status;
592 if ((status = SD_SDCmdAndRsp(pSD, 6, 0x02, 0)) != Successful) // set bus width
593 return status;
594
595 SD->CTL |= SDH_CTL_DBW_Msk;
596 }
597 else if (pSD->CardType == SD_TYPE_SD_LOW)
598 {
599 _sd_pSDHCBuffer = (uint8_t *)((uint32_t)_sd_ucSDHCBuffer);
600 SD->DMASA = (uint32_t) _sd_pSDHCBuffer; // set DMA transfer starting address
601 SD->BLEN = 0x07; // 64 bit
602
603 if ((status = SD_SDCmdAndRsp(pSD, 55, pSD->RCA, 0)) != Successful)
604 return status;
605 if ((status = SD_SDCmdAndRspDataIn(pSD, 51, 0x00)) != Successful)
606 return status;
607
608 // set data bus width. ACMD6 for SD card, SDCR_DBW for host.
609 if ((status = SD_SDCmdAndRsp(pSD, 55, pSD->RCA, 0)) != Successful)
610 return status;
611
612 if ((status = SD_SDCmdAndRsp(pSD, 6, 0x02, 0)) != Successful) // set bus width
613 return status;
614
615 SD->CTL |= SDH_CTL_DBW_Msk;
616 }
617 else if ((pSD->CardType == SD_TYPE_MMC) ||(pSD->CardType == SD_TYPE_EMMC))
618 {
619
620 if(pSD->CardType == SD_TYPE_MMC)
621 SD->CTL &= ~SDH_CTL_DBW_Msk;
622
623 //--- sent CMD6 to MMC card to set bus width to 4 bits mode
624 // set CMD6 argument Access field to 3, Index to 183, Value to 1 (4-bit mode)
625 arg = (3 << 24) | (183 << 16) | (1 << 8);
626 if ((status = SD_SDCmdAndRsp(pSD, 6, arg, 0)) != Successful)
627 return status;
628 SD_CheckRB();
629
630 SD->CTL |= SDH_CTL_DBW_Msk;; // set bus width to 4-bit mode for SD host controller
631
632 }
633
634 if ((status = SD_SDCmdAndRsp(pSD, 16, SD_BLOCK_SIZE, 0)) != Successful) // set block length
635 return status;
636 SD->BLEN = SD_BLOCK_SIZE - 1; // set the block size
637
638 SD_SDCommand(pSD, 7, 0);
639 SD->CTL |= SDH_CTL_CLK8OEN_Msk;
640 while(SD->CTL & SDH_CTL_CLK8OEN_Msk)
641 {
642 if (SD->INTSTS & SDH_INTSTS_CDSTS0_Msk)
643 {
644 return SD_NO_SD_CARD;
645 }
646 }
647
648#ifdef _SD_USE_INT_
649 SD->INTEN |= SDH_INTEN_BLKDIEN_Msk;
650#endif //_SD_USE_INT_
651
652 return Successful;
653}
654
655void SD_Get_SD_info(SD_INFO_T *pSD, DISK_DATA_T *_info)
656{
657 unsigned int R_LEN, C_Size, MULT, size;
658 uint32_t Buffer[4];
659 unsigned char *ptr;
660
661 SD_SDCmdAndRsp2(pSD, 9, pSD->RCA, Buffer);
662
663 if ((pSD->CardType == SD_TYPE_MMC) || (pSD->CardType == SD_TYPE_EMMC))
664 {
665 // for MMC/eMMC card
666 if ((Buffer[0] & 0xc0000000) == 0xc0000000)
667 {
668 // CSD_STRUCTURE [127:126] is 3
669 // CSD version depend on EXT_CSD register in eMMC v4.4 for card size > 2GB
670 SD_SDCmdAndRsp(pSD, 7, pSD->RCA, 0);
671
672 ptr = (uint8_t *)((uint32_t)_sd_ucSDHCBuffer );
673 SD->DMASA = (uint32_t)ptr; // set DMA transfer starting address
674 SD->BLEN = 511; // read 512 bytes for EXT_CSD
675
676 if (SD_SDCmdAndRspDataIn(pSD, 8, 0x00) != Successful)
677 return;
678
679 SD_SDCommand(pSD, 7, 0);
680 SD->CTL |= SDH_CTL_CLK8OEN_Msk;
681 while(SD->CTL & SDH_CTL_CLK8OEN_Msk)
682 {
683 if (SD->INTSTS & SDH_INTSTS_CDSTS0_Msk)
684 {
685 return;
686 }
687 }
688
689 _info->totalSectorN = (*(uint32_t *)(ptr+212));
690 _info->diskSize = _info->totalSectorN / 2;
691 }
692 else
693 {
694 // CSD version v1.0/1.1/1.2 in eMMC v4.4 spec for card size <= 2GB
695 R_LEN = (Buffer[1] & 0x000f0000) >> 16;
696 C_Size = ((Buffer[1] & 0x000003ff) << 2) | ((Buffer[2] & 0xc0000000) >> 30);
697 MULT = (Buffer[2] & 0x00038000) >> 15;
698 size = (C_Size+1) * (1<<(MULT+2)) * (1<<R_LEN);
699
700 _info->diskSize = size / 1024;
701 _info->totalSectorN = size / 512;
702 }
703 }
704 else
705 {
706 if (Buffer[0] & 0xc0000000)
707 {
708 C_Size = ((Buffer[1] & 0x0000003f) << 16) | ((Buffer[2] & 0xffff0000) >> 16);
709 size = (C_Size+1) * 512; // Kbytes
710
711 _info->diskSize = size;
712 _info->totalSectorN = size << 1;
713 }
714 else
715 {
716 R_LEN = (Buffer[1] & 0x000f0000) >> 16;
717 C_Size = ((Buffer[1] & 0x000003ff) << 2) | ((Buffer[2] & 0xc0000000) >> 30);
718 MULT = (Buffer[2] & 0x00038000) >> 15;
719 size = (C_Size+1) * (1<<(MULT+2)) * (1<<R_LEN);
720
721 _info->diskSize = size / 1024;
722 _info->totalSectorN = size / 512;
723 }
724 }
725
726 _info->sectorSize = 512;
727}
728
729int SD_ChipErase(SD_INFO_T *pSD, DISK_DATA_T *_info)
730{
731 int status=0;
732
733 status = SD_SDCmdAndRsp(pSD, 32, 512, 6000);
734 if (status < 0)
735 {
736 return status;
737 }
738 status = SD_SDCmdAndRsp(pSD, 33, _info->totalSectorN*512, 6000);
739 if (status < 0)
740 {
741 return status;
742 }
743 status = SD_SDCmdAndRsp(pSD, 38, 0, 6000);
744 if (status < 0)
745 {
746 return status;
747 }
748 SD_CheckRB();
749
750 return 0;
751}
752
754
755
764void SD_Open(uint32_t u32CardDetSrc)
765{
766 // Enable SD Card Host Controller operation.
767 //CLK->AHBCLK |= CLK_AHBCLK_SDHCKEN_Msk;
768
769 // enable DMAC
770 SD->DMACTL = SDH_DMACTL_DMARST_Msk;
771 while(SD->DMACTL & SDH_DMACTL_DMARST_Msk);
772
773 SD->DMACTL = SDH_DMACTL_DMAEN_Msk;
774
775 //Reset FMI
776 SD->GCTL = SDH_GCTL_GCTLRST_Msk; // Start reset FMI controller.
777 while(SD->GCTL & SDH_GCTL_GCTLRST_Msk);
778
779
780//#ifdef _SD_USE_INT_
781// NVIC_EnableIRQ(SD_IRQn);
782//#endif //_SD_USE_INT_
783
784 // enable SD
785 SD->GCTL = SDH_GCTL_SDEN_Msk;
786
787 if(u32CardDetSrc & SD_PORT0)
788 {
789 SD->CTL |= (SD->CTL & ~SDH_CTL_SDPORT_Msk);
790
791 if(u32CardDetSrc & CardDetect_From_DAT3)
792 {
793 SD->INTEN &= ~SDH_INTEN_CDSRC0_Msk;
794 }
795 else
796 {
797 SD->INTEN |= SDH_INTEN_CDSRC0_Msk;
798 }
799 }
800 else if(u32CardDetSrc & SD_PORT1)
801 {
802 SD->CTL |= ((SD->CTL & ~SDH_CTL_SDPORT_Msk) | (1 << SDH_CTL_SDPORT_Pos));
803
804 if(u32CardDetSrc & CardDetect_From_DAT3)
805 {
806 SD->INTEN &= ~SDH_INTEN_CDSRC1_Msk;
807 }
808 else
809 {
810 SD->INTEN |= SDH_INTEN_CDSRC1_Msk;
811 }
812 }
813
814 SD->CTL |= SDH_CTL_CTLRST_Msk; // SD software reset
815 while(SD->CTL & SDH_CTL_CTLRST_Msk);
816
817 SD->CTL &= ~((0xFF) | (SDH_CTL_CLKKEEP1_Msk)); // disable SD clock output
818
819 if(u32CardDetSrc & SD_PORT0)
820 {
821 memset(&SD0, 0, sizeof(SD_INFO_T));
822 }
823 else if(u32CardDetSrc & SD_PORT1)
824 {
825 memset(&SD1, 0, sizeof(SD_INFO_T));
826 }
827
828}
829
837void SD_Probe(uint32_t u32CardNum)
838{
839 // Disable FMI/SD host interrupt
840 SD->GINTEN = 0;
841
842 SD->CTL &= ~SDH_CTL_SDNWR_Msk;
843 SD->CTL |= 0x09 << SDH_CTL_SDNWR_Pos; // set SDNWR = 9
844 SD->CTL &= ~SDH_CTL_BLKCNT_Msk;
845 SD->CTL |= 0x01 << SDH_CTL_BLKCNT_Pos; // set BLKCNT = 1
846 SD->CTL &= ~SDH_CTL_DBW_Msk; // SD 1-bit data bus
847
848 if(!(SD_CardDetection(u32CardNum)))
849 return;
850
851 if (u32CardNum == SD_PORT0)
852 {
853 if (SD_Init(&SD0) < 0)
854 return;
855
856 /* divider */
857 if (SD0.CardType == SD_TYPE_MMC)
858 SD_Set_clock(20000);
859 else
860 SD_Set_clock(SD_FREQ);
861
862 SD_Get_SD_info(&SD0, &SD_DiskInfo0);
863
864 if (SD_SelectCardType(&SD0))
865 return;
866
867 sd0_ok = 1;
868 }
869 else if (u32CardNum == SD_PORT1)
870 {
871 if (SD_Init(&SD1) < 0)
872 return;
873
874 /* divider */
875 if (SD1.CardType == SD_TYPE_MMC)
876 SD_Set_clock(20000);
877 else
878 SD_Set_clock(SD_FREQ);
879
880 SD_Get_SD_info(&SD1, &SD_DiskInfo1);
881
882 if (SD_SelectCardType(&SD1))
883 return;
884
885 sd1_ok = 1;
886 }
887
888
889}
890
901uint32_t SD_Read(uint32_t u32CardNum, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount)
902{
903 char volatile bIsSendCmd = FALSE, buf;
904 unsigned int volatile reg;
905 int volatile i, loop, status;
906 uint32_t blksize = SD_BLOCK_SIZE;
907
908 SD_INFO_T *pSD;
909
910 if(u32CardNum == SD_PORT0)
911 pSD = &SD0;
912 else
913 pSD = &SD1;
914
915 //--- check input parameters
916 if (u32SecCount == 0)
917 {
918 return SD_SELECT_ERROR;
919 }
920
921 if ((status = SD_SDCmdAndRsp(pSD, 7, pSD->RCA, 0)) != Successful)
922 return status;
923 SD_CheckRB();
924
925 SD->BLEN = blksize - 1; // the actual byte count is equal to (SDBLEN+1)
926
927 if ( (pSD->CardType == SD_TYPE_SD_HIGH) || (pSD->CardType == SD_TYPE_EMMC) )
928 SD->CMDARG = u32StartSec;
929 else
930 SD->CMDARG = u32StartSec * blksize;
931
932 SD->DMASA = (uint32_t)pu8BufAddr;
933
934 loop = u32SecCount / 255;
935 for (i=0; i<loop; i++)
936 {
937#ifdef _SD_USE_INT_
938 _sd_SDDataReady = FALSE;
939#endif //_SD_USE_INT_
940
941 reg = SD->CTL & ~SDH_CTL_CMDCODE_Msk;
942 reg = reg | 0xff0000; // set BLK_CNT to 255
943 if (bIsSendCmd == FALSE)
944 {
945 SD->CTL = reg|(18<<8)|(SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk);
946 bIsSendCmd = TRUE;
947 }
948 else
949 SD->CTL = reg | SDH_CTL_DIEN_Msk;
950
951#ifdef _SD_USE_INT_
952 while(!_sd_SDDataReady)
953#else
954 while(1)
955#endif //_SD_USE_INT_
956 {
957 if(_sd_SDDataReady) break;
958
959#ifndef _SD_USE_INT_
960 if ((SD->INTSTS & SDH_INTSTS_BLKDIF_Msk) && (!(SD->CTL & SDH_CTL_DIEN_Msk)))
961 {
962 SD->INTSTS = SDH_INTSTS_BLKDIF_Msk;
963 break;
964 }
965#endif
966 if (pSD->IsCardInsert == FALSE)
967 return SD_NO_SD_CARD;
968 if (SD->INTSTS & SDH_INTSTS_CDSTS0_Msk)
969 {
970 return SD_NO_SD_CARD;
971 }
972 }
973
974 if (!(SD->INTSTS & SDH_INTSTS_CRC7_Msk)) // check CRC7
975 {
976 //printf("sdioSD_Read_in_blksize(): response error!\n");
977 return SD_CRC7_ERROR;
978 }
979
980 if (!(SD->INTSTS & SDH_INTSTS_CRC16_Msk)) // check CRC16
981 {
982 //printf("sdioSD_Read_in_blksize() :read data error!\n");
983 return SD_CRC16_ERROR;
984 }
985 }
986
987 loop = u32SecCount % 255;
988 if (loop != 0)
989 {
990#ifdef _SD_USE_INT_
991 _sd_SDDataReady = FALSE;
992#endif //_SD_USE_INT_
993
994 reg = SD->CTL & (~SDH_CTL_CMDCODE_Msk);
995 reg = reg & (~SDH_CTL_BLKCNT_Msk);
996 reg |= (loop << 16); // setup SDCR_BLKCNT
997
998 if (bIsSendCmd == FALSE)
999 {
1000 SD->CTL = reg|(18<<8)|(SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk);
1001 bIsSendCmd = TRUE;
1002 }
1003 else
1004 SD->CTL = reg | SDH_CTL_DIEN_Msk;
1005
1006#ifdef _SD_USE_INT_
1007 while(!_sd_SDDataReady)
1008#else
1009 while(1)
1010#endif //_SD_USE_INT_
1011 {
1012
1013#ifndef _SD_USE_INT_
1014 if ((SD->INTSTS & SDH_INTSTS_BLKDIF_Msk) && (!(SD->CTL & SDH_CTL_DIEN_Msk)))
1015 {
1016 SD->INTSTS = SDH_INTSTS_BLKDIF_Msk;
1017 break;
1018 }
1019#endif
1020
1021 if (pSD->IsCardInsert == FALSE)
1022 return SD_NO_SD_CARD;
1023 if (SD->INTSTS & SDH_INTSTS_CDSTS0_Msk)
1024 {
1025 return SD_NO_SD_CARD;
1026 }
1027 }
1028
1029 if (!(SD->INTSTS & SDH_INTSTS_CRC7_Msk)) // check CRC7
1030 {
1031 //printf("sdioSD_Read_in_blksize(): response error!\n");
1032 return SD_CRC7_ERROR;
1033 }
1034
1035 if (!(SD->INTSTS & SDH_INTSTS_CRC16_Msk)) // check CRC16
1036 {
1037 //printf("sdioSD_Read_in_blksize(): read data error!\n");
1038 return SD_CRC16_ERROR;
1039 }
1040 }
1041
1042 if (SD_SDCmdAndRsp(pSD, 12, 0, 0)) // stop command
1043 {
1044 //printf("stop command fail !!\n");
1045 return SD_CRC7_ERROR;
1046 }
1047 SD_CheckRB();
1048
1049 SD_SDCommand(pSD, 7, 0);
1050 SD->CTL |= SDH_CTL_CLK8OEN_Msk;
1051 while(SD->CTL & SDH_CTL_CLK8OEN_Msk)
1052 {
1053 if (SD->INTSTS & SDH_INTSTS_CDSTS0_Msk)
1054 {
1055 return SD_NO_SD_CARD;
1056 }
1057 }
1058
1059 return Successful;
1060}
1061
1062
1077uint32_t SD_Write(uint32_t u32CardNum, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount)
1078{
1079 char volatile bIsSendCmd = FALSE;
1080 unsigned int volatile reg;
1081 int volatile i, loop, status;
1082
1083 SD_INFO_T *pSD;
1084
1085 if(u32CardNum == SD_PORT0)
1086 pSD = &SD0;
1087 else
1088 pSD = &SD1;
1089
1090
1091 //--- check input parameters
1092 if (u32SecCount == 0)
1093 {
1094 return SD_SELECT_ERROR;
1095 }
1096
1097 if ((status = SD_SDCmdAndRsp(pSD, 7, pSD->RCA, 0)) != Successful)
1098 return status;
1099
1100 SD_CheckRB();
1101
1102 // According to SD Spec v2.0, the write CMD block size MUST be 512, and the start address MUST be 512*n.
1103 SD->BLEN = SD_BLOCK_SIZE - 1; // set the block size
1104
1105 if ((pSD->CardType == SD_TYPE_SD_HIGH) || (pSD->CardType == SD_TYPE_EMMC))
1106 SD->CMDARG = u32StartSec;
1107 else
1108 SD->CMDARG = u32StartSec * SD_BLOCK_SIZE; // set start address for SD CMD
1109
1110 SD->DMASA = (uint32_t)pu8BufAddr;
1111 loop = u32SecCount / 255; // the maximum block count is 0xFF=255 for register SDCR[BLK_CNT]
1112 for (i=0; i<loop; i++)
1113 {
1114#ifdef _SD_USE_INT_
1115 _sd_SDDataReady = FALSE;
1116#endif //_SD_USE_INT_
1117
1118 reg = SD->CTL & 0xff00c080;
1119 reg = reg | 0xff0000; // set BLK_CNT to 0xFF=255
1120 if (!bIsSendCmd)
1121 {
1122 SD->CTL = reg|(25<<8)|(SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DOEN_Msk);
1123 bIsSendCmd = TRUE;
1124 }
1125 else
1126 SD->CTL = reg | SDH_CTL_DOEN_Msk;
1127
1128#ifdef _SD_USE_INT_
1129 while(!_sd_SDDataReady)
1130#else
1131 while(1)
1132#endif //_SD_USE_INT_
1133 {
1134#ifndef _SD_USE_INT_
1135 if ((SD->INTSTS & SDH_INTSTS_BLKDIF_Msk) && (!(SD->CTL & SDH_CTL_DOEN_Msk)))
1136 {
1137 SD->INTSTS = SDH_INTSTS_BLKDIF_Msk;
1138 break;
1139 }
1140#endif
1141 if (pSD->IsCardInsert == FALSE)
1142 return SD_NO_SD_CARD;
1143 if (SD->INTSTS & SDH_INTSTS_CDSTS0_Msk)
1144 {
1145 return SD_NO_SD_CARD;
1146 }
1147 }
1148
1149 if ((SD->INTSTS & SDH_INTSTS_CRCIF_Msk) != 0) // check CRC
1150 {
1151 SD->INTSTS = SDH_INTSTS_CRCIF_Msk;
1152 return SD_CRC_ERROR;
1153 }
1154 }
1155
1156 loop = u32SecCount % 255;
1157 if (loop != 0)
1158 {
1159#ifdef _SD_USE_INT_
1160 _sd_SDDataReady = FALSE;
1161#endif //_SD_USE_INT_
1162
1163 reg = (SD->CTL & 0xff00c080) | (loop << 16);
1164 if (!bIsSendCmd)
1165 {
1166 SD->CTL = reg|(25<<8)|(SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DOEN_Msk);
1167 bIsSendCmd = TRUE;
1168 }
1169 else
1170 SD->CTL = reg | SDH_CTL_DOEN_Msk;
1171
1172#ifdef _SD_USE_INT_
1173 while(!_sd_SDDataReady)
1174#else
1175 while(1)
1176#endif //_SD_USE_INT_
1177 {
1178#ifndef _SD_USE_INT_
1179 if ((SD->INTSTS & SDH_INTSTS_BLKDIF_Msk) && (!(SD->CTL & SDH_CTL_DOEN_Msk)))
1180 {
1181 SD->INTSTS = SDH_INTSTS_BLKDIF_Msk;
1182 break;
1183 }
1184#endif
1185 if (pSD->IsCardInsert == FALSE)
1186 return SD_NO_SD_CARD;
1187 if (SD->INTSTS & SDH_INTSTS_CDSTS0_Msk)
1188 {
1189 return SD_NO_SD_CARD;
1190 }
1191 }
1192
1193 if ((SD->INTSTS & SDH_INTSTS_CRCIF_Msk) != 0) // check CRC
1194 {
1195 SD->INTSTS = SDH_INTSTS_CRCIF_Msk;
1196 return SD_CRC_ERROR;
1197 }
1198 }
1199 SD->INTSTS = SDH_INTSTS_CRCIF_Msk;
1200
1201 if (SD_SDCmdAndRsp(pSD, 12, 0, 0)) // stop command
1202 {
1203 return SD_CRC7_ERROR;
1204 }
1205 SD_CheckRB();
1206
1207 SD_SDCommand(pSD, 7, 0);
1208 SD->CTL |= SDH_CTL_CLK8OEN_Msk;
1209 while(SD->CTL & SDH_CTL_CLK8OEN_Msk)
1210 {
1211 if (SD->INTSTS & SDH_INTSTS_CDSTS0_Msk)
1212 {
1213 return SD_NO_SD_CARD;
1214 }
1215 }
1216
1217 return Successful;
1218}
1219
1220 /* end of group NUC472_442_SD_EXPORTED_FUNCTIONS */
1222 /* end of group NUC472_442_SD_Driver */
1224 /* end of group NUC472_442_Device_Driver */
1226
1227/*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/
1228
1229
1230
1231
1232
1233
1234
1235
void *__dso_handle __attribute__((weak))
Definition: _syscalls.c:35
NUC472/NUC442 peripheral access layer header file. This file contains all the peripheral register's d...
#define SDH_DMACTL_DMAEN_Msk
Definition: NUC472_442.h:22503
#define SDH_CTL_COEN_Msk
Definition: NUC472_442.h:22548
#define SDH_CTL_SDNWR_Pos
Definition: NUC472_442.h:22583
#define SDH_CTL_R2EN_Msk
Definition: NUC472_442.h:22560
#define SDH_CTL_CLK8OEN_Msk
Definition: NUC472_442.h:22566
#define SDH_CTL_SDPORT_Pos
Definition: NUC472_442.h:22586
#define SDH_CTL_DBW_Msk
Definition: NUC472_442.h:22578
#define SDH_GCTL_GCTLRST_Msk
Definition: NUC472_442.h:22536
#define SDH_INTSTS_CDSTS0_Msk
Definition: NUC472_442.h:22665
#define SDH_CTL_RIEN_Msk
Definition: NUC472_442.h:22551
#define SDH_INTSTS_BLKDIF_Msk
Definition: NUC472_442.h:22629
#define SDH_CTL_CLKKEEP1_Msk
Definition: NUC472_442.h:22590
#define SDH_INTSTS_CDSTS1_Msk
Definition: NUC472_442.h:22668
#define SDH_INTSTS_DAT0STS_Msk
Definition: NUC472_442.h:22644
#define SDH_CTL_CLK74OEN_Msk
Definition: NUC472_442.h:22563
#define SDH_INTEN_CDSRC1_Msk
Definition: NUC472_442.h:22626
#define SDH_DMACTL_DMARST_Msk
Definition: NUC472_442.h:22506
#define SDH_CTL_BLKCNT_Pos
Definition: NUC472_442.h:22580
#define SDH_GCTL_SDEN_Msk
Definition: NUC472_442.h:22539
#define SDH_INTSTS_CRC7_Msk
Definition: NUC472_442.h:22635
#define CLK_CLKDIV0_SDHDIV_Pos
Definition: NUC472_442.h:3871
#define SDH_CTL_CLKKEEP0_Msk
Definition: NUC472_442.h:22569
#define CLK_CLKSEL0_SDHSEL_Msk
Definition: NUC472_442.h:3776
#define SDH_INTSTS_CRC16_Msk
Definition: NUC472_442.h:22638
#define SDH_CTL_DOEN_Msk
Definition: NUC472_442.h:22557
#define SDH_CTL_DIEN_Msk
Definition: NUC472_442.h:22554
#define SDH_INTEN_BLKDIEN_Msk
Definition: NUC472_442.h:22596
#define SDH_INTSTS_CRCIF_Msk
Definition: NUC472_442.h:22632
#define SDH_INTEN_CDSRC0_Msk
Definition: NUC472_442.h:22623
#define SDH_CTL_CTLRST_Msk
Definition: NUC472_442.h:22575
#define CLK_CLKSEL0_SDHSEL_HXT
Definition: clk.h:115
#define CLK_CLKSEL0_SDHSEL_HIRC
Definition: clk.h:118
#define CLK_CLKSEL0_SDHSEL_PLL
Definition: clk.h:116
#define CLK_CLKSEL0_SDHSEL_HCLK
Definition: clk.h:117
uint32_t CLK_GetHCLKFreq(void)
Get HCLK frequency.
Definition: clk.c:145
uint32_t CLK_GetPLLClockFreq(void)
This function get PLL frequency. The frequency unit is Hz.
Definition: clk.c:166
uint32_t CLK_GetHXTFreq(void)
Get external high speed crystal clock frequency.
Definition: clk.c:118
#define CLK
Definition: NUC472_442.h:28798
#define SD
Definition: NUC472_442.h:28821
#define SD_BASE
Definition: NUC472_442.h:28732
#define SD_CRC_ERROR
Definition: sd.h:56
#define SD_FREQ
Definition: sd.h:59
#define SD_CMD8_ERROR
Definition: sd.h:57
#define SD_INIT_ERROR
Definition: sd.h:53
#define SD_NO_SD_CARD
Definition: sd.h:48
#define Successful
Definition: sd.h:37
#define SD_PORT0
Definition: sd.h:64
#define SD_ERR_DEVICE
Definition: sd.h:49
#define SD_TYPE_EMMC
Definition: sd.h:45
#define SD_TYPE_SD_LOW
Definition: sd.h:43
#define SD_CRC16_ERROR
Definition: sd.h:55
#define SD_PORT1
Definition: sd.h:65
#define Fail
Definition: sd.h:38
#define CardDetect_From_DAT3
Definition: sd.h:68
#define SDHC_FREQ
Definition: sd.h:60
#define SD_CRC7_ERROR
Definition: sd.h:54
#define SD_TYPE_UNKNOWN
Definition: sd.h:41
#define SD_SELECT_ERROR
Definition: sd.h:51
#define SD_TYPE_MMC
Definition: sd.h:44
#define SD_TYPE_SD_HIGH
Definition: sd.h:42
unsigned int diskSize
Definition: sd.h:89
uint32_t SD_Read(uint32_t u32CardNum, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount)
This function use to read data from SD card.
Definition: sd.c:901
#define SD_BLOCK_SIZE
Definition: sd.c:29
unsigned int totalSectorN
Definition: sd.h:88
uint32_t SD_Write(uint32_t u32CardNum, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount)
This function use to write data to SD card.
Definition: sd.c:1077
int sectorSize
Definition: sd.h:90
uint32_t RCA
Definition: sd.h:78
void SD_Open(uint32_t u32CardDetSrc)
This function use to reset SD function and select card detection source and pin.
Definition: sd.c:764
uint8_t IsCardInsert
Definition: sd.h:79
uint32_t CardType
Definition: sd.h:77
void SD_Probe(uint32_t u32CardNum)
This function use to initial SD card.
Definition: sd.c:837
#define TRUE
Boolean true, define to use in API parameters or return value.
Definition: NUC472_442.h:29021
#define FALSE
Boolean false, define to use in API parameters or return value.
Definition: NUC472_442.h:29022
static int void * arg
Definition: semihosting.h:74
Definition: sd.h:76
Definition: sd.h:84
#define __HIRC