Merge pull request #11297 from SteveCEvans/baro_state
[betaflight.git] / src / main / drivers / sdcard.c
blob1cc4c7595adce355607e8f92c790b495bb482270
1 /*
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)
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 #include <stdbool.h>
22 #include <stdint.h>
24 #include "platform.h"
26 #ifdef USE_SDCARD
28 #include "drivers/nvic.h"
29 #include "drivers/io.h"
30 #include "dma.h"
31 #include "dma_reqmap.h"
33 #include "drivers/bus_spi.h"
34 #include "drivers/time.h"
36 #include "pg/bus_spi.h"
37 #include "pg/sdcard.h"
39 #include "sdcard.h"
40 #include "sdcard_impl.h"
41 #include "sdcard_standard.h"
43 #ifdef AFATFS_USE_INTROSPECTIVE_LOGGING
44 #define SDCARD_PROFILING
45 #endif
47 #define SDCARD_INIT_NUM_DUMMY_BYTES 10
48 #define SDCARD_MAXIMUM_BYTE_DELAY_FOR_CMD_REPLY 8
49 // Chosen so that CMD8 will have the same CRC as CMD0:
50 #define SDCARD_IF_COND_CHECK_PATTERN 0xAB
52 #define SDCARD_TIMEOUT_INIT_MILLIS 200
53 #define SDCARD_MAX_CONSECUTIVE_FAILURES 8
55 /* SPI_CLOCK_INITIALIZATION (256) is the slowest (Spec calls for under 400KHz) */
56 #define SDCARD_SPI_INITIALIZATION_CLOCK_DIVIDER SPI_CLOCK_INITIALIZATION
58 /* Operational speed <= 25MHz */
59 #define SDCARD_SPI_FULL_SPEED_CLOCK_DIVIDER SPI_CLOCK_FAST
61 /* Break up 512-byte SD card sectors into chunks of this size when writing without DMA to reduce the peak overhead
62 * per call to sdcard_poll().
64 #define SDCARD_NON_DMA_CHUNK_SIZE 256
66 sdcard_t sdcard;
68 STATIC_ASSERT(sizeof(sdcardCSD_t) == 16, sdcard_csd_bitfields_didnt_pack_properly);
70 static void sdcardInsertionDetectInit(const sdcardConfig_t *config)
72 if (config->cardDetectTag) {
73 sdcard.cardDetectPin = IOGetByTag(config->cardDetectTag);
74 sdcard.detectionInverted = config->cardDetectInverted;
75 } else {
76 sdcard.cardDetectPin = IO_NONE;
77 sdcard.detectionInverted = false;
80 if (sdcard.cardDetectPin) {
81 IOInit(sdcard.cardDetectPin, OWNER_SDCARD_DETECT, 0);
82 IOConfigGPIO(sdcard.cardDetectPin, IOCFG_IPU);
86 /**
87 * Detect if a SD card is physically present in the memory slot.
89 bool sdcard_isInserted(void)
91 bool result = true;
92 if (sdcard.cardDetectPin) {
93 result = IORead(sdcard.cardDetectPin) != 0;
94 if (sdcard.detectionInverted) {
95 result = !result;
98 return result;
102 * Dispatch
104 sdcardVTable_t *sdcardVTable;
106 void sdcard_preInit(const sdcardConfig_t *config)
108 #ifdef USE_SDCARD_SPI
109 sdcardSpiVTable.sdcard_preInit(config);
110 #else
111 UNUSED(config);
112 #endif
115 void sdcard_init(const sdcardConfig_t *config)
117 sdcardInsertionDetectInit(config);
119 switch (config->mode) {
120 #ifdef USE_SDCARD_SPI
121 case SDCARD_MODE_SPI:
122 sdcardVTable = &sdcardSpiVTable;
123 break;
124 #endif
125 #ifdef USE_SDCARD_SDIO
126 case SDCARD_MODE_SDIO:
127 sdcardVTable = &sdcardSdioVTable;
128 break;
129 #endif
130 default:
131 break;
134 if (sdcardVTable) {
135 sdcardVTable->sdcard_init(config, spiPinConfig(0));
139 bool sdcard_readBlock(uint32_t blockIndex, uint8_t *buffer, sdcard_operationCompleteCallback_c callback, uint32_t callbackData)
141 return sdcardVTable->sdcard_readBlock(blockIndex, buffer, callback, callbackData);
144 sdcardOperationStatus_e sdcard_beginWriteBlocks(uint32_t blockIndex, uint32_t blockCount)
146 return sdcardVTable->sdcard_beginWriteBlocks(blockIndex, blockCount);
149 sdcardOperationStatus_e sdcard_writeBlock(uint32_t blockIndex, uint8_t *buffer, sdcard_operationCompleteCallback_c callback, uint32_t callbackData)
151 return sdcardVTable->sdcard_writeBlock(blockIndex, buffer, callback, callbackData);
154 bool sdcard_poll(void)
156 // sdcard_poll is called from taskMain() via afatfs_poll() and for USE_SDCARD.
157 if (sdcardVTable) {
158 return sdcardVTable->sdcard_poll();
159 } else {
160 return false;
164 bool sdcard_isFunctional(void)
166 // sdcard_isFunctional is called from multiple places, including the case of hardware implementation
167 // without a detect pin in which case sdcard_isInserted() always returns true.
168 if (sdcardVTable) {
169 return sdcardVTable->sdcard_isFunctional();
170 } else {
171 return false;
175 bool sdcard_isInitialized(void)
177 return sdcardVTable->sdcard_isInitialized();
180 const sdcardMetadata_t* sdcard_getMetadata(void)
182 return sdcardVTable->sdcard_getMetadata();
184 #endif