2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
21 /* Adaptation of original driver to SDIO: Chris Hockuba (https://github.com/conkerkh) */
29 #ifdef USE_SDCARD_SDIO
31 #include "drivers/nvic.h"
32 #include "drivers/io.h"
33 #include "drivers/dma.h"
34 #include "drivers/dma_reqmap.h"
36 #include "drivers/time.h"
38 #include "pg/bus_spi.h" // For spiPinConfig_t, which is unused but should be defined
41 #include "drivers/sdcard.h"
42 #include "drivers/sdcard_impl.h"
43 #include "drivers/sdcard_standard.h"
44 #include "drivers/sdmmc_sdio.h"
46 // Use this to speed up writing to SDCARD... asyncfatfs has limited support for multiblock write
47 #define FATFS_BLOCK_CACHE_SIZE 16
48 uint8_t writeCache
[512 * FATFS_BLOCK_CACHE_SIZE
] __attribute__ ((aligned (4)));
49 uint32_t cacheCount
= 0;
51 void cache_write(uint8_t *buffer
)
53 if (cacheCount
== sizeof(writeCache
)) {
57 memcpy(&writeCache
[cacheCount
], buffer
, 512);
61 uint16_t cache_getCount(void)
63 return (cacheCount
/ 512);
66 void cache_reset(void)
72 * Returns true if the card has already been, or is currently, initializing and hasn't encountered enough errors to
73 * trip our error threshold and be disabled (i.e. our card is in and working!)
75 static bool sdcardSdio_isFunctional(void)
77 return sdcard
.state
!= SDCARD_STATE_NOT_PRESENT
;
81 * Handle a failure of an SD card operation by resetting the card back to its initialization phase.
83 * Increments the failure counter, and when the failure threshold is reached, disables the card until
84 * the next call to sdcard_init().
86 static void sdcard_reset(void)
89 sdcard
.failureCount
++;
90 if (sdcard
.failureCount
>= SDCARD_MAX_CONSECUTIVE_FAILURES
|| !sdcard_isInserted()) {
91 sdcard
.state
= SDCARD_STATE_NOT_PRESENT
;
93 sdcard
.operationStartTime
= millis();
94 sdcard
.state
= SDCARD_STATE_RESET
;
100 SDCARD_RECEIVE_SUCCESS
,
101 SDCARD_RECEIVE_BLOCK_IN_PROGRESS
,
103 } sdcardReceiveBlockStatus_e
;
106 * Attempt to receive a data block from the SD card.
108 * Return true on success, otherwise the card has not responded yet and you should retry later.
110 static sdcardReceiveBlockStatus_e
sdcard_receiveDataBlock(uint8_t *buffer
, int count
)
114 SD_Error_t ret
= SD_CheckRead();
116 if (ret
== SD_BUSY
) {
117 return SDCARD_RECEIVE_BLOCK_IN_PROGRESS
;
120 if (SD_GetState() != true) {
121 return SDCARD_RECEIVE_ERROR
;
124 return SDCARD_RECEIVE_SUCCESS
;
127 static bool sdcard_receiveCID(void)
129 SD_CardInfo_t
*sdinfo
= &SD_CardInfo
;
130 SD_Error_t error
= SD_GetCardInfo();
135 sdcard
.metadata
.manufacturerID
= sdinfo
->SD_cid
.ManufacturerID
;
136 sdcard
.metadata
.oemID
= sdinfo
->SD_cid
.OEM_AppliID
;
137 sdcard
.metadata
.productName
[0] = (sdinfo
->SD_cid
.ProdName1
& 0xFF000000) >> 24;
138 sdcard
.metadata
.productName
[1] = (sdinfo
->SD_cid
.ProdName1
& 0x00FF0000) >> 16;
139 sdcard
.metadata
.productName
[2] = (sdinfo
->SD_cid
.ProdName1
& 0x0000FF00) >> 8;
140 sdcard
.metadata
.productName
[3] = (sdinfo
->SD_cid
.ProdName1
& 0x000000FF) >> 0;
141 sdcard
.metadata
.productName
[4] = sdinfo
->SD_cid
.ProdName2
;
142 sdcard
.metadata
.productRevisionMajor
= sdinfo
->SD_cid
.ProdRev
>> 4;
143 sdcard
.metadata
.productRevisionMinor
= sdinfo
->SD_cid
.ProdRev
& 0x0F;
144 sdcard
.metadata
.productSerial
= sdinfo
->SD_cid
.ProdSN
;
145 sdcard
.metadata
.productionYear
= (((sdinfo
->SD_cid
.ManufactDate
& 0x0F00) >> 8) | ((sdinfo
->SD_cid
.ManufactDate
& 0xFF) >> 4)) + 2000;
146 sdcard
.metadata
.productionMonth
= sdinfo
->SD_cid
.ManufactDate
& 0x000F;
151 static bool sdcard_fetchCSD(void)
153 /* The CSD command's data block should always arrive within 8 idle clock cycles (SD card spec). This is because
154 * the information about card latency is stored in the CSD register itself, so we can't use that yet!
156 SD_CardInfo_t
*sdinfo
= &SD_CardInfo
;
158 error
= SD_GetCardInfo();
163 sdcard
.metadata
.numBlocks
= sdinfo
->CardCapacity
;
168 * Check if the SD Card has completed its startup sequence. Must be called with sdcard.state == SDCARD_STATE_INITIALIZATION.
170 * Returns true if the card has finished its init process.
172 static bool sdcard_checkInitDone(void)
175 SD_CardType_t
*sdtype
= &SD_CardType
;
176 SD_Error_t errorState
= SD_GetCardInfo();
177 if (errorState
!= SD_OK
) {
181 sdcard
.version
= (*sdtype
) ? 2 : 1;
182 sdcard
.highCapacity
= (*sdtype
== 2) ? 1 : 0;
186 // When card init is complete, the idle bit in the response becomes zero.
191 * Begin the initialization process for the SD card. This must be called first before any other sdcard_ routine.
193 static void sdcardSdio_init(const sdcardConfig_t
*config
, const spiPinConfig_t
*spiConfig
)
197 sdcard
.enabled
= config
->mode
;
198 if (!sdcard
.enabled
) {
199 sdcard
.state
= SDCARD_STATE_NOT_PRESENT
;
204 #if !defined(STM32H7) // H7 uses IDMA
205 const dmaChannelSpec_t
*dmaChannelSpec
= dmaGetChannelSpecByPeripheral(DMA_PERIPH_SDIO
, 0, sdioConfig()->dmaopt
);
207 if (!dmaChannelSpec
) {
208 sdcard
.state
= SDCARD_STATE_NOT_PRESENT
;
212 sdcard
.dmaIdentifier
= dmaGetIdentifier(dmaChannelSpec
->ref
);
214 if (sdcard
.dmaIdentifier
== 0) {
215 sdcard
.state
= SDCARD_STATE_NOT_PRESENT
;
220 if (sdioConfig()->useCache
) {
226 #if defined(STM32H7) // H7 uses IDMA
229 SD_Initialize_LL((DMA_ARCH_TYPE
*)dmaChannelSpec
->ref
);
232 SD_Initialize_LL(SDCARD_SDIO_DMA_OPT
);
235 if (sdcard_isInserted()) {
236 if (SD_Init() != 0) {
237 sdcard
.state
= SDCARD_STATE_NOT_PRESENT
;
238 sdcard
.failureCount
++;
242 sdcard
.state
= SDCARD_STATE_NOT_PRESENT
;
243 sdcard
.failureCount
++;
247 sdcard
.operationStartTime
= millis();
248 sdcard
.state
= SDCARD_STATE_RESET
;
249 sdcard
.failureCount
= 0;
253 * Returns true if the card is ready to accept read/write commands.
255 static bool sdcard_isReady()
257 return sdcard
.state
== SDCARD_STATE_READY
|| sdcard
.state
== SDCARD_STATE_WRITING_MULTIPLE_BLOCKS
;
261 * Send the stop-transmission token to complete a multi-block write.
264 * SDCARD_OPERATION_IN_PROGRESS - We're now waiting for that stop to complete, the card will enter
265 * the SDCARD_STATE_STOPPING_MULTIPLE_BLOCK_WRITE state.
266 * SDCARD_OPERATION_SUCCESS - The multi-block write finished immediately, the card will enter
267 * the SDCARD_READY state.
270 static sdcardOperationStatus_e
sdcard_endWriteBlocks()
272 sdcard
.multiWriteBlocksRemain
= 0;
273 if (sdcard
.useCache
) {
277 // 8 dummy clocks to guarantee N_WR clocks between the last card response and this token
279 // Card may choose to raise a busy (non-0xFF) signal after at most N_BR (1 byte) delay
281 sdcard
.state
= SDCARD_STATE_READY
;
282 return SDCARD_OPERATION_SUCCESS
;
284 sdcard
.state
= SDCARD_STATE_STOPPING_MULTIPLE_BLOCK_WRITE
;
285 sdcard
.operationStartTime
= millis();
287 return SDCARD_OPERATION_IN_PROGRESS
;
291 * Call periodically for the SD card to perform in-progress transfers.
293 * Returns true if the card is ready to accept commands.
295 static bool sdcardSdio_poll(void)
297 if (!sdcard
.enabled
) {
298 sdcard
.state
= SDCARD_STATE_NOT_PRESENT
;
302 #ifdef SDCARD_PROFILING
303 bool profilingComplete
;
307 switch (sdcard
.state
) {
308 case SDCARD_STATE_RESET
:
309 //HAL Takes care of voltage crap.
310 sdcard
.state
= SDCARD_STATE_CARD_INIT_IN_PROGRESS
;
314 case SDCARD_STATE_CARD_INIT_IN_PROGRESS
:
315 if (sdcard_checkInitDone()) {
316 // Now fetch the CSD and CID registers
317 if (sdcard_fetchCSD()) {
318 sdcard
.state
= SDCARD_STATE_INITIALIZATION_RECEIVE_CID
;
326 case SDCARD_STATE_INITIALIZATION_RECEIVE_CID
:
327 if (sdcard_receiveCID()) {
329 /* The spec is a little iffy on what the default block size is for Standard Size cards (it can be changed on
330 * standard size cards) so let's just set it to 512 explicitly so we don't have a problem.
332 // if (!sdcard.highCapacity && SDMMC_CmdBlockLength(_HSD.Instance, SDCARD_BLOCK_SIZE)) {
337 sdcard
.multiWriteBlocksRemain
= 0;
339 sdcard
.state
= SDCARD_STATE_READY
;
341 } // else keep waiting for the CID to arrive
343 case SDCARD_STATE_SENDING_WRITE
:
344 // Have we finished sending the write yet?
345 if (SD_CheckWrite() == SD_OK
) {
347 // The SD card is now busy committing that write to the card
348 sdcard
.state
= SDCARD_STATE_WAITING_FOR_WRITE
;
349 sdcard
.operationStartTime
= millis();
351 // Since we've transmitted the buffer we can go ahead and tell the caller their operation is complete
352 if (sdcard
.pendingOperation
.callback
) {
353 sdcard
.pendingOperation
.callback(SDCARD_BLOCK_OPERATION_WRITE
, sdcard
.pendingOperation
.blockIndex
, sdcard
.pendingOperation
.buffer
, sdcard
.pendingOperation
.callbackData
);
357 case SDCARD_STATE_WAITING_FOR_WRITE
:
359 #ifdef SDCARD_PROFILING
360 profilingComplete
= true;
363 sdcard
.failureCount
= 0; // Assume the card is good if it can complete a write
365 // Still more blocks left to write in a multi-block chain?
366 if (sdcard
.multiWriteBlocksRemain
> 1) {
367 sdcard
.multiWriteBlocksRemain
--;
368 sdcard
.multiWriteNextBlock
++;
369 if (sdcard
.useCache
) {
372 sdcard
.state
= SDCARD_STATE_WRITING_MULTIPLE_BLOCKS
;
373 } else if (sdcard
.multiWriteBlocksRemain
== 1) {
374 // This function changes the sd card state for us whether immediately succesful or delayed:
375 sdcard_endWriteBlocks();
377 sdcard
.state
= SDCARD_STATE_READY
;
380 #ifdef SDCARD_PROFILING
381 if (profilingComplete
&& sdcard
.profiler
) {
382 sdcard
.profiler(SDCARD_BLOCK_OPERATION_WRITE
, sdcard
.pendingOperation
.blockIndex
, micros() - sdcard
.pendingOperation
.profileStartTime
);
385 } else if (millis() > sdcard
.operationStartTime
+ SDCARD_TIMEOUT_WRITE_MSEC
) {
387 * The caller has already been told that their write has completed, so they will have discarded
388 * their buffer and have no hope of retrying the operation. But this should be very rare and it allows
389 * them to reuse their buffer milliseconds faster than they otherwise would.
395 case SDCARD_STATE_READING
:
396 switch (sdcard_receiveDataBlock(sdcard
.pendingOperation
.buffer
, SDCARD_BLOCK_SIZE
)) {
397 case SDCARD_RECEIVE_SUCCESS
:
399 sdcard
.state
= SDCARD_STATE_READY
;
400 sdcard
.failureCount
= 0; // Assume the card is good if it can complete a read
402 #ifdef SDCARD_PROFILING
403 if (sdcard
.profiler
) {
404 sdcard
.profiler(SDCARD_BLOCK_OPERATION_READ
, sdcard
.pendingOperation
.blockIndex
, micros() - sdcard
.pendingOperation
.profileStartTime
);
408 if (sdcard
.pendingOperation
.callback
) {
409 sdcard
.pendingOperation
.callback(
410 SDCARD_BLOCK_OPERATION_READ
,
411 sdcard
.pendingOperation
.blockIndex
,
412 sdcard
.pendingOperation
.buffer
,
413 sdcard
.pendingOperation
.callbackData
417 case SDCARD_RECEIVE_BLOCK_IN_PROGRESS
:
418 if (millis() <= sdcard
.operationStartTime
+ SDCARD_TIMEOUT_READ_MSEC
) {
419 break; // Timeout not reached yet so keep waiting
421 // Timeout has expired, so fall through to convert to a fatal error
423 case SDCARD_RECEIVE_ERROR
:
428 case SDCARD_STATE_STOPPING_MULTIPLE_BLOCK_WRITE
:
430 sdcard
.state
= SDCARD_STATE_READY
;
432 #ifdef SDCARD_PROFILING
433 if (sdcard
.profiler
) {
434 sdcard
.profiler(SDCARD_BLOCK_OPERATION_WRITE
, sdcard
.pendingOperation
.blockIndex
, micros() - sdcard
.pendingOperation
.profileStartTime
);
437 } else if (millis() > sdcard
.operationStartTime
+ SDCARD_TIMEOUT_WRITE_MSEC
) {
442 case SDCARD_STATE_NOT_PRESENT
:
447 // Is the card's initialization taking too long?
448 if (sdcard
.state
>= SDCARD_STATE_RESET
&& sdcard
.state
< SDCARD_STATE_READY
449 && millis() - sdcard
.operationStartTime
> SDCARD_TIMEOUT_INIT_MILLIS
) {
453 return sdcard_isReady();
457 * Write the 512-byte block from the given buffer into the block with the given index.
459 * If the write does not complete immediately, your callback will be called later. If the write was successful, the
460 * buffer pointer will be the same buffer you originally passed in, otherwise the buffer will be set to NULL.
463 * SDCARD_OPERATION_IN_PROGRESS - Your buffer is currently being transmitted to the card and your callback will be
464 * called later to report the completion. The buffer pointer must remain valid until
466 * SDCARD_OPERATION_SUCCESS - Your buffer has been transmitted to the card now.
467 * SDCARD_OPERATION_BUSY - The card is already busy and cannot accept your write
468 * SDCARD_OPERATION_FAILURE - Your write was rejected by the card, card will be reset
470 static sdcardOperationStatus_e
sdcardSdio_writeBlock(uint32_t blockIndex
, uint8_t *buffer
, sdcard_operationCompleteCallback_c callback
, uint32_t callbackData
)
473 #ifdef SDCARD_PROFILING
474 sdcard
.pendingOperation
.profileStartTime
= micros();
478 switch (sdcard
.state
) {
479 case SDCARD_STATE_WRITING_MULTIPLE_BLOCKS
:
480 // Do we need to cancel the previous multi-block write?
481 if (blockIndex
!= sdcard
.multiWriteNextBlock
) {
482 if (sdcard_endWriteBlocks() == SDCARD_OPERATION_SUCCESS
) {
483 // Now we've entered the ready state, we can try again
486 return SDCARD_OPERATION_BUSY
;
490 // We're continuing a multi-block write
492 case SDCARD_STATE_READY
:
495 return SDCARD_OPERATION_BUSY
;
498 sdcard
.pendingOperation
.buffer
= buffer
;
499 sdcard
.pendingOperation
.blockIndex
= blockIndex
;
501 uint16_t block_count
= 1;
502 if ((cache_getCount() < FATFS_BLOCK_CACHE_SIZE
) &&
503 (sdcard
.multiWriteBlocksRemain
!= 0) && sdcard
.useCache
) {
505 if (cache_getCount() == FATFS_BLOCK_CACHE_SIZE
|| sdcard
.multiWriteBlocksRemain
== 1) {
507 buffer
= (uint8_t*)writeCache
;
508 //Recalculate block index
509 blockIndex
-= cache_getCount() - 1;
510 block_count
= cache_getCount();
512 sdcard
.multiWriteBlocksRemain
--;
513 sdcard
.multiWriteNextBlock
++;
514 sdcard
.state
= SDCARD_STATE_READY
;
515 return SDCARD_OPERATION_SUCCESS
;
519 sdcard
.pendingOperation
.callback
= callback
;
520 sdcard
.pendingOperation
.callbackData
= callbackData
;
521 sdcard
.pendingOperation
.chunkIndex
= 1; // (for non-DMA transfers) we've sent chunk #0 already
522 sdcard
.state
= SDCARD_STATE_SENDING_WRITE
;
524 if (SD_WriteBlocks_DMA(blockIndex
, (uint32_t*) buffer
, 512, block_count
) != SD_OK
) {
525 /* Our write was rejected! This could be due to a bad address but we hope not to attempt that, so assume
526 * the card is broken and needs reset.
530 // Announce write failure:
531 if (sdcard
.pendingOperation
.callback
) {
532 sdcard
.pendingOperation
.callback(SDCARD_BLOCK_OPERATION_WRITE
, sdcard
.pendingOperation
.blockIndex
, NULL
, sdcard
.pendingOperation
.callbackData
);
534 return SDCARD_OPERATION_FAILURE
;
537 return SDCARD_OPERATION_IN_PROGRESS
;
541 * Begin writing a series of consecutive blocks beginning at the given block index. This will allow (but not require)
542 * the SD card to pre-erase the number of blocks you specifiy, which can allow the writes to complete faster.
544 * Afterwards, just call sdcard_writeBlock() as normal to write those blocks consecutively.
546 * It's okay to abort the multi-block write at any time by writing to a non-consecutive address, or by performing a read.
549 * SDCARD_OPERATION_SUCCESS - Multi-block write has been queued
550 * SDCARD_OPERATION_BUSY - The card is already busy and cannot accept your write
551 * SDCARD_OPERATION_FAILURE - A fatal error occured, card will be reset
553 static sdcardOperationStatus_e
sdcardSdio_beginWriteBlocks(uint32_t blockIndex
, uint32_t blockCount
)
555 if (sdcard
.state
!= SDCARD_STATE_READY
) {
556 if (sdcard
.state
== SDCARD_STATE_WRITING_MULTIPLE_BLOCKS
) {
557 if (blockIndex
== sdcard
.multiWriteNextBlock
) {
558 // Assume that the caller wants to continue the multi-block write they already have in progress!
559 return SDCARD_OPERATION_SUCCESS
;
560 } else if (sdcard_endWriteBlocks() != SDCARD_OPERATION_SUCCESS
) {
561 return SDCARD_OPERATION_BUSY
;
562 } // Else we've completed the previous multi-block write and can fall through to start the new one
564 return SDCARD_OPERATION_BUSY
;
568 sdcard
.state
= SDCARD_STATE_WRITING_MULTIPLE_BLOCKS
;
569 sdcard
.multiWriteBlocksRemain
= blockCount
;
570 sdcard
.multiWriteNextBlock
= blockIndex
;
571 return SDCARD_OPERATION_SUCCESS
;
575 * Read the 512-byte block with the given index into the given 512-byte buffer.
577 * When the read completes, your callback will be called. If the read was successful, the buffer pointer will be the
578 * same buffer you originally passed in, otherwise the buffer will be set to NULL.
580 * You must keep the pointer to the buffer valid until the operation completes!
583 * true - The operation was successfully queued for later completion, your callback will be called later
584 * false - The operation could not be started due to the card being busy (try again later).
586 static bool sdcardSdio_readBlock(uint32_t blockIndex
, uint8_t *buffer
, sdcard_operationCompleteCallback_c callback
, uint32_t callbackData
)
588 if (sdcard
.state
!= SDCARD_STATE_READY
) {
589 if (sdcard
.state
== SDCARD_STATE_WRITING_MULTIPLE_BLOCKS
) {
590 if (sdcard_endWriteBlocks() != SDCARD_OPERATION_SUCCESS
) {
598 #ifdef SDCARD_PROFILING
599 sdcard
.pendingOperation
.profileStartTime
= micros();
602 // Standard size cards use byte addressing, high capacity cards use block addressing
603 uint8_t status
= SD_ReadBlocks_DMA(blockIndex
, (uint32_t*) buffer
, 512, 1);
605 if (status
== SD_OK
) {
606 sdcard
.pendingOperation
.buffer
= buffer
;
607 sdcard
.pendingOperation
.blockIndex
= blockIndex
;
608 sdcard
.pendingOperation
.callback
= callback
;
609 sdcard
.pendingOperation
.callbackData
= callbackData
;
611 sdcard
.state
= SDCARD_STATE_READING
;
613 sdcard
.operationStartTime
= millis();
618 if (sdcard
.pendingOperation
.callback
) {
619 sdcard
.pendingOperation
.callback(
620 SDCARD_BLOCK_OPERATION_READ
,
621 sdcard
.pendingOperation
.blockIndex
,
623 sdcard
.pendingOperation
.callbackData
631 * Returns true if the SD card has successfully completed its startup procedures.
633 static bool sdcardSdio_isInitialized(void)
635 return sdcard
.state
>= SDCARD_STATE_READY
;
638 static const sdcardMetadata_t
* sdcardSdio_getMetadata(void)
640 return &sdcard
.metadata
;
643 #ifdef SDCARD_PROFILING
645 static void sdcardSdio_setProfilerCallback(sdcard_profilerCallback_c callback
)
647 sdcard
.profiler
= callback
;
652 sdcardVTable_t sdcardSdioVTable
= {
655 sdcardSdio_readBlock
,
656 sdcardSdio_beginWriteBlocks
,
657 sdcardSdio_writeBlock
,
659 sdcardSdio_isFunctional
,
660 sdcardSdio_isInitialized
,
661 sdcardSdio_getMetadata
,
662 #ifdef SDCARD_PROFILING
663 sdcardSdio_setProfilerCallback
,