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/>.
22 * Original author: Alain (https://github.com/aroyer-qc)
23 * Modified for BF source: Chris Hockuba (https://github.com/conkerkh)
26 /* Include(s) -------------------------------------------------------------------------------------------------------*/
33 #ifdef USE_SDCARD_SDIO
35 #include "sdmmc_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
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
{
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
;
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
];
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
] = {
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) },
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) },
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
];
132 #define SDIOFINDPIN(pinname) { \
133 const sdioPin_t *pindef; \
134 pindef = sdioFindPinDef(sdioHardware->sdioPin ## pinname, sdioPinConfig()->pinname ## Pin); \
136 sdioPin[SDIO_PIN_ ## pinname] = *pindef; \
140 void sdioPinConfigure(void)
142 SDIODevice device
= SDIO_CFG_TO_DEV(sdioConfig()->device
);
144 if (device
== SDIOINVALID
) {
148 sdioHardware
= &sdioPinHardware
[device
];
154 if (sdioConfig()->use4BitWidth
) {
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
)
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
);
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)
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);
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.
237 IOConfigGPIO(d0
, IOCFG_OUT_PP
);
243 IOConfigGPIO(d1
, IOCFG_OUT_PP
);
244 IOConfigGPIO(d2
, IOCFG_OUT_PP
);
245 IOConfigGPIO(d3
, IOCFG_OUT_PP
);
250 IOConfigGPIO(clk
, IOCFG_OUT_PP
);
251 IOConfigGPIO(cmd
, IOCFG_OUT_PP
);
254 void SD_Initialize_LL(DMA_Stream_TypeDef
*dma
)
259 bool SD_GetState(void)
261 HAL_SD_CardStateTypedef cardState
= HAL_SD_GetCardState(&hsd1
);
263 return (cardState
== HAL_SD_CARD_TRANSFER
);
266 static SD_Error_t
SD_DoInit(void)
268 HAL_StatusTypeDef status
;
270 memset(&hsd1
, 0, sizeof(hsd1
));
272 hsd1
.Instance
= sdioHardware
->instance
;
274 hsd1
.Init
.ClockEdge
= SDMMC_CLOCK_EDGE_RISING
;
275 hsd1
.Init
.ClockPowerSave
= SDMMC_CLOCK_POWER_SAVE_ENABLE
;
276 if (sdioConfig()->use4BitWidth
) {
277 hsd1
.Init
.BusWide
= SDMMC_BUS_WIDE_4B
;
279 hsd1
.Init
.BusWide
= SDMMC_BUS_WIDE_1B
; // FIXME untested
281 hsd1
.Init
.HardwareFlowControl
= SDMMC_HARDWARE_FLOW_CONTROL_ENABLE
;
282 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
284 status
= HAL_SD_Init(&hsd1
); // Will call HAL_SD_MspInit
286 if (status
!= HAL_OK
) {
290 switch(hsd1
.SdCard
.CardType
) {
292 switch (hsd1
.SdCard
.CardVersion
) {
294 SD_CardType
= SD_STD_CAPACITY_V1_1
;
297 SD_CardType
= SD_STD_CAPACITY_V2_0
;
305 SD_CardType
= SD_HIGH_CAPACITY
;
312 STATIC_ASSERT(sizeof(SD_Handle
.CSD
) == sizeof(hsd1
.CSD
), hal
-csd
-size
-error
);
313 memcpy(&SD_Handle
.CSD
, &hsd1
.CSD
, sizeof(SD_Handle
.CSD
));
315 STATIC_ASSERT(sizeof(SD_Handle
.CID
) == sizeof(hsd1
.CID
), hal
-cid
-size
-error
);
316 memcpy(&SD_Handle
.CID
, &hsd1
.CID
, sizeof(SD_Handle
.CID
));
321 SD_Error_t
SD_GetCardInfo(void)
323 SD_Error_t ErrorState
= SD_OK
;
325 // fill in SD_CardInfo
330 Temp
= (SD_Handle
.CSD
[0] & 0xFF000000) >> 24;
331 SD_CardInfo
.SD_csd
.CSDStruct
= (uint8_t)((Temp
& 0xC0) >> 6);
332 SD_CardInfo
.SD_csd
.SysSpecVersion
= (uint8_t)((Temp
& 0x3C) >> 2);
333 SD_CardInfo
.SD_csd
.Reserved1
= Temp
& 0x03;
336 Temp
= (SD_Handle
.CSD
[0] & 0x00FF0000) >> 16;
337 SD_CardInfo
.SD_csd
.TAAC
= (uint8_t)Temp
;
340 Temp
= (SD_Handle
.CSD
[0] & 0x0000FF00) >> 8;
341 SD_CardInfo
.SD_csd
.NSAC
= (uint8_t)Temp
;
344 Temp
= SD_Handle
.CSD
[0] & 0x000000FF;
345 SD_CardInfo
.SD_csd
.MaxBusClkFrec
= (uint8_t)Temp
;
348 Temp
= (SD_Handle
.CSD
[1] & 0xFF000000) >> 24;
349 SD_CardInfo
.SD_csd
.CardComdClasses
= (uint16_t)(Temp
<< 4);
352 Temp
= (SD_Handle
.CSD
[1] & 0x00FF0000) >> 16;
353 SD_CardInfo
.SD_csd
.CardComdClasses
|= (uint16_t)((Temp
& 0xF0) >> 4);
354 SD_CardInfo
.SD_csd
.RdBlockLen
= (uint8_t)(Temp
& 0x0F);
357 Temp
= (SD_Handle
.CSD
[1] & 0x0000FF00) >> 8;
358 SD_CardInfo
.SD_csd
.PartBlockRead
= (uint8_t)((Temp
& 0x80) >> 7);
359 SD_CardInfo
.SD_csd
.WrBlockMisalign
= (uint8_t)((Temp
& 0x40) >> 6);
360 SD_CardInfo
.SD_csd
.RdBlockMisalign
= (uint8_t)((Temp
& 0x20) >> 5);
361 SD_CardInfo
.SD_csd
.DSRImpl
= (uint8_t)((Temp
& 0x10) >> 4);
362 SD_CardInfo
.SD_csd
.Reserved2
= 0; /*!< Reserved */
364 if((SD_CardType
== SD_STD_CAPACITY_V1_1
) || (SD_CardType
== SD_STD_CAPACITY_V2_0
)) {
365 SD_CardInfo
.SD_csd
.DeviceSize
= (Temp
& 0x03) << 10;
368 Temp
= (uint8_t)(SD_Handle
.CSD
[1] & 0x000000FF);
369 SD_CardInfo
.SD_csd
.DeviceSize
|= (Temp
) << 2;
372 Temp
= (uint8_t)((SD_Handle
.CSD
[2] & 0xFF000000) >> 24);
373 SD_CardInfo
.SD_csd
.DeviceSize
|= (Temp
& 0xC0) >> 6;
375 SD_CardInfo
.SD_csd
.MaxRdCurrentVDDMin
= (Temp
& 0x38) >> 3;
376 SD_CardInfo
.SD_csd
.MaxRdCurrentVDDMax
= (Temp
& 0x07);
379 Temp
= (uint8_t)((SD_Handle
.CSD
[2] & 0x00FF0000) >> 16);
380 SD_CardInfo
.SD_csd
.MaxWrCurrentVDDMin
= (Temp
& 0xE0) >> 5;
381 SD_CardInfo
.SD_csd
.MaxWrCurrentVDDMax
= (Temp
& 0x1C) >> 2;
382 SD_CardInfo
.SD_csd
.DeviceSizeMul
= (Temp
& 0x03) << 1;
385 Temp
= (uint8_t)((SD_Handle
.CSD
[2] & 0x0000FF00) >> 8);
386 SD_CardInfo
.SD_csd
.DeviceSizeMul
|= (Temp
& 0x80) >> 7;
388 SD_CardInfo
.CardCapacity
= (SD_CardInfo
.SD_csd
.DeviceSize
+ 1) ;
389 SD_CardInfo
.CardCapacity
*= (1 << (SD_CardInfo
.SD_csd
.DeviceSizeMul
+ 2));
390 SD_CardInfo
.CardBlockSize
= 1 << (SD_CardInfo
.SD_csd
.RdBlockLen
);
391 SD_CardInfo
.CardCapacity
= SD_CardInfo
.CardCapacity
* SD_CardInfo
.CardBlockSize
/ 512; // In 512 byte blocks
392 } else if(SD_CardType
== SD_HIGH_CAPACITY
) {
394 Temp
= (uint8_t)(SD_Handle
.CSD
[1] & 0x000000FF);
395 SD_CardInfo
.SD_csd
.DeviceSize
= (Temp
& 0x3F) << 16;
398 Temp
= (uint8_t)((SD_Handle
.CSD
[2] & 0xFF000000) >> 24);
400 SD_CardInfo
.SD_csd
.DeviceSize
|= (Temp
<< 8);
403 Temp
= (uint8_t)((SD_Handle
.CSD
[2] & 0x00FF0000) >> 16);
405 SD_CardInfo
.SD_csd
.DeviceSize
|= (Temp
);
408 Temp
= (uint8_t)((SD_Handle
.CSD
[2] & 0x0000FF00) >> 8);
410 SD_CardInfo
.CardCapacity
= ((uint64_t)SD_CardInfo
.SD_csd
.DeviceSize
+ 1) * 1024;
411 SD_CardInfo
.CardBlockSize
= 512;
413 // Not supported card type
414 ErrorState
= SD_ERROR
;
417 SD_CardInfo
.SD_csd
.EraseGrSize
= (Temp
& 0x40) >> 6;
418 SD_CardInfo
.SD_csd
.EraseGrMul
= (Temp
& 0x3F) << 1;
421 Temp
= (uint8_t)(SD_Handle
.CSD
[2] & 0x000000FF);
422 SD_CardInfo
.SD_csd
.EraseGrMul
|= (Temp
& 0x80) >> 7;
423 SD_CardInfo
.SD_csd
.WrProtectGrSize
= (Temp
& 0x7F);
426 Temp
= (uint8_t)((SD_Handle
.CSD
[3] & 0xFF000000) >> 24);
427 SD_CardInfo
.SD_csd
.WrProtectGrEnable
= (Temp
& 0x80) >> 7;
428 SD_CardInfo
.SD_csd
.ManDeflECC
= (Temp
& 0x60) >> 5;
429 SD_CardInfo
.SD_csd
.WrSpeedFact
= (Temp
& 0x1C) >> 2;
430 SD_CardInfo
.SD_csd
.MaxWrBlockLen
= (Temp
& 0x03) << 2;
433 Temp
= (uint8_t)((SD_Handle
.CSD
[3] & 0x00FF0000) >> 16);
434 SD_CardInfo
.SD_csd
.MaxWrBlockLen
|= (Temp
& 0xC0) >> 6;
435 SD_CardInfo
.SD_csd
.WriteBlockPaPartial
= (Temp
& 0x20) >> 5;
436 SD_CardInfo
.SD_csd
.Reserved3
= 0;
437 SD_CardInfo
.SD_csd
.ContentProtectAppli
= (Temp
& 0x01);
440 Temp
= (uint8_t)((SD_Handle
.CSD
[3] & 0x0000FF00) >> 8);
441 SD_CardInfo
.SD_csd
.FileFormatGrouop
= (Temp
& 0x80) >> 7;
442 SD_CardInfo
.SD_csd
.CopyFlag
= (Temp
& 0x40) >> 6;
443 SD_CardInfo
.SD_csd
.PermWrProtect
= (Temp
& 0x20) >> 5;
444 SD_CardInfo
.SD_csd
.TempWrProtect
= (Temp
& 0x10) >> 4;
445 SD_CardInfo
.SD_csd
.FileFormat
= (Temp
& 0x0C) >> 2;
446 SD_CardInfo
.SD_csd
.ECC
= (Temp
& 0x03);
449 Temp
= (uint8_t)(SD_Handle
.CSD
[3] & 0x000000FF);
450 SD_CardInfo
.SD_csd
.CSD_CRC
= (Temp
& 0xFE) >> 1;
451 SD_CardInfo
.SD_csd
.Reserved4
= 1;
454 Temp
= (uint8_t)((SD_Handle
.CID
[0] & 0xFF000000) >> 24);
455 SD_CardInfo
.SD_cid
.ManufacturerID
= Temp
;
458 Temp
= (uint8_t)((SD_Handle
.CID
[0] & 0x00FF0000) >> 16);
459 SD_CardInfo
.SD_cid
.OEM_AppliID
= Temp
<< 8;
462 Temp
= (uint8_t)((SD_Handle
.CID
[0] & 0x000000FF00) >> 8);
463 SD_CardInfo
.SD_cid
.OEM_AppliID
|= Temp
;
466 Temp
= (uint8_t)(SD_Handle
.CID
[0] & 0x000000FF);
467 SD_CardInfo
.SD_cid
.ProdName1
= Temp
<< 24;
470 Temp
= (uint8_t)((SD_Handle
.CID
[1] & 0xFF000000) >> 24);
471 SD_CardInfo
.SD_cid
.ProdName1
|= Temp
<< 16;
474 Temp
= (uint8_t)((SD_Handle
.CID
[1] & 0x00FF0000) >> 16);
475 SD_CardInfo
.SD_cid
.ProdName1
|= Temp
<< 8;
478 Temp
= (uint8_t)((SD_Handle
.CID
[1] & 0x0000FF00) >> 8);
479 SD_CardInfo
.SD_cid
.ProdName1
|= Temp
;
482 Temp
= (uint8_t)(SD_Handle
.CID
[1] & 0x000000FF);
483 SD_CardInfo
.SD_cid
.ProdName2
= Temp
;
486 Temp
= (uint8_t)((SD_Handle
.CID
[2] & 0xFF000000) >> 24);
487 SD_CardInfo
.SD_cid
.ProdRev
= Temp
;
490 Temp
= (uint8_t)((SD_Handle
.CID
[2] & 0x00FF0000) >> 16);
491 SD_CardInfo
.SD_cid
.ProdSN
= Temp
<< 24;
494 Temp
= (uint8_t)((SD_Handle
.CID
[2] & 0x0000FF00) >> 8);
495 SD_CardInfo
.SD_cid
.ProdSN
|= Temp
<< 16;
498 Temp
= (uint8_t)(SD_Handle
.CID
[2] & 0x000000FF);
499 SD_CardInfo
.SD_cid
.ProdSN
|= Temp
<< 8;
502 Temp
= (uint8_t)((SD_Handle
.CID
[3] & 0xFF000000) >> 24);
503 SD_CardInfo
.SD_cid
.ProdSN
|= Temp
;
506 Temp
= (uint8_t)((SD_Handle
.CID
[3] & 0x00FF0000) >> 16);
507 SD_CardInfo
.SD_cid
.Reserved1
|= (Temp
& 0xF0) >> 4;
508 SD_CardInfo
.SD_cid
.ManufactDate
= (Temp
& 0x0F) << 8;
511 Temp
= (uint8_t)((SD_Handle
.CID
[3] & 0x0000FF00) >> 8);
512 SD_CardInfo
.SD_cid
.ManufactDate
|= Temp
;
515 Temp
= (uint8_t)(SD_Handle
.CID
[3] & 0x000000FF);
516 SD_CardInfo
.SD_cid
.CID_CRC
= (Temp
& 0xFE) >> 1;
517 SD_CardInfo
.SD_cid
.Reserved2
= 1;
522 SD_Error_t
SD_Init(void)
524 static bool sdInitAttempted
= false;
525 static SD_Error_t result
= SD_ERROR
;
527 if (sdInitAttempted
) {
531 sdInitAttempted
= true;
533 result
= SD_DoInit();
538 SD_Error_t
SD_CheckWrite(void) {
539 if (SD_Handle
.TXCplt
!= 0) return SD_BUSY
;
543 SD_Error_t
SD_CheckRead(void) {
544 if (SD_Handle
.RXCplt
!= 0) return SD_BUSY
;
548 SD_Error_t
SD_WriteBlocks_DMA(uint64_t WriteAddress
, uint32_t *buffer
, uint32_t BlockSize
, uint32_t NumberOfBlocks
)
550 SD_Error_t ErrorState
= SD_OK
;
551 SD_Handle
.TXCplt
= 1;
553 if (BlockSize
!= 512) {
554 return SD_ERROR
; // unsupported.
557 if ((uint32_t)buffer
& 0x1f) {
558 return SD_ADDR_MISALIGNED
;
561 // Ensure the data is flushed to main memory
562 SCB_CleanDCache_by_Addr(buffer
, NumberOfBlocks
* BlockSize
);
564 HAL_StatusTypeDef status
;
565 if ((status
= HAL_SD_WriteBlocks_DMA(&hsd1
, (uint8_t *)buffer
, WriteAddress
, NumberOfBlocks
)) != HAL_OK
) {
575 uint32_t NumberOfBlocks
;
576 } sdReadParameters_t
;
578 sdReadParameters_t sdReadParameters
;
580 SD_Error_t
SD_ReadBlocks_DMA(uint64_t ReadAddress
, uint32_t *buffer
, uint32_t BlockSize
, uint32_t NumberOfBlocks
)
582 SD_Error_t ErrorState
= SD_OK
;
584 if (BlockSize
!= 512) {
585 return SD_ERROR
; // unsupported.
588 if ((uint32_t)buffer
& 0x1f) {
589 return SD_ADDR_MISALIGNED
;
592 SD_Handle
.RXCplt
= 1;
594 sdReadParameters
.buffer
= buffer
;
595 sdReadParameters
.BlockSize
= BlockSize
;
596 sdReadParameters
.NumberOfBlocks
= NumberOfBlocks
;
598 HAL_StatusTypeDef status
;
599 if ((status
= HAL_SD_ReadBlocks_DMA(&hsd1
, (uint8_t *)buffer
, ReadAddress
, NumberOfBlocks
)) != HAL_OK
) {
607 * @brief Tx Transfer completed callback
608 * @param hsd: SD handle
611 void HAL_SD_TxCpltCallback(SD_HandleTypeDef
*hsd
)
615 SD_Handle
.TXCplt
= 0;
619 * @brief Rx Transfer completed callback
620 * @param hsd: SD handle
623 void HAL_SD_RxCpltCallback(SD_HandleTypeDef
*hsd
)
627 SD_Handle
.RXCplt
= 0;
630 the SCB_InvalidateDCache_by_Addr() requires a 32-Byte aligned address,
631 adjust the address and the D-Cache size to invalidate accordingly.
633 uint32_t alignedAddr
= (uint32_t)sdReadParameters
.buffer
& ~0x1F;
634 SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr
, sdReadParameters
.NumberOfBlocks
* sdReadParameters
.BlockSize
+ ((uint32_t)sdReadParameters
.buffer
- alignedAddr
));
637 void HAL_SD_ErrorCallback(SD_HandleTypeDef
*hsd
)
640 if (SD_Handle
.RXCplt
) {
641 SD_Handle
.RXErrors
++;
642 SD_Handle
.RXCplt
= 0;
645 if (SD_Handle
.TXCplt
) {
646 SD_Handle
.TXErrors
++;
647 SD_Handle
.TXCplt
= 0;
651 void HAL_SD_AbortCallback(SD_HandleTypeDef
*hsd
)
655 SD_Handle
.TXCplt
= 0;
656 SD_Handle
.RXCplt
= 0;
659 void SDMMC1_IRQHandler(void)
661 HAL_SD_IRQHandler(&hsd1
);
664 void SDMMC2_IRQHandler(void)
666 HAL_SD_IRQHandler(&hsd1
);