Blackbox device type 'file' (SITL) considered working when file handler is available
[inav.git] / src / main / drivers / sdcard / sdcard_sdio.c
blob58fc79acc1f23117f7f42fa9149e0d4662defe69
1 /*
2 * This file is part of INAV, Cleanflight and Betaflight.
4 * INAV, 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)
8 * any later version.
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) */
23 #include <stdbool.h>
24 #include <stdint.h>
25 #include <string.h>
27 #include "platform.h"
29 #include "build/debug.h"
30 #include "common/utils.h"
32 #include "drivers/time.h"
33 #include "drivers/nvic.h"
34 #include "drivers/io.h"
35 #include "drivers/bus.h"
36 #include "drivers/bus_spi.h"
37 #include "drivers/dma.h"
39 #include "drivers/sdcard/sdcard.h"
40 #include "drivers/sdcard/sdcard_impl.h"
41 #include "drivers/sdcard/sdcard_standard.h"
42 #include "drivers/sdcard/sdmmc_sdio.h"
44 #include "scheduler/protothreads.h"
46 #ifdef USE_SDCARD_SDIO
48 //#define USE_SDCARD_SDIO_CACHE
50 #if !defined(SDCARD_SDIO_DMA)
51 #define SDCARD_SDIO_DMA DMA_TAG(2,3,4)
52 #endif
54 #if defined(USE_SDCARD_SDIO_CACHE)
55 // Use this to speed up writing to SDCARD... asyncfatfs has limited support for multiblock write
56 #define FATFS_BLOCK_CACHE_SIZE 16
57 uint8_t writeCache[512 * FATFS_BLOCK_CACHE_SIZE] __attribute__ ((aligned (4)));
58 uint32_t cacheCount = 0;
60 void cache_write(uint8_t *buffer)
62 if (cacheCount == sizeof(writeCache)) {
63 // Prevents overflow
64 return;
66 memcpy(&writeCache[cacheCount], buffer, 512);
67 cacheCount += 512;
70 uint16_t cache_getCount(void)
72 return (cacheCount / 512);
75 void cache_reset(void)
77 cacheCount = 0;
79 #endif
81 /**
82 * Returns true if the card has already been, or is currently, initializing and hasn't encountered enough errors to
83 * trip our error threshold and be disabled (i.e. our card is in and working!)
85 static bool sdcardSdio_isFunctional(void)
87 return sdcard.state != SDCARD_STATE_NOT_PRESENT;
90 /**
91 * Handle a failure of an SD card operation by resetting the card back to its initialization phase.
93 * Increments the failure counter, and when the failure threshold is reached, disables the card until
94 * the next call to sdcard_init().
96 static void sdcardSdio_reset(void)
98 if (SD_Init() != 0) {
99 sdcard.failureCount++;
100 if (sdcard.failureCount >= SDCARD_MAX_CONSECUTIVE_FAILURES || !sdcard_isInserted()) {
101 sdcard.state = SDCARD_STATE_NOT_PRESENT;
102 } else {
103 sdcard.operationStartTime = millis();
104 sdcard.state = SDCARD_STATE_RESET;
109 typedef enum {
110 SDCARD_RECEIVE_SUCCESS,
111 SDCARD_RECEIVE_BLOCK_IN_PROGRESS,
112 SDCARD_RECEIVE_ERROR
113 } sdcardReceiveBlockStatus_e;
116 * Attempt to receive a data block from the SD card.
118 * Return true on success, otherwise the card has not responded yet and you should retry later.
120 static sdcardReceiveBlockStatus_e sdcard_receiveDataBlock(uint8_t *buffer, int count)
122 UNUSED(buffer);
123 UNUSED(count);
124 SD_Error_t ret = SD_CheckRead();
126 if (ret == SD_BUSY) {
127 return SDCARD_RECEIVE_BLOCK_IN_PROGRESS;
130 if (SD_GetState() != true) {
131 return SDCARD_RECEIVE_ERROR;
134 return SDCARD_RECEIVE_SUCCESS;
137 static bool sdcard_receiveCID(void)
139 SD_CardInfo_t *sdinfo = &SD_CardInfo;
140 SD_Error_t error = SD_GetCardInfo();
141 if (error) {
142 return false;
145 sdcard.metadata.manufacturerID = sdinfo->SD_cid.ManufacturerID;
146 sdcard.metadata.oemID = sdinfo->SD_cid.OEM_AppliID;
147 sdcard.metadata.productName[0] = (sdinfo->SD_cid.ProdName1 & 0xFF000000) >> 24;
148 sdcard.metadata.productName[1] = (sdinfo->SD_cid.ProdName1 & 0x00FF0000) >> 16;
149 sdcard.metadata.productName[2] = (sdinfo->SD_cid.ProdName1 & 0x0000FF00) >> 8;
150 sdcard.metadata.productName[3] = (sdinfo->SD_cid.ProdName1 & 0x000000FF) >> 0;
151 sdcard.metadata.productName[4] = sdinfo->SD_cid.ProdName2;
152 sdcard.metadata.productRevisionMajor = sdinfo->SD_cid.ProdRev >> 4;
153 sdcard.metadata.productRevisionMinor = sdinfo->SD_cid.ProdRev & 0x0F;
154 sdcard.metadata.productSerial = sdinfo->SD_cid.ProdSN;
155 sdcard.metadata.productionYear = (((sdinfo->SD_cid.ManufactDate & 0x0F00) >> 8) | ((sdinfo->SD_cid.ManufactDate & 0xFF) >> 4)) + 2000;
156 sdcard.metadata.productionMonth = sdinfo->SD_cid.ManufactDate & 0x000F;
158 return true;
161 static bool sdcard_fetchCSD(void)
163 /* The CSD command's data block should always arrive within 8 idle clock cycles (SD card spec). This is because
164 * the information about card latency is stored in the CSD register itself, so we can't use that yet!
166 SD_CardInfo_t *sdinfo = &SD_CardInfo;
167 SD_Error_t error;
168 error = SD_GetCardInfo();
169 if (error) {
170 return false;
173 sdcard.metadata.numBlocks = sdinfo->CardCapacity;
174 return true;
178 * Check if the SD Card has completed its startup sequence. Must be called with sdcard.state == SDCARD_STATE_INITIALIZATION.
180 * Returns true if the card has finished its init process.
182 static bool sdcard_checkInitDone(void)
184 if (SD_GetState()) {
185 SD_CardType_t *sdtype = &SD_CardType;
186 SD_Error_t errorState = SD_GetCardInfo();
187 if (errorState != SD_OK) {
188 return false;
191 sdcard.version = (*sdtype) ? 2 : 1;
192 sdcard.highCapacity = (*sdtype == 2) ? 1 : 0;
193 return true;
196 // When card init is complete, the idle bit in the response becomes zero.
197 return false;
201 * Returns true if the card is ready to accept read/write commands.
203 static bool sdcard_isReady(void)
205 return sdcard.state == SDCARD_STATE_READY || sdcard.state == SDCARD_STATE_WRITING_MULTIPLE_BLOCKS;
209 * Send the stop-transmission token to complete a multi-block write.
211 * Returns:
212 * SDCARD_OPERATION_IN_PROGRESS - We're now waiting for that stop to complete, the card will enter
213 * the SDCARD_STATE_STOPPING_MULTIPLE_BLOCK_WRITE state.
214 * SDCARD_OPERATION_SUCCESS - The multi-block write finished immediately, the card will enter
215 * the SDCARD_READY state.
218 static sdcardOperationStatus_e sdcard_endWriteBlocks(void)
220 sdcard.multiWriteBlocksRemain = 0;
222 #if defined(USE_SDCARD_SDIO_CACHE)
223 cache_reset();
224 #endif
226 // Card may choose to raise a busy (non-0xFF) signal after at most N_BR (1 byte) delay
227 if (SD_GetState()) {
228 sdcard.state = SDCARD_STATE_READY;
229 return SDCARD_OPERATION_SUCCESS;
230 } else {
231 sdcard.state = SDCARD_STATE_STOPPING_MULTIPLE_BLOCK_WRITE;
232 sdcard.operationStartTime = millis();
234 return SDCARD_OPERATION_IN_PROGRESS;
238 * Call periodically for the SD card to perform in-progress transfers.
240 * Returns true if the card is ready to accept commands.
242 static bool sdcardSdio_poll(void)
244 #if !defined(STM32H7) // H7 uses IDMA
245 if (!sdcard.dma) {
246 sdcard.state = SDCARD_STATE_NOT_PRESENT;
247 return false;
249 #endif
250 doMore:
251 switch (sdcard.state) {
252 case SDCARD_STATE_RESET:
253 //HAL Takes care of voltage crap.
254 sdcard.state = SDCARD_STATE_CARD_INIT_IN_PROGRESS;
255 goto doMore;
256 break;
258 case SDCARD_STATE_CARD_INIT_IN_PROGRESS:
259 if (sdcard_checkInitDone()) {
260 // Now fetch the CSD and CID registers
261 if (sdcard_fetchCSD()) {
262 sdcard.state = SDCARD_STATE_INITIALIZATION_RECEIVE_CID;
263 goto doMore;
264 } else {
265 sdcardSdio_reset();
266 goto doMore;
269 break;
270 case SDCARD_STATE_INITIALIZATION_RECEIVE_CID:
271 if (sdcard_receiveCID()) {
273 /* The spec is a little iffy on what the default block size is for Standard Size cards (it can be changed on
274 * standard size cards) so let's just set it to 512 explicitly so we don't have a problem.
276 // if (!sdcard.highCapacity && SDMMC_CmdBlockLength(_HSD.Instance, SDCARD_BLOCK_SIZE)) {
277 // sdcardSdio_reset();
278 // goto doMore;
279 // }
281 sdcard.multiWriteBlocksRemain = 0;
283 sdcard.state = SDCARD_STATE_READY;
284 goto doMore;
285 } // else keep waiting for the CID to arrive
286 break;
287 case SDCARD_STATE_SENDING_WRITE:
288 // Have we finished sending the write yet?
289 if (SD_CheckWrite() == SD_OK) {
291 // The SD card is now busy committing that write to the card
292 sdcard.state = SDCARD_STATE_WAITING_FOR_WRITE;
293 sdcard.operationStartTime = millis();
295 // Since we've transmitted the buffer we can go ahead and tell the caller their operation is complete
296 if (sdcard.pendingOperation.callback) {
297 sdcard.pendingOperation.callback(SDCARD_BLOCK_OPERATION_WRITE, sdcard.pendingOperation.blockIndex, sdcard.pendingOperation.buffer, sdcard.pendingOperation.callbackData);
300 break;
301 case SDCARD_STATE_WAITING_FOR_WRITE:
302 if (SD_GetState()) {
303 sdcard.failureCount = 0; // Assume the card is good if it can complete a write
305 // Still more blocks left to write in a multi-block chain?
306 if (sdcard.multiWriteBlocksRemain > 1) {
307 sdcard.multiWriteBlocksRemain--;
308 sdcard.multiWriteNextBlock++;
309 #if defined(USE_SDCARD_SDIO_CACHE)
310 cache_reset();
311 #endif
312 sdcard.state = SDCARD_STATE_WRITING_MULTIPLE_BLOCKS;
313 } else if (sdcard.multiWriteBlocksRemain == 1) {
314 // This function changes the sd card state for us whether immediately succesful or delayed:
315 sdcard_endWriteBlocks();
316 } else {
317 sdcard.state = SDCARD_STATE_READY;
319 } else if (millis() > sdcard.operationStartTime + SDCARD_TIMEOUT_WRITE_MSEC) {
321 * The caller has already been told that their write has completed, so they will have discarded
322 * their buffer and have no hope of retrying the operation. But this should be very rare and it allows
323 * them to reuse their buffer milliseconds faster than they otherwise would.
325 sdcardSdio_reset();
326 goto doMore;
328 break;
329 case SDCARD_STATE_READING:
330 switch (sdcard_receiveDataBlock(sdcard.pendingOperation.buffer, SDCARD_BLOCK_SIZE)) {
331 case SDCARD_RECEIVE_SUCCESS:
333 sdcard.state = SDCARD_STATE_READY;
334 sdcard.failureCount = 0; // Assume the card is good if it can complete a read
336 if (sdcard.pendingOperation.callback) {
337 sdcard.pendingOperation.callback(
338 SDCARD_BLOCK_OPERATION_READ,
339 sdcard.pendingOperation.blockIndex,
340 sdcard.pendingOperation.buffer,
341 sdcard.pendingOperation.callbackData
344 break;
345 case SDCARD_RECEIVE_BLOCK_IN_PROGRESS:
346 if (millis() <= sdcard.operationStartTime + SDCARD_TIMEOUT_READ_MSEC) {
347 break; // Timeout not reached yet so keep waiting
349 // Timeout has expired, so fall through to convert to a fatal error
351 case SDCARD_RECEIVE_ERROR:
352 goto doMore;
353 break;
355 break;
356 case SDCARD_STATE_STOPPING_MULTIPLE_BLOCK_WRITE:
357 if (SD_GetState()) {
358 sdcard.state = SDCARD_STATE_READY;
359 } else if (millis() > sdcard.operationStartTime + SDCARD_TIMEOUT_WRITE_MSEC) {
360 sdcardSdio_reset();
361 goto doMore;
363 break;
364 case SDCARD_STATE_NOT_PRESENT:
365 default:
369 // Is the card's initialization taking too long?
370 if (sdcard.state >= SDCARD_STATE_RESET && sdcard.state < SDCARD_STATE_READY
371 && millis() - sdcard.operationStartTime > SDCARD_TIMEOUT_INIT_MILLIS) {
372 sdcardSdio_reset();
375 return sdcard_isReady();
379 * Write the 512-byte block from the given buffer into the block with the given index.
381 * If the write does not complete immediately, your callback will be called later. If the write was successful, the
382 * buffer pointer will be the same buffer you originally passed in, otherwise the buffer will be set to NULL.
384 * Returns:
385 * SDCARD_OPERATION_IN_PROGRESS - Your buffer is currently being transmitted to the card and your callback will be
386 * called later to report the completion. The buffer pointer must remain valid until
387 * that time.
388 * SDCARD_OPERATION_SUCCESS - Your buffer has been transmitted to the card now.
389 * SDCARD_OPERATION_BUSY - The card is already busy and cannot accept your write
390 * SDCARD_OPERATION_FAILURE - Your write was rejected by the card, card will be reset
392 static sdcardOperationStatus_e sdcardSdio_writeBlock(uint32_t blockIndex, uint8_t *buffer, sdcard_operationCompleteCallback_c callback, uint32_t callbackData)
394 doMore:
395 switch (sdcard.state) {
396 case SDCARD_STATE_WRITING_MULTIPLE_BLOCKS:
397 // Do we need to cancel the previous multi-block write?
398 if (blockIndex != sdcard.multiWriteNextBlock) {
399 if (sdcard_endWriteBlocks() == SDCARD_OPERATION_SUCCESS) {
400 // Now we've entered the ready state, we can try again
401 goto doMore;
402 } else {
403 return SDCARD_OPERATION_BUSY;
407 // We're continuing a multi-block write
408 break;
409 case SDCARD_STATE_READY:
410 break;
411 default:
412 return SDCARD_OPERATION_BUSY;
415 sdcard.pendingOperation.buffer = buffer;
416 sdcard.pendingOperation.blockIndex = blockIndex;
418 unsigned block_count = 1;
420 #if defined(USE_SDCARD_SDIO_CACHE)
421 if ((cache_getCount() < FATFS_BLOCK_CACHE_SIZE) && (sdcard.multiWriteBlocksRemain != 0)) {
422 cache_write(buffer);
424 if (cache_getCount() == FATFS_BLOCK_CACHE_SIZE || sdcard.multiWriteBlocksRemain == 1) {
425 //Relocate buffer and recalculate block index
426 buffer = (uint8_t*)writeCache;
427 blockIndex -= cache_getCount() - 1;
428 block_count = cache_getCount();
429 } else {
430 sdcard.multiWriteBlocksRemain--;
431 sdcard.multiWriteNextBlock++;
432 sdcard.state = SDCARD_STATE_READY;
433 return SDCARD_OPERATION_SUCCESS;
436 #endif
438 sdcard.pendingOperation.callback = callback;
439 sdcard.pendingOperation.callbackData = callbackData;
440 sdcard.pendingOperation.chunkIndex = 1; // (for non-DMA transfers) we've sent chunk #0 already
441 sdcard.state = SDCARD_STATE_SENDING_WRITE;
443 if (SD_WriteBlocks_DMA(blockIndex, (uint32_t*) buffer, 512, block_count) != SD_OK) {
444 /* Our write was rejected! This could be due to a bad address but we hope not to attempt that, so assume
445 * the card is broken and needs reset.
447 sdcardSdio_reset();
449 // Announce write failure:
450 if (sdcard.pendingOperation.callback) {
451 sdcard.pendingOperation.callback(SDCARD_BLOCK_OPERATION_WRITE, sdcard.pendingOperation.blockIndex, NULL, sdcard.pendingOperation.callbackData);
453 return SDCARD_OPERATION_FAILURE;
456 return SDCARD_OPERATION_IN_PROGRESS;
460 * Begin writing a series of consecutive blocks beginning at the given block index. This will allow (but not require)
461 * the SD card to pre-erase the number of blocks you specifiy, which can allow the writes to complete faster.
463 * Afterwards, just call sdcard_writeBlock() as normal to write those blocks consecutively.
465 * It's okay to abort the multi-block write at any time by writing to a non-consecutive address, or by performing a read.
467 * Returns:
468 * SDCARD_OPERATION_SUCCESS - Multi-block write has been queued
469 * SDCARD_OPERATION_BUSY - The card is already busy and cannot accept your write
470 * SDCARD_OPERATION_FAILURE - A fatal error occured, card will be reset
472 static sdcardOperationStatus_e sdcardSdio_beginWriteBlocks(uint32_t blockIndex, uint32_t blockCount)
474 if (sdcard.state != SDCARD_STATE_READY) {
475 if (sdcard.state == SDCARD_STATE_WRITING_MULTIPLE_BLOCKS) {
476 if (blockIndex == sdcard.multiWriteNextBlock) {
477 // Assume that the caller wants to continue the multi-block write they already have in progress!
478 return SDCARD_OPERATION_SUCCESS;
479 } else if (sdcard_endWriteBlocks() != SDCARD_OPERATION_SUCCESS) {
480 return SDCARD_OPERATION_BUSY;
481 } // Else we've completed the previous multi-block write and can fall through to start the new one
482 } else {
483 return SDCARD_OPERATION_BUSY;
487 sdcard.state = SDCARD_STATE_WRITING_MULTIPLE_BLOCKS;
488 sdcard.multiWriteBlocksRemain = blockCount;
489 sdcard.multiWriteNextBlock = blockIndex;
490 return SDCARD_OPERATION_SUCCESS;
494 * Read the 512-byte block with the given index into the given 512-byte buffer.
496 * When the read completes, your callback will be called. If the read was successful, the buffer pointer will be the
497 * same buffer you originally passed in, otherwise the buffer will be set to NULL.
499 * You must keep the pointer to the buffer valid until the operation completes!
501 * Returns:
502 * true - The operation was successfully queued for later completion, your callback will be called later
503 * false - The operation could not be started due to the card being busy (try again later).
505 static bool sdcardSdio_readBlock(uint32_t blockIndex, uint8_t *buffer, sdcard_operationCompleteCallback_c callback, uint32_t callbackData)
507 if (sdcard.state != SDCARD_STATE_READY) {
508 if (sdcard.state == SDCARD_STATE_WRITING_MULTIPLE_BLOCKS) {
509 if (sdcard_endWriteBlocks() != SDCARD_OPERATION_SUCCESS) {
510 return false;
512 } else {
513 return false;
517 // Standard size cards use byte addressing, high capacity cards use block addressing
518 uint8_t status = SD_ReadBlocks_DMA(blockIndex, (uint32_t*) buffer, 512, 1);
520 if (status == SD_OK) {
521 sdcard.pendingOperation.buffer = buffer;
522 sdcard.pendingOperation.blockIndex = blockIndex;
523 sdcard.pendingOperation.callback = callback;
524 sdcard.pendingOperation.callbackData = callbackData;
526 sdcard.state = SDCARD_STATE_READING;
527 sdcard.operationStartTime = millis();
529 return true;
530 } else {
531 sdcardSdio_reset();
532 if (sdcard.pendingOperation.callback) {
533 sdcard.pendingOperation.callback(
534 SDCARD_BLOCK_OPERATION_READ,
535 sdcard.pendingOperation.blockIndex,
536 NULL,
537 sdcard.pendingOperation.callbackData
540 return false;
545 * Begin the initialization process for the SD card. This must be called first before any other sdcard_ routine.
547 void sdcardSdio_init(void)
549 #if !defined(STM32H7) // H7 uses IDMA
550 sdcard.dma = dmaGetByTag(SDCARD_SDIO_DMA);
552 if (!sdcard.dma) {
553 sdcard.state = SDCARD_STATE_NOT_PRESENT;
554 return;
557 // Check if somebody already occupies this DMA channel
558 if (dmaGetOwner(sdcard.dma) != OWNER_FREE) {
559 sdcard.dma = NULL;
560 sdcard.state = SDCARD_STATE_NOT_PRESENT;
561 return;
564 if (!SD_Initialize_LL(sdcard.dma->ref)) {
565 sdcard.dma = NULL;
566 sdcard.state = SDCARD_STATE_NOT_PRESENT;
567 return;
569 #else
570 if (!SD_Initialize_LL(0)) {
571 sdcard.state = SDCARD_STATE_NOT_PRESENT;
572 return;
574 #endif
575 // We don't support hot insertion
576 if (!sdcard_isInserted()) {
577 sdcard.state = SDCARD_STATE_NOT_PRESENT;
578 return;
581 if (SD_Init() != 0) {
582 sdcard.state = SDCARD_STATE_NOT_PRESENT;
583 return;
586 sdcard.operationStartTime = millis();
587 sdcard.state = SDCARD_STATE_RESET;
588 sdcard.failureCount = 0;
592 * Returns true if the SD card has successfully completed its startup procedures.
594 static bool sdcardSdio_isInitialized(void)
596 return sdcard.state >= SDCARD_STATE_READY;
599 static const sdcardMetadata_t* sdcardSdio_getMetadata(void)
601 return &sdcard.metadata;
604 sdcardVTable_t sdcardSdioVTable = {
605 .init = &sdcardSdio_init,
606 .readBlock = &sdcardSdio_readBlock,
607 .beginWriteBlocks = &sdcardSdio_beginWriteBlocks,
608 .writeBlock = &sdcardSdio_writeBlock,
609 .poll = &sdcardSdio_poll,
610 .isFunctional = &sdcardSdio_isFunctional,
611 .isInitialized = &sdcardSdio_isInitialized,
612 .getMetadata = &sdcardSdio_getMetadata,
615 #endif