Merge pull request #11198 from SteveCEvans/sce_rc2
[betaflight.git] / src / main / drivers / sdio_h7xx.c
blob52e5e12697f48c1887d76896e284a993edbcb2c3
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/>.
22 * Original author: Alain (https://github.com/aroyer-qc)
23 * Modified for BF source: Chris Hockuba (https://github.com/conkerkh)
26 /* Include(s) -------------------------------------------------------------------------------------------------------*/
28 #include "stdbool.h"
29 #include <string.h>
31 #include "platform.h"
33 #ifdef USE_SDCARD_SDIO
35 #include "sdmmc_sdio.h"
37 #include "pg/sdio.h"
39 #include "drivers/io.h"
40 #include "drivers/io_impl.h"
41 #include "drivers/nvic.h"
42 #include "drivers/sdio.h"
44 typedef struct SD_Handle_s
46 uint32_t CSD[4]; // SD card specific data table
47 uint32_t CID[4]; // SD card identification number table
48 volatile uint32_t RXCplt; // SD RX Complete is equal 0 when no transfer
49 volatile uint32_t TXCplt; // SD TX Complete is equal 0 when no transfer
51 uint32_t RXErrors;
52 uint32_t TXErrors;
53 } SD_Handle_t;
55 SD_HandleTypeDef hsd1;
57 SD_CardInfo_t SD_CardInfo;
58 SD_CardType_t SD_CardType;
60 SD_Handle_t SD_Handle;
62 typedef struct sdioPin_s {
63 ioTag_t pin;
64 uint8_t af;
65 } sdioPin_t;
67 #define SDIO_PIN_D0 0
68 #define SDIO_PIN_D1 1
69 #define SDIO_PIN_D2 2
70 #define SDIO_PIN_D3 3
71 #define SDIO_PIN_CK 4
72 #define SDIO_PIN_CMD 5
73 #define SDIO_PIN_COUNT 6
75 #define SDIO_MAX_PINDEFS 2
77 typedef struct sdioHardware_s {
78 SDMMC_TypeDef *instance;
79 IRQn_Type irqn;
80 sdioPin_t sdioPinCK[SDIO_MAX_PINDEFS];
81 sdioPin_t sdioPinCMD[SDIO_MAX_PINDEFS];
82 sdioPin_t sdioPinD0[SDIO_MAX_PINDEFS];
83 sdioPin_t sdioPinD1[SDIO_MAX_PINDEFS];
84 sdioPin_t sdioPinD2[SDIO_MAX_PINDEFS];
85 sdioPin_t sdioPinD3[SDIO_MAX_PINDEFS];
86 } sdioHardware_t;
88 // Possible pin assignments
90 #define PINDEF(device, pin, afnum) { DEFIO_TAG_E(pin), GPIO_AF ## afnum ## _SDMMC ## device }
92 static const sdioHardware_t sdioPinHardware[SDIODEV_COUNT] = {
94 .instance = SDMMC1,
95 .irqn = SDMMC1_IRQn,
96 .sdioPinCK = { PINDEF(1, PC12, 12) },
97 .sdioPinCMD = { PINDEF(1, PD2, 12) },
98 .sdioPinD0 = { PINDEF(1, PC8, 12) },
99 .sdioPinD1 = { PINDEF(1, PC9, 12) },
100 .sdioPinD2 = { PINDEF(1, PC10, 12) },
101 .sdioPinD3 = { PINDEF(1, PC11, 12) },
104 .instance = SDMMC2,
105 .irqn = SDMMC2_IRQn,
106 .sdioPinCK = { PINDEF(2, PC1, 9), PINDEF(2, PD6, 11) },
107 .sdioPinCMD = { PINDEF(2, PA0, 9), PINDEF(2, PD7, 11) },
108 .sdioPinD0 = { PINDEF(2, PB14, 9) },
109 .sdioPinD1 = { PINDEF(2, PB15, 9) },
110 .sdioPinD2 = { PINDEF(2, PB3, 9) },
111 .sdioPinD3 = { PINDEF(2, PB4, 9) },
115 #undef PINDEF
117 // Active configuration
118 static const sdioHardware_t *sdioHardware;
119 static sdioPin_t sdioPin[SDIO_PIN_COUNT];
121 static const sdioPin_t *sdioFindPinDef(const sdioPin_t *pindefs, ioTag_t pin)
123 for (unsigned index = 0; index < SDIO_MAX_PINDEFS; index++) {
124 if (pindefs[index].pin == pin) {
125 return &pindefs[index];
129 return NULL;
132 #define SDIOFINDPIN(pinname) { \
133 const sdioPin_t *pindef; \
134 pindef = sdioFindPinDef(sdioHardware->sdioPin ## pinname, sdioPinConfig()->pinname ## Pin); \
135 if (pindef) { \
136 sdioPin[SDIO_PIN_ ## pinname] = *pindef; \
138 } struct dummy
140 void sdioPinConfigure(void)
142 SDIODevice device = SDIO_CFG_TO_DEV(sdioConfig()->device);
144 if (device == SDIOINVALID) {
145 return;
148 sdioHardware = &sdioPinHardware[device];
150 SDIOFINDPIN(CK);
151 SDIOFINDPIN(CMD);
152 SDIOFINDPIN(D0);
154 if (sdioConfig()->use4BitWidth) {
155 SDIOFINDPIN(D1);
156 SDIOFINDPIN(D2);
157 SDIOFINDPIN(D3);
161 #undef SDIOFINDPIN
163 #define IOCFG_SDMMC IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL)
165 void HAL_SD_MspInit(SD_HandleTypeDef* hsd)
167 UNUSED(hsd);
169 if (!sdioHardware) {
170 return;
173 if (sdioHardware->instance == SDMMC1) {
174 __HAL_RCC_SDMMC1_CLK_DISABLE();
175 __HAL_RCC_SDMMC1_FORCE_RESET();
176 __HAL_RCC_SDMMC1_RELEASE_RESET();
177 __HAL_RCC_SDMMC1_CLK_ENABLE();
178 } else if (sdioHardware->instance == SDMMC2) {
179 __HAL_RCC_SDMMC2_CLK_DISABLE();
180 __HAL_RCC_SDMMC2_FORCE_RESET();
181 __HAL_RCC_SDMMC2_RELEASE_RESET();
182 __HAL_RCC_SDMMC2_CLK_ENABLE();
185 uint8_t is4BitWidth = sdioConfig()->use4BitWidth;
187 const IO_t clk = IOGetByTag(sdioPin[SDIO_PIN_CK].pin);
188 const IO_t cmd = IOGetByTag(sdioPin[SDIO_PIN_CMD].pin);
189 const IO_t d0 = IOGetByTag(sdioPin[SDIO_PIN_D0].pin);
190 const IO_t d1 = IOGetByTag(sdioPin[SDIO_PIN_D1].pin);
191 const IO_t d2 = IOGetByTag(sdioPin[SDIO_PIN_D2].pin);
192 const IO_t d3 = IOGetByTag(sdioPin[SDIO_PIN_D3].pin);
194 IOConfigGPIOAF(clk, IOCFG_SDMMC, sdioPin[SDIO_PIN_CK].af);
195 IOConfigGPIOAF(cmd, IOCFG_SDMMC, sdioPin[SDIO_PIN_CMD].af);
196 IOConfigGPIOAF(d0, IOCFG_SDMMC, sdioPin[SDIO_PIN_D0].af);
198 if(is4BitWidth) {
199 IOConfigGPIOAF(d1, IOCFG_SDMMC, sdioPin[SDIO_PIN_D1].af);
200 IOConfigGPIOAF(d2, IOCFG_SDMMC, sdioPin[SDIO_PIN_D2].af);
201 IOConfigGPIOAF(d3, IOCFG_SDMMC, sdioPin[SDIO_PIN_D3].af);
204 HAL_NVIC_SetPriority(sdioHardware->irqn, NVIC_PRIORITY_BASE(NVIC_PRIO_SDIO_DMA), NVIC_PRIORITY_SUB(NVIC_PRIO_SDIO_DMA));
205 HAL_NVIC_EnableIRQ(sdioHardware->irqn);
208 void SDIO_GPIO_Init(void)
210 if (!sdioHardware) {
211 return;
214 uint8_t is4BitWidth = sdioConfig()->use4BitWidth;
216 const IO_t clk = IOGetByTag(sdioPin[SDIO_PIN_CK].pin);
217 const IO_t cmd = IOGetByTag(sdioPin[SDIO_PIN_CMD].pin);
218 const IO_t d0 = IOGetByTag(sdioPin[SDIO_PIN_D0].pin);
219 const IO_t d1 = IOGetByTag(sdioPin[SDIO_PIN_D1].pin);
220 const IO_t d2 = IOGetByTag(sdioPin[SDIO_PIN_D2].pin);
221 const IO_t d3 = IOGetByTag(sdioPin[SDIO_PIN_D3].pin);
223 IOInit(clk, OWNER_SDIO_CK, 0);
224 IOInit(cmd, OWNER_SDIO_CMD, 0);
225 IOInit(d0, OWNER_SDIO_D0, 0);
227 if (is4BitWidth) {
228 IOInit(d1, OWNER_SDIO_D1, 0);
229 IOInit(d2, OWNER_SDIO_D2, 0);
230 IOInit(d3, OWNER_SDIO_D3, 0);
234 // Setting all the SDIO pins to high for a short time results in more robust initialisation.
236 IOHi(d0);
237 IOConfigGPIO(d0, IOCFG_OUT_PP);
239 if(is4BitWidth) {
240 IOHi(d1);
241 IOHi(d2);
242 IOHi(d3);
243 IOConfigGPIO(d1, IOCFG_OUT_PP);
244 IOConfigGPIO(d2, IOCFG_OUT_PP);
245 IOConfigGPIO(d3, IOCFG_OUT_PP);
248 IOHi(clk);
249 IOHi(cmd);
250 IOConfigGPIO(clk, IOCFG_OUT_PP);
251 IOConfigGPIO(cmd, IOCFG_OUT_PP);
254 bool SD_Initialize_LL(DMA_Stream_TypeDef *dma)
256 UNUSED(dma);
258 return true;
261 bool SD_GetState(void)
263 HAL_SD_CardStateTypedef cardState = HAL_SD_GetCardState(&hsd1);
265 return (cardState == HAL_SD_CARD_TRANSFER);
268 static SD_Error_t SD_DoInit(void)
270 HAL_StatusTypeDef status;
272 memset(&hsd1, 0, sizeof(hsd1));
274 hsd1.Instance = sdioHardware->instance;
276 hsd1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
277 hsd1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_ENABLE;
278 if (sdioConfig()->use4BitWidth) {
279 hsd1.Init.BusWide = SDMMC_BUS_WIDE_4B;
280 } else {
281 hsd1.Init.BusWide = SDMMC_BUS_WIDE_1B; // FIXME untested
283 hsd1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_ENABLE;
284 #if defined(STM32H730xx)
285 hsd1.Init.ClockDiv = 2; // 200Mhz / (2 * 2 ) = 50Mhz, used for "UltraHigh speed SD card" only, see HAL_SD_ConfigWideBusOperation, SDMMC_HSpeed_CLK_DIV, SDMMC_NSpeed_CLK_DIV
286 #else
287 hsd1.Init.ClockDiv = 1; // 200Mhz / (2 * 1 ) = 100Mhz, used for "UltraHigh speed SD card" only, see HAL_SD_ConfigWideBusOperation, SDMMC_HSpeed_CLK_DIV, SDMMC_NSpeed_CLK_DIV
288 #endif
289 status = HAL_SD_Init(&hsd1); // Will call HAL_SD_MspInit
291 if (status != HAL_OK) {
292 return SD_ERROR;
295 switch(hsd1.SdCard.CardType) {
296 case CARD_SDSC:
297 switch (hsd1.SdCard.CardVersion) {
298 case CARD_V1_X:
299 SD_CardType = SD_STD_CAPACITY_V1_1;
300 break;
301 case CARD_V2_X:
302 SD_CardType = SD_STD_CAPACITY_V2_0;
303 break;
304 default:
305 return SD_ERROR;
307 break;
309 case CARD_SDHC_SDXC:
310 SD_CardType = SD_HIGH_CAPACITY;
311 break;
313 default:
314 return SD_ERROR;
317 STATIC_ASSERT(sizeof(SD_Handle.CSD) == sizeof(hsd1.CSD), hal-csd-size-error);
318 memcpy(&SD_Handle.CSD, &hsd1.CSD, sizeof(SD_Handle.CSD));
320 STATIC_ASSERT(sizeof(SD_Handle.CID) == sizeof(hsd1.CID), hal-cid-size-error);
321 memcpy(&SD_Handle.CID, &hsd1.CID, sizeof(SD_Handle.CID));
323 return SD_OK;
326 SD_Error_t SD_GetCardInfo(void)
328 SD_Error_t ErrorState = SD_OK;
330 // fill in SD_CardInfo
332 uint32_t Temp = 0;
334 // Byte 0
335 Temp = (SD_Handle.CSD[0] & 0xFF000000) >> 24;
336 SD_CardInfo.SD_csd.CSDStruct = (uint8_t)((Temp & 0xC0) >> 6);
337 SD_CardInfo.SD_csd.SysSpecVersion = (uint8_t)((Temp & 0x3C) >> 2);
338 SD_CardInfo.SD_csd.Reserved1 = Temp & 0x03;
340 // Byte 1
341 Temp = (SD_Handle.CSD[0] & 0x00FF0000) >> 16;
342 SD_CardInfo.SD_csd.TAAC = (uint8_t)Temp;
344 // Byte 2
345 Temp = (SD_Handle.CSD[0] & 0x0000FF00) >> 8;
346 SD_CardInfo.SD_csd.NSAC = (uint8_t)Temp;
348 // Byte 3
349 Temp = SD_Handle.CSD[0] & 0x000000FF;
350 SD_CardInfo.SD_csd.MaxBusClkFrec = (uint8_t)Temp;
352 // Byte 4
353 Temp = (SD_Handle.CSD[1] & 0xFF000000) >> 24;
354 SD_CardInfo.SD_csd.CardComdClasses = (uint16_t)(Temp << 4);
356 // Byte 5
357 Temp = (SD_Handle.CSD[1] & 0x00FF0000) >> 16;
358 SD_CardInfo.SD_csd.CardComdClasses |= (uint16_t)((Temp & 0xF0) >> 4);
359 SD_CardInfo.SD_csd.RdBlockLen = (uint8_t)(Temp & 0x0F);
361 // Byte 6
362 Temp = (SD_Handle.CSD[1] & 0x0000FF00) >> 8;
363 SD_CardInfo.SD_csd.PartBlockRead = (uint8_t)((Temp & 0x80) >> 7);
364 SD_CardInfo.SD_csd.WrBlockMisalign = (uint8_t)((Temp & 0x40) >> 6);
365 SD_CardInfo.SD_csd.RdBlockMisalign = (uint8_t)((Temp & 0x20) >> 5);
366 SD_CardInfo.SD_csd.DSRImpl = (uint8_t)((Temp & 0x10) >> 4);
367 SD_CardInfo.SD_csd.Reserved2 = 0; /*!< Reserved */
369 if((SD_CardType == SD_STD_CAPACITY_V1_1) || (SD_CardType == SD_STD_CAPACITY_V2_0)) {
370 SD_CardInfo.SD_csd.DeviceSize = (Temp & 0x03) << 10;
372 // Byte 7
373 Temp = (uint8_t)(SD_Handle.CSD[1] & 0x000000FF);
374 SD_CardInfo.SD_csd.DeviceSize |= (Temp) << 2;
376 // Byte 8
377 Temp = (uint8_t)((SD_Handle.CSD[2] & 0xFF000000) >> 24);
378 SD_CardInfo.SD_csd.DeviceSize |= (Temp & 0xC0) >> 6;
380 SD_CardInfo.SD_csd.MaxRdCurrentVDDMin = (Temp & 0x38) >> 3;
381 SD_CardInfo.SD_csd.MaxRdCurrentVDDMax = (Temp & 0x07);
383 // Byte 9
384 Temp = (uint8_t)((SD_Handle.CSD[2] & 0x00FF0000) >> 16);
385 SD_CardInfo.SD_csd.MaxWrCurrentVDDMin = (Temp & 0xE0) >> 5;
386 SD_CardInfo.SD_csd.MaxWrCurrentVDDMax = (Temp & 0x1C) >> 2;
387 SD_CardInfo.SD_csd.DeviceSizeMul = (Temp & 0x03) << 1;
389 // Byte 10
390 Temp = (uint8_t)((SD_Handle.CSD[2] & 0x0000FF00) >> 8);
391 SD_CardInfo.SD_csd.DeviceSizeMul |= (Temp & 0x80) >> 7;
393 SD_CardInfo.CardCapacity = (SD_CardInfo.SD_csd.DeviceSize + 1) ;
394 SD_CardInfo.CardCapacity *= (1 << (SD_CardInfo.SD_csd.DeviceSizeMul + 2));
395 SD_CardInfo.CardBlockSize = 1 << (SD_CardInfo.SD_csd.RdBlockLen);
396 SD_CardInfo.CardCapacity = SD_CardInfo.CardCapacity * SD_CardInfo.CardBlockSize / 512; // In 512 byte blocks
397 } else if(SD_CardType == SD_HIGH_CAPACITY) {
398 // Byte 7
399 Temp = (uint8_t)(SD_Handle.CSD[1] & 0x000000FF);
400 SD_CardInfo.SD_csd.DeviceSize = (Temp & 0x3F) << 16;
402 // Byte 8
403 Temp = (uint8_t)((SD_Handle.CSD[2] & 0xFF000000) >> 24);
405 SD_CardInfo.SD_csd.DeviceSize |= (Temp << 8);
407 // Byte 9
408 Temp = (uint8_t)((SD_Handle.CSD[2] & 0x00FF0000) >> 16);
410 SD_CardInfo.SD_csd.DeviceSize |= (Temp);
412 // Byte 10
413 Temp = (uint8_t)((SD_Handle.CSD[2] & 0x0000FF00) >> 8);
415 SD_CardInfo.CardCapacity = ((uint64_t)SD_CardInfo.SD_csd.DeviceSize + 1) * 1024;
416 SD_CardInfo.CardBlockSize = 512;
417 } else {
418 // Not supported card type
419 ErrorState = SD_ERROR;
422 SD_CardInfo.SD_csd.EraseGrSize = (Temp & 0x40) >> 6;
423 SD_CardInfo.SD_csd.EraseGrMul = (Temp & 0x3F) << 1;
425 // Byte 11
426 Temp = (uint8_t)(SD_Handle.CSD[2] & 0x000000FF);
427 SD_CardInfo.SD_csd.EraseGrMul |= (Temp & 0x80) >> 7;
428 SD_CardInfo.SD_csd.WrProtectGrSize = (Temp & 0x7F);
430 // Byte 12
431 Temp = (uint8_t)((SD_Handle.CSD[3] & 0xFF000000) >> 24);
432 SD_CardInfo.SD_csd.WrProtectGrEnable = (Temp & 0x80) >> 7;
433 SD_CardInfo.SD_csd.ManDeflECC = (Temp & 0x60) >> 5;
434 SD_CardInfo.SD_csd.WrSpeedFact = (Temp & 0x1C) >> 2;
435 SD_CardInfo.SD_csd.MaxWrBlockLen = (Temp & 0x03) << 2;
437 // Byte 13
438 Temp = (uint8_t)((SD_Handle.CSD[3] & 0x00FF0000) >> 16);
439 SD_CardInfo.SD_csd.MaxWrBlockLen |= (Temp & 0xC0) >> 6;
440 SD_CardInfo.SD_csd.WriteBlockPaPartial = (Temp & 0x20) >> 5;
441 SD_CardInfo.SD_csd.Reserved3 = 0;
442 SD_CardInfo.SD_csd.ContentProtectAppli = (Temp & 0x01);
444 // Byte 14
445 Temp = (uint8_t)((SD_Handle.CSD[3] & 0x0000FF00) >> 8);
446 SD_CardInfo.SD_csd.FileFormatGrouop = (Temp & 0x80) >> 7;
447 SD_CardInfo.SD_csd.CopyFlag = (Temp & 0x40) >> 6;
448 SD_CardInfo.SD_csd.PermWrProtect = (Temp & 0x20) >> 5;
449 SD_CardInfo.SD_csd.TempWrProtect = (Temp & 0x10) >> 4;
450 SD_CardInfo.SD_csd.FileFormat = (Temp & 0x0C) >> 2;
451 SD_CardInfo.SD_csd.ECC = (Temp & 0x03);
453 // Byte 15
454 Temp = (uint8_t)(SD_Handle.CSD[3] & 0x000000FF);
455 SD_CardInfo.SD_csd.CSD_CRC = (Temp & 0xFE) >> 1;
456 SD_CardInfo.SD_csd.Reserved4 = 1;
458 // Byte 0
459 Temp = (uint8_t)((SD_Handle.CID[0] & 0xFF000000) >> 24);
460 SD_CardInfo.SD_cid.ManufacturerID = Temp;
462 // Byte 1
463 Temp = (uint8_t)((SD_Handle.CID[0] & 0x00FF0000) >> 16);
464 SD_CardInfo.SD_cid.OEM_AppliID = Temp << 8;
466 // Byte 2
467 Temp = (uint8_t)((SD_Handle.CID[0] & 0x000000FF00) >> 8);
468 SD_CardInfo.SD_cid.OEM_AppliID |= Temp;
470 // Byte 3
471 Temp = (uint8_t)(SD_Handle.CID[0] & 0x000000FF);
472 SD_CardInfo.SD_cid.ProdName1 = Temp << 24;
474 // Byte 4
475 Temp = (uint8_t)((SD_Handle.CID[1] & 0xFF000000) >> 24);
476 SD_CardInfo.SD_cid.ProdName1 |= Temp << 16;
478 // Byte 5
479 Temp = (uint8_t)((SD_Handle.CID[1] & 0x00FF0000) >> 16);
480 SD_CardInfo.SD_cid.ProdName1 |= Temp << 8;
482 // Byte 6
483 Temp = (uint8_t)((SD_Handle.CID[1] & 0x0000FF00) >> 8);
484 SD_CardInfo.SD_cid.ProdName1 |= Temp;
486 // Byte 7
487 Temp = (uint8_t)(SD_Handle.CID[1] & 0x000000FF);
488 SD_CardInfo.SD_cid.ProdName2 = Temp;
490 // Byte 8
491 Temp = (uint8_t)((SD_Handle.CID[2] & 0xFF000000) >> 24);
492 SD_CardInfo.SD_cid.ProdRev = Temp;
494 // Byte 9
495 Temp = (uint8_t)((SD_Handle.CID[2] & 0x00FF0000) >> 16);
496 SD_CardInfo.SD_cid.ProdSN = Temp << 24;
498 // Byte 10
499 Temp = (uint8_t)((SD_Handle.CID[2] & 0x0000FF00) >> 8);
500 SD_CardInfo.SD_cid.ProdSN |= Temp << 16;
502 // Byte 11
503 Temp = (uint8_t)(SD_Handle.CID[2] & 0x000000FF);
504 SD_CardInfo.SD_cid.ProdSN |= Temp << 8;
506 // Byte 12
507 Temp = (uint8_t)((SD_Handle.CID[3] & 0xFF000000) >> 24);
508 SD_CardInfo.SD_cid.ProdSN |= Temp;
510 // Byte 13
511 Temp = (uint8_t)((SD_Handle.CID[3] & 0x00FF0000) >> 16);
512 SD_CardInfo.SD_cid.Reserved1 |= (Temp & 0xF0) >> 4;
513 SD_CardInfo.SD_cid.ManufactDate = (Temp & 0x0F) << 8;
515 // Byte 14
516 Temp = (uint8_t)((SD_Handle.CID[3] & 0x0000FF00) >> 8);
517 SD_CardInfo.SD_cid.ManufactDate |= Temp;
519 // Byte 15
520 Temp = (uint8_t)(SD_Handle.CID[3] & 0x000000FF);
521 SD_CardInfo.SD_cid.CID_CRC = (Temp & 0xFE) >> 1;
522 SD_CardInfo.SD_cid.Reserved2 = 1;
524 return ErrorState;
527 SD_Error_t SD_Init(void)
529 static bool sdInitAttempted = false;
530 static SD_Error_t result = SD_ERROR;
532 if (sdInitAttempted) {
533 return result;
536 sdInitAttempted = true;
538 result = SD_DoInit();
540 return result;
543 SD_Error_t SD_CheckWrite(void) {
544 if (SD_Handle.TXCplt != 0) return SD_BUSY;
545 return SD_OK;
548 SD_Error_t SD_CheckRead(void) {
549 if (SD_Handle.RXCplt != 0) return SD_BUSY;
550 return SD_OK;
553 SD_Error_t SD_WriteBlocks_DMA(uint64_t WriteAddress, uint32_t *buffer, uint32_t BlockSize, uint32_t NumberOfBlocks)
555 SD_Error_t ErrorState = SD_OK;
556 SD_Handle.TXCplt = 1;
558 if (BlockSize != 512) {
559 return SD_ERROR; // unsupported.
562 if ((uint32_t)buffer & 0x1f) {
563 return SD_ADDR_MISALIGNED;
566 // Ensure the data is flushed to main memory
567 SCB_CleanDCache_by_Addr(buffer, NumberOfBlocks * BlockSize);
569 HAL_StatusTypeDef status;
570 if ((status = HAL_SD_WriteBlocks_DMA(&hsd1, (uint8_t *)buffer, WriteAddress, NumberOfBlocks)) != HAL_OK) {
571 return SD_ERROR;
574 return ErrorState;
577 typedef struct {
578 uint32_t *buffer;
579 uint32_t BlockSize;
580 uint32_t NumberOfBlocks;
581 } sdReadParameters_t;
583 sdReadParameters_t sdReadParameters;
585 SD_Error_t SD_ReadBlocks_DMA(uint64_t ReadAddress, uint32_t *buffer, uint32_t BlockSize, uint32_t NumberOfBlocks)
587 SD_Error_t ErrorState = SD_OK;
589 if (BlockSize != 512) {
590 return SD_ERROR; // unsupported.
593 if ((uint32_t)buffer & 0x1f) {
594 return SD_ADDR_MISALIGNED;
597 SD_Handle.RXCplt = 1;
599 sdReadParameters.buffer = buffer;
600 sdReadParameters.BlockSize = BlockSize;
601 sdReadParameters.NumberOfBlocks = NumberOfBlocks;
603 HAL_StatusTypeDef status;
604 if ((status = HAL_SD_ReadBlocks_DMA(&hsd1, (uint8_t *)buffer, ReadAddress, NumberOfBlocks)) != HAL_OK) {
605 return SD_ERROR;
608 return ErrorState;
612 * @brief Tx Transfer completed callback
613 * @param hsd: SD handle
614 * @retval None
616 void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
618 UNUSED(hsd);
620 SD_Handle.TXCplt = 0;
624 * @brief Rx Transfer completed callback
625 * @param hsd: SD handle
626 * @retval None
628 void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
630 UNUSED(hsd);
632 SD_Handle.RXCplt = 0;
635 the SCB_InvalidateDCache_by_Addr() requires a 32-Byte aligned address,
636 adjust the address and the D-Cache size to invalidate accordingly.
638 uint32_t alignedAddr = (uint32_t)sdReadParameters.buffer & ~0x1F;
639 SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr, sdReadParameters.NumberOfBlocks * sdReadParameters.BlockSize + ((uint32_t)sdReadParameters.buffer - alignedAddr));
642 void HAL_SD_ErrorCallback(SD_HandleTypeDef *hsd)
644 UNUSED(hsd);
645 if (SD_Handle.RXCplt) {
646 SD_Handle.RXErrors++;
647 SD_Handle.RXCplt = 0;
650 if (SD_Handle.TXCplt) {
651 SD_Handle.TXErrors++;
652 SD_Handle.TXCplt = 0;
656 void HAL_SD_AbortCallback(SD_HandleTypeDef *hsd)
658 UNUSED(hsd);
660 SD_Handle.TXCplt = 0;
661 SD_Handle.RXCplt = 0;
664 void SDMMC1_IRQHandler(void)
666 HAL_SD_IRQHandler(&hsd1);
669 void SDMMC2_IRQHandler(void)
671 HAL_SD_IRQHandler(&hsd1);
674 #endif