1 /*
2  * Copyright (c) 2017-2020, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  *  ======== SDSPI.c ========
35  */
36 
37 #include <stdint.h>
38 #include <stdbool.h>
39 
40 #include <ti/drivers/dpl/ClockP.h>
41 #include <ti/drivers/dpl/HwiP.h>
42 #include <ti/drivers/dpl/SemaphoreP.h>
43 #include <ti/drivers/GPIO.h>
44 #include <ti/drivers/SD.h>
45 #include <ti/drivers/sd/SDSPI.h>
46 #include <ti/drivers/SPI.h>
47 
48 /* Definitions for MMC/SDC command */
49 #define CMD0                      (0x40+0)     /* GO_IDLE_STATE */
50 #define CMD1                      (0x40+1)     /* SEND_OP_COND */
51 #define CMD8                      (0x40+8)     /* SEND_IF_COND */
52 #define CMD9                      (0x40+9)     /* SEND_CSD */
53 #define CMD10                     (0x40+10)    /* SEND_CID */
54 #define CMD12                     (0x40+12)    /* STOP_TRANSMISSION */
55 #define CMD16                     (0x40+16)    /* SET_BLOCKLEN */
56 #define CMD17                     (0x40+17)    /* READ_SINGLE_BLOCK */
57 #define CMD18                     (0x40+18)    /* READ_MULTIPLE_BLOCK */
58 #define CMD23                     (0x40+23)    /* SET_BLOCK_COUNT */
59 #define CMD24                     (0x40+24)    /* WRITE_BLOCK */
60 #define CMD25                     (0x40+25)    /* WRITE_MULTIPLE_BLOCK */
61 #define CMD41                     (0x40+41)    /* SEND_OP_COND (ACMD) */
62 #define CMD55                     (0x40+55)    /* APP_CMD */
63 #define CMD58                     (0x40+58)    /* READ_OCR */
64 #define START_BLOCK_TOKEN         (0xFE)
65 #define START_MULTIBLOCK_TOKEN    (0xFC)
66 #define STOP_MULTIBLOCK_TOKEN     (0xFD)
67 
68 #define SD_SECTOR_SIZE            (512)
69 
70 #define DRIVE_NOT_MOUNTED         ((uint16_t) ~0)
71 
72 void SDSPI_close(SD_Handle handle);
73 int_fast16_t SDSPI_control(SD_Handle handle, uint_fast16_t cmd,
74     void *arg);
75 uint_fast32_t SDSPI_getNumSectors(SD_Handle handle);
76 uint_fast32_t SDSPI_getSectorSize(SD_Handle handle);
77 int_fast16_t SDSPI_initialize(SD_Handle handle);
78 void SDSPI_init(SD_Handle handle);
79 SD_Handle SDSPI_open(SD_Handle handle, SD_Params *params);
80 int_fast16_t SDSPI_read(SD_Handle handle, void *buf,
81     int_fast32_t sector, uint_fast32_t sectorCount);
82 int_fast16_t SDSPI_write(SD_Handle handle, const void *buf,
83     int_fast32_t sector, uint_fast32_t sectorCount);
84 
85 static inline void assertCS(SDSPI_HWAttrs const *hwAttrs);
86 static inline void deassertCS(SDSPI_HWAttrs const *hwAttrs);
87 static bool recvDataBlock(SPI_Handle handle, void *buf, uint32_t count);
88 static uint8_t sendCmd(SPI_Handle handle, uint8_t cmd, uint32_t arg);
89 static int_fast16_t spiTransfer(SPI_Handle handle, void *rxBuf,
90     void *txBuf, size_t count);
91 static bool waitUntilReady(SPI_Handle handle);
92 static bool transmitDataBlock(SPI_Handle handle, void *buf, uint32_t count,
93     uint8_t token);
94 
95 /* SDSPI function table for SDSPI implementation */
96 const SD_FxnTable SDSPI_fxnTable = {
97     SDSPI_close,
98     SDSPI_control,
99     SDSPI_getNumSectors,
100     SDSPI_getSectorSize,
101     SDSPI_init,
102     SDSPI_initialize,
103     SDSPI_open,
104     SDSPI_read,
105     SDSPI_write
106 };
107 
108 /*
109  *  ======== SDSPI_close ========
110  */
SDSPI_close(SD_Handle handle)111 void SDSPI_close(SD_Handle handle)
112 {
113     SDSPI_Object *object = handle->object;
114 
115     if (object->spiHandle) {
116         SPI_close(object->spiHandle);
117         object->spiHandle = NULL;
118     }
119 
120     if (object->lockSem) {
121         SemaphoreP_delete(object->lockSem);
122         object->lockSem = NULL;
123     }
124 
125     object->cardType = SD_NOCARD;
126     object->isOpen = false;
127 }
128 
129 /*
130  *  ======== SDSPI_control ========
131  */
SDSPI_control(SD_Handle handle,uint_fast16_t cmd,void * arg)132 int_fast16_t SDSPI_control(SD_Handle handle, uint_fast16_t cmd, void *arg)
133 {
134     return (SD_STATUS_UNDEFINEDCMD);
135 }
136 
137 /*
138  *  ======== SDSPI_getNumSectors ========
139  */
SDSPI_getNumSectors(SD_Handle handle)140 uint_fast32_t SDSPI_getNumSectors(SD_Handle handle)
141 {
142     uint8_t              n;
143     uint8_t              csd[16];
144     uint16_t             csize;
145     uint32_t             sectors = 0;
146     SDSPI_Object        *object = handle->object;
147     SDSPI_HWAttrs const *hwAttrs = handle->hwAttrs;
148 
149     SemaphoreP_pend(object->lockSem, SemaphoreP_WAIT_FOREVER);
150 
151     assertCS(hwAttrs);
152 
153     /* Get number of sectors on the disk (uint32_t) */
154     if ((sendCmd(object->spiHandle, CMD9, 0) == 0) &&
155         recvDataBlock(object->spiHandle, csd, 16)) {
156         /* SDC ver 2.00 */
157         if ((csd[0] >> 6) == 1) {
158             csize = csd[9] + (csd[8] << 8) + 1;
159             sectors = csize << 10;
160         }
161         /* MMC or SDC ver 1.XX */
162         else {
163             n = (csd[5] & 15) + ((csd[10] & 128) >> 7) +
164                 ((csd[9] & 3) << 1) + 2;
165 
166             csize = (csd[8] >> 6) + ((uint16_t) csd[7] << 2) +
167                 ((uint16_t) (csd[6] & 3) << 10) + 1;
168             sectors = (uint32_t)csize << (n - 9);
169         }
170     }
171 
172     deassertCS(hwAttrs);
173 
174     SemaphoreP_post(object->lockSem);
175 
176     return (sectors);
177 }
178 
179 /*
180  *  ======== SDSPI_getSectorSize ========
181  */
SDSPI_getSectorSize(SD_Handle handle)182 uint_fast32_t SDSPI_getSectorSize(SD_Handle handle)
183 {
184     return (SD_SECTOR_SIZE);
185 }
186 
187 /*
188  *  ======== SDSPI_init ========
189  */
SDSPI_init(SD_Handle handle)190 void SDSPI_init(SD_Handle handle)
191 {
192     GPIO_init();
193     SPI_init();
194 }
195 
196 /*
197  *  ======== SDSPI_initialize ========
198  */
SDSPI_initialize(SD_Handle handle)199 int_fast16_t SDSPI_initialize(SD_Handle handle)
200 {
201     SD_CardType          cardType = SD_NOCARD;
202     uint8_t              i;
203     uint8_t              ocr[4];
204     uint8_t              txDummy[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
205                                        0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
206     int_fast16_t         status;
207     uint32_t             currentTime;
208     uint32_t             startTime;
209     uint32_t             timeout;
210     SPI_Params           spiParams;
211     SDSPI_Object        *object = handle->object;
212     SDSPI_HWAttrs const *hwAttrs = handle->hwAttrs;
213 
214     SemaphoreP_pend(object->lockSem, SemaphoreP_WAIT_FOREVER);
215 
216     /*
217      * The CS line should not be asserted when attempting to put the
218      * SD card into SPI mode.
219      */
220     deassertCS(hwAttrs);
221 
222     /*
223      * To put the SD card in SPI mode we must keep the TX line high while
224      * toggling the clock line several times. To do this we transmit 0xFF
225      * 10 times. Do not assert CS during this time
226      */
227     status = spiTransfer(object->spiHandle, NULL, &txDummy, 10);
228     if (status != SD_STATUS_SUCCESS) {
229         SemaphoreP_post(object->lockSem);
230         return (status);
231     }
232 
233     /* Now select the SD Card's chip select to send CMD0 command */
234     assertCS(hwAttrs);
235 
236     /*
237      * Send CMD0 to put the SD card in idle mode. Depending on the previous
238      * state of the SD card, this may take up to a couple hundred milliseconds.
239      * Rather than delay between attempts, we try up to 255 attempts.
240      * Failure is returned if the card does not respond will a valid byte
241      * within 255 attempts. When the card will respond with 0x1 when its
242      * in idle mode.
243      */
244     for (i = 255, status = 0xFF; i > 0 && status != 0x1; i--) {
245         status = sendCmd(object->spiHandle, CMD0, 0);
246     }
247 
248     /* If the card never transitioned into idle mode */
249     if (status != 0x1) {
250         deassertCS(hwAttrs);
251         SemaphoreP_post(object->lockSem);
252         return (SD_STATUS_ERROR);
253     }
254 
255     /*
256      * Proceed with initialization since the SD Card is in the idle state
257      * Determine what SD Card version we are dealing with
258      * Depending on which SD Card version, we need to send different SD
259      * commands to the SD Card, which will have different response fields.
260      */
261     if (sendCmd(object->spiHandle, CMD8, 0x1AA) == 1) {
262         /* SD Version 2.0 or higher */
263         status = spiTransfer(object->spiHandle, &ocr, &txDummy, 4);
264         if (status == SD_STATUS_SUCCESS) {
265             /*
266              * Ensure that the card's voltage range is valid
267              * The card can work at VDD range of 2.7-3.6V
268              */
269             if ((ocr[2] == 0x01) && (ocr[3] == 0xAA)) {
270                 /*
271                  * Wait for data packet in timeout of 1s - status used to
272                  * indicate if a timeout occurred before operation
273                  * completed.
274                  */
275                 status = SD_STATUS_ERROR;
276                 timeout = 1000000/ClockP_getSystemTickPeriod();
277                 startTime = ClockP_getSystemTicks();
278 
279                 do {
280                     /* ACMD41 with HCS bit */
281                     if ((sendCmd(object->spiHandle, CMD55, 0) <= 1) &&
282                         (sendCmd(object->spiHandle, CMD41, 1UL << 30) == 0)) {
283                         status = SD_STATUS_SUCCESS;
284                         break;
285                     }
286                     currentTime = ClockP_getSystemTicks();
287                 } while ((currentTime - startTime) < timeout);
288 
289                 /*
290                  * Check CCS bit to determine which type of capacity we are
291                  * dealing with
292                  */
293                 if ((status == SD_STATUS_SUCCESS) &&
294                     sendCmd(object->spiHandle, CMD58, 0) == 0) {
295                     status = spiTransfer(object->spiHandle, &ocr, &txDummy, 4);
296                     if (status == SD_STATUS_SUCCESS) {
297                         cardType = (ocr[0] & 0x40) ? SD_SDHC : SD_SDSC;
298                     }
299                 }
300             }
301         }
302     }
303     else {
304         /* SDC Version 1 or MMC */
305         /*
306          * The card version is not SDC V2+ so check if we are dealing with a
307          * SDC or MMC card
308          */
309         if ((sendCmd(object->spiHandle, CMD55, 0) <= 1) &&
310             (sendCmd(object->spiHandle, CMD41, 0) <= 1)) {
311             cardType = SD_SDSC;
312         }
313         else {
314             cardType = SD_MMC;
315         }
316 
317         /*
318          * Wait for data packet in timeout of 1s - status used to
319          * indicate if a timeout occurred before operation
320          * completed.
321          */
322         status = SD_STATUS_ERROR;
323         timeout = 1000000/ClockP_getSystemTickPeriod();
324         startTime = ClockP_getSystemTicks();
325         do {
326             if (cardType == SD_SDSC) {
327                 /* ACMD41 */
328                 if ((sendCmd(object->spiHandle, CMD55, 0) <= 1) &&
329                     (sendCmd(object->spiHandle, CMD41, 0) == 0)) {
330                     status = SD_STATUS_SUCCESS;
331                     break;
332                 }
333             }
334             else {
335                 /* CMD1 */
336                 if (sendCmd(object->spiHandle, CMD1, 0) == 0) {
337                     status = SD_STATUS_SUCCESS;
338                     break;
339                 }
340             }
341             currentTime = ClockP_getSystemTicks();
342         } while ((currentTime - startTime) < timeout);
343 
344         /* Select R/W block length */
345         if ((status == SD_STATUS_ERROR) ||
346             (sendCmd(object->spiHandle, CMD16, SD_SECTOR_SIZE) != 0)) {
347             cardType = SD_NOCARD;
348         }
349     }
350 
351     deassertCS(hwAttrs);
352 
353     object->cardType = cardType;
354 
355     /* Check to see if a card type was determined */
356     if (cardType == SD_NOCARD) {
357         status = SD_STATUS_ERROR;
358     }
359     else {
360         /* Reconfigure the SPI to operate @ 2.5 MHz */
361         SPI_close(object->spiHandle);
362 
363         SPI_Params_init(&spiParams);
364         spiParams.bitRate = 2500000;
365         object->spiHandle = SPI_open(hwAttrs->spiIndex, &spiParams);
366         status = (object->spiHandle == NULL) ? SD_STATUS_ERROR :
367             SD_STATUS_SUCCESS;
368     }
369 
370     SemaphoreP_post(object->lockSem);
371 
372     return (status);
373 }
374 
375 /*
376  *  ======== SDSPI_open ========
377  */
SDSPI_open(SD_Handle handle,SD_Params * params)378 SD_Handle SDSPI_open(SD_Handle handle, SD_Params *params)
379 {
380     uintptr_t            key;
381     int_fast16_t         status;
382     SPI_Params           spiParams;
383     SDSPI_Object        *object = handle->object;
384     SDSPI_HWAttrs const *hwAttrs = handle->hwAttrs;
385 
386     key = HwiP_disable();
387 
388     if (object->isOpen) {
389         HwiP_restore(key);
390 
391         return (NULL);
392     }
393     object->isOpen = true;
394 
395     HwiP_restore(key);
396 
397     /* Configure the SPI CS pin as output set high */
398     status = GPIO_setConfig(hwAttrs->spiCsGpioIndex,
399         GPIO_CFG_OUT_STD | GPIO_CFG_OUT_HIGH);
400     if (status != GPIO_STATUS_SUCCESS) {
401         object->isOpen = false;
402 
403         return (NULL);
404     }
405 
406     object->lockSem = SemaphoreP_createBinary(1);
407     if (object->lockSem == NULL) {
408         object->isOpen = false;
409 
410         return (NULL);
411     }
412 
413     /*
414      * SPI is initially set to 400 kHz to perform SD initialization.  This is
415      * is done to ensure compatibility with older SD cards.  Once the card has
416      * been initialized (in SPI mode) the SPI peripheral will be closed &
417      * reopened at 2.5 MHz.
418      */
419     SPI_Params_init(&spiParams);
420     spiParams.bitRate = 400000;
421     object->spiHandle = SPI_open(hwAttrs->spiIndex, &spiParams);
422     if (object->spiHandle == NULL) {
423         SDSPI_close(handle);
424 
425         return (NULL);
426     }
427 
428     /* Ensure the CS line is de-asserted. */
429     deassertCS(hwAttrs);
430 
431     return (handle);
432 }
433 
434 /*
435  *  ======== SDSPI_read ========
436  */
SDSPI_read(SD_Handle handle,void * buf,int_fast32_t sector,uint_fast32_t sectorCount)437 int_fast16_t SDSPI_read(SD_Handle handle, void *buf, int_fast32_t sector,
438     uint_fast32_t sectorCount)
439 {
440     uint8_t             ffByte = 0xFF;
441     int_fast16_t        status = SD_STATUS_ERROR;
442     SDSPI_Object        *object = handle->object;
443     SDSPI_HWAttrs const *hwAttrs = handle->hwAttrs;
444 
445     if (sectorCount == 0) {
446         return (SD_STATUS_ERROR);
447     }
448 
449     SemaphoreP_pend(object->lockSem, SemaphoreP_WAIT_FOREVER);
450 
451     /*
452      * On a SDSC card, the sector address is a byte address on the SD Card
453      * On a SDHC card, the sector addressing is via sector blocks
454      */
455     if (object->cardType != SD_SDHC) {
456         /* Convert to byte address */
457         sector *= SD_SECTOR_SIZE;
458     }
459 
460     assertCS(hwAttrs);
461 
462     /* Single block read */
463     if (sectorCount == 1) {
464         if ((sendCmd(object->spiHandle, CMD17, sector) == 0) &&
465             recvDataBlock(object->spiHandle, buf, SD_SECTOR_SIZE)) {
466             status = SD_STATUS_SUCCESS;
467         }
468     }
469     /* Multiple block read */
470     else {
471         if (sendCmd(object->spiHandle, CMD18, sector) == 0) {
472             do {
473                 if (!recvDataBlock(object->spiHandle, buf, SD_SECTOR_SIZE)) {
474                     break;
475                 }
476                 buf = (void *) (((uint32_t) buf) + SD_SECTOR_SIZE);
477             } while (--sectorCount);
478 
479             /*
480              * STOP_TRANSMISSION - order is important; always want to send
481              * stop signal
482              */
483             if (sendCmd(object->spiHandle, CMD12, 0) == 0 && sectorCount == 0) {
484                 status = SD_STATUS_SUCCESS;
485             }
486         }
487     }
488 
489     deassertCS(hwAttrs);
490 
491     /* Send a 0xFF with CS high to try to put SD card into low power mode */
492     spiTransfer(object->spiHandle, NULL, &ffByte, 1);
493 
494     SemaphoreP_post(object->lockSem);
495 
496     return (status);
497 }
498 
499 /*
500  *  ======== SDSPI_write ========
501  */
SDSPI_write(SD_Handle handle,const void * buf,int_fast32_t sector,uint_fast32_t sectorCount)502 int_fast16_t SDSPI_write(SD_Handle handle, const void *buf,
503     int_fast32_t sector, uint_fast32_t sectorCount)
504 {
505     int_fast16_t        status = SD_STATUS_SUCCESS;
506     SDSPI_Object        *object = handle->object;
507     SDSPI_HWAttrs const *hwAttrs = handle->hwAttrs;
508 
509     if (sectorCount == 0) {
510         return (SD_STATUS_ERROR);
511     }
512 
513     SemaphoreP_pend(object->lockSem, SemaphoreP_WAIT_FOREVER);
514 
515     /*
516      * On a SDSC card, the sector address is a byte address on the SD Card
517      * On a SDHC card, the sector addressing is via sector blocks
518      */
519     if (object->cardType != SD_SDHC) {
520         /* Convert to byte address if needed */
521         sector *= SD_SECTOR_SIZE;
522     }
523 
524     assertCS(hwAttrs);
525 
526     /* Single block write */
527     if (sectorCount == 1) {
528         if ((sendCmd(object->spiHandle, CMD24, sector) == 0) &&
529             transmitDataBlock(object->spiHandle, (void *) buf, SD_SECTOR_SIZE,
530                 START_BLOCK_TOKEN)) {
531             sectorCount = 0;
532         }
533     }
534     /* Multiple block write */
535     else {
536         if ((object->cardType == SD_SDSC) || (object->cardType == SD_SDHC)) {
537             if (sendCmd(object->spiHandle, CMD55, 0) != 0) {
538                 status = SD_STATUS_ERROR;
539             }
540 
541             /* ACMD23 */
542             if ((status == SD_STATUS_SUCCESS) &&
543                 (sendCmd(object->spiHandle, CMD23, sectorCount) != 0)) {
544                 status = SD_STATUS_ERROR;
545             }
546         }
547 
548         /* WRITE_MULTIPLE_BLOCK command */
549         if ((status == SD_STATUS_SUCCESS) &&
550             (sendCmd(object->spiHandle, CMD25, sector) == 0)) {
551             do {
552                 if (!transmitDataBlock(object->spiHandle, (void *) buf,
553                     SD_SECTOR_SIZE, START_MULTIBLOCK_TOKEN)) {
554                     break;
555                 }
556                 buf = (void *) (((uint32_t) buf) + SD_SECTOR_SIZE);
557             } while (--sectorCount);
558 
559             /* STOP_TRAN token */
560             if (!transmitDataBlock(object->spiHandle, NULL, 0,
561                 STOP_MULTIBLOCK_TOKEN)) {
562                 sectorCount = 1;
563             }
564         }
565     }
566 
567     /*
568      * Wait for SD card to finish storing the data it received. This may help
569      * the card go into low power mode.
570      */
571     waitUntilReady(object->spiHandle);
572 
573     deassertCS(hwAttrs);
574 
575     SemaphoreP_post(object->lockSem);
576 
577     return ((sectorCount) ? SD_STATUS_ERROR : SD_STATUS_SUCCESS);
578 }
579 
580 /*
581  *  ======== assertCS ========
582  */
assertCS(SDSPI_HWAttrs const * hwAttrs)583 static inline void assertCS(SDSPI_HWAttrs const *hwAttrs)
584 {
585     GPIO_write(hwAttrs->spiCsGpioIndex, 0);
586 }
587 
588 /*
589  *  ======== deassertCS ========
590  */
deassertCS(SDSPI_HWAttrs const * hwAttrs)591 static inline void deassertCS(SDSPI_HWAttrs const *hwAttrs)
592 {
593     GPIO_write(hwAttrs->spiCsGpioIndex, 1);
594 }
595 
596 /*
597  *  ======== recvDataBlock ========
598  *  Function to receive a block of data from the SDCard
599  */
recvDataBlock(SPI_Handle handle,void * buf,uint32_t count)600 static bool recvDataBlock(SPI_Handle handle, void *buf, uint32_t count)
601 {
602     uint8_t      rxBuf[2];
603     uint8_t      txBuf[2] = {0xFF, 0xFF};
604     int_fast16_t status;
605     uint32_t     currentTime;
606     uint32_t     startTime;
607     uint32_t     timeout;
608 
609     /*
610      * Wait for SD card to be ready up to 1s.  SD card is ready when the
611      * START_BLOCK_TOKEN is received.
612      */
613     timeout = 1000000/ClockP_getSystemTickPeriod();
614     startTime = ClockP_getSystemTicks();
615     do {
616         status = spiTransfer(handle, &rxBuf, &txBuf, 1);
617         currentTime = ClockP_getSystemTicks();
618     } while ((status == SD_STATUS_SUCCESS) && (rxBuf[0] == 0xFF) &&
619         (currentTime - startTime) < timeout);
620 
621     if (rxBuf[0] != START_BLOCK_TOKEN) {
622         /* Return error if valid data token was not received */
623         return (false);
624     }
625 
626     /* Receive the data block into buffer */
627     if (spiTransfer(handle, buf, NULL, count) != SD_STATUS_SUCCESS) {
628         return (false);
629     }
630 
631     /* Read the 16 bit CRC, but discard it */
632     if (spiTransfer(handle, &rxBuf, &txBuf, 2) != SD_STATUS_SUCCESS) {
633         return (false);
634     }
635 
636     /* Return with success */
637     return (true);
638 }
639 
640 /*
641  *  ======== sendCmd ========
642  *  Function to send a command to the SD card.  Command responses from
643  *  SD card are returned.  (0xFF) is returned on failures.
644  */
sendCmd(SPI_Handle handle,uint8_t cmd,uint32_t arg)645 static uint8_t sendCmd(SPI_Handle handle, uint8_t cmd, uint32_t arg)
646 {
647     uint8_t      i;
648     uint8_t      rxBuf;
649     uint8_t      txBuf[6];
650     int_fast16_t status;
651 
652     if ((cmd != CMD0) && !waitUntilReady(handle)) {
653         return (0xFF);
654     }
655 
656     /* Setup SPI transaction */
657     txBuf[0] = cmd;                  /* Command */
658     txBuf[1] = (uint8_t)(arg >> 24); /* Argument[31..24] */
659     txBuf[2] = (uint8_t)(arg >> 16); /* Argument[23..16] */
660     txBuf[3] = (uint8_t)(arg >> 8);  /* Argument[15..8] */
661     txBuf[4] = (uint8_t) arg;        /* Argument[7..0] */
662 
663     if (cmd == CMD0) {
664         /* CRC for CMD0(0) */
665         txBuf[5] = 0x95;
666     }
667     else if (cmd == CMD8) {
668         /* CRC for CMD8(0x1AA) */
669         txBuf[5] = 0x87;
670     }
671     else {
672         /* Default CRC should be at least 0x01 */
673         txBuf[5] = 0x01;
674     }
675 
676     if (spiTransfer(handle, NULL, &txBuf, 6) != SD_STATUS_SUCCESS) {
677         return (0xFF);
678     }
679 
680     /* Prepare to receive SD card response (send 0xFF) */
681     txBuf[0] = 0xFF;
682 
683     /*
684      * CMD 12 has R1b response which transfers an additional
685      * "busy" byte
686      */
687     if ((cmd == CMD12) &&
688         (spiTransfer(handle, &rxBuf, &txBuf, 1) != SD_STATUS_SUCCESS)) {
689             return (0xFF);
690     }
691 
692     /* Wait for a valid response; 10 attempts */
693     i = 10;
694     do {
695         status = spiTransfer(handle, &rxBuf, &txBuf, 1);
696     } while ((status == SD_STATUS_SUCCESS) && (rxBuf & 0x80) && (--i));
697 
698     /* Return with the response value */
699     return (rxBuf);
700 }
701 
702 /*
703  *  ======== spiTransfer ========
704  *  Returns SD_STATUS_SUCCESS when transfer is completed;
705  *  SD_STATUS_ERROR otherwise.
706  */
spiTransfer(SPI_Handle handle,void * rxBuf,void * txBuf,size_t count)707 static int_fast16_t spiTransfer(SPI_Handle handle, void *rxBuf,
708     void *txBuf, size_t count) {
709     int_fast16_t    status;
710     SPI_Transaction transaction;
711 
712     transaction.rxBuf = rxBuf;
713     transaction.txBuf = txBuf;
714     transaction.count = count;
715 
716     status = (SPI_transfer(handle, &transaction)) ?
717         SD_STATUS_SUCCESS : SD_STATUS_ERROR;
718 
719     return (status);
720 }
721 
722 /*
723  *  ======== transmitDataBlock ========
724  *  Function to transmit a block of data to the SD card.  A valid command
725  *  token must be sent to the SD card prior to sending the data block.
726  *  The available tokens are:
727  *      START_BLOCK_TOKEN
728  *      START_MULTIBLOCK_TOKEN
729  *      STOP_MULTIBLOCK_TOKEN
730  */
transmitDataBlock(SPI_Handle handle,void * buf,uint32_t count,uint8_t token)731 static bool transmitDataBlock(SPI_Handle handle, void *buf, uint32_t count,
732     uint8_t token)
733 {
734     uint8_t rxBuf;
735     uint8_t txBuf[2] = {0xFF, 0xFF};
736 
737     if (!waitUntilReady(handle)) {
738         return (false);
739     }
740 
741     /* transmit data token */
742     txBuf[0] = token;
743     if (spiTransfer(handle, NULL, &txBuf, 1) != SD_STATUS_SUCCESS) {
744         return (false);
745     }
746 
747     /* Send data only when token != STOP_MULTIBLOCK_TOKEN */
748     if (token != STOP_MULTIBLOCK_TOKEN) {
749         /* Write data to the SD card */
750         if (spiTransfer(handle, NULL, buf, count) != SD_STATUS_SUCCESS) {
751             return (false);
752         }
753 
754         /* Receive the 16 bit CRC, but discard it */
755         txBuf[0] = (0xFF);
756         if (spiTransfer(handle, NULL, &txBuf, 2) != SD_STATUS_SUCCESS) {
757             return (false);
758         }
759 
760         /* Receive data response token from SD card */
761         if (spiTransfer(handle, &rxBuf, &txBuf, 1) != SD_STATUS_SUCCESS) {
762             return (false);
763         }
764 
765         /* Check data response; return error if data was rejected  */
766         if ((rxBuf & 0x1F) != 0x05) {
767             return (false);
768         }
769     }
770 
771     return (true);
772 }
773 
774 /*
775  *  ======== waitUntilReady ========
776  *  Function to check if the SD card is busy.
777  *
778  *  Returns true if SD card is ready; false indicates the SD card is still busy
779  *  & a timeout occurred.
780  */
waitUntilReady(SPI_Handle handle)781 static bool waitUntilReady(SPI_Handle handle)
782 {
783     uint8_t      rxDummy;
784     uint8_t      txDummy = 0xFF;
785     int_fast16_t status;
786     uint32_t     currentTime;
787     uint32_t     startTime;
788     uint32_t     timeout;
789 
790     /* Wait up to 1s for data packet */
791     timeout = 1000000/ClockP_getSystemTickPeriod();
792     startTime = ClockP_getSystemTicks();
793     do {
794         status = spiTransfer(handle, &rxDummy, &txDummy, 1);
795         currentTime = ClockP_getSystemTicks();
796     } while ((status == SD_STATUS_SUCCESS) && (rxDummy != 0xFF) &&
797         (currentTime - startTime) < timeout);
798 
799     return (rxDummy == 0xFF);
800 }
801