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 bool SD_Initialize_LL(DMA_Stream_TypeDef
*dma
)
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
;
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
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
289 status
= HAL_SD_Init(&hsd1
); // Will call HAL_SD_MspInit
291 if (status
!= HAL_OK
) {
295 switch(hsd1
.SdCard
.CardType
) {
297 switch (hsd1
.SdCard
.CardVersion
) {
299 SD_CardType
= SD_STD_CAPACITY_V1_1
;
302 SD_CardType
= SD_STD_CAPACITY_V2_0
;
310 SD_CardType
= SD_HIGH_CAPACITY
;
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
));
326 SD_Error_t
SD_GetCardInfo(void)
328 SD_Error_t ErrorState
= SD_OK
;
330 // fill in SD_CardInfo
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;
341 Temp
= (SD_Handle
.CSD
[0] & 0x00FF0000) >> 16;
342 SD_CardInfo
.SD_csd
.TAAC
= (uint8_t)Temp
;
345 Temp
= (SD_Handle
.CSD
[0] & 0x0000FF00) >> 8;
346 SD_CardInfo
.SD_csd
.NSAC
= (uint8_t)Temp
;
349 Temp
= SD_Handle
.CSD
[0] & 0x000000FF;
350 SD_CardInfo
.SD_csd
.MaxBusClkFrec
= (uint8_t)Temp
;
353 Temp
= (SD_Handle
.CSD
[1] & 0xFF000000) >> 24;
354 SD_CardInfo
.SD_csd
.CardComdClasses
= (uint16_t)(Temp
<< 4);
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);
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;
373 Temp
= (uint8_t)(SD_Handle
.CSD
[1] & 0x000000FF);
374 SD_CardInfo
.SD_csd
.DeviceSize
|= (Temp
) << 2;
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);
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;
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
) {
399 Temp
= (uint8_t)(SD_Handle
.CSD
[1] & 0x000000FF);
400 SD_CardInfo
.SD_csd
.DeviceSize
= (Temp
& 0x3F) << 16;
403 Temp
= (uint8_t)((SD_Handle
.CSD
[2] & 0xFF000000) >> 24);
405 SD_CardInfo
.SD_csd
.DeviceSize
|= (Temp
<< 8);
408 Temp
= (uint8_t)((SD_Handle
.CSD
[2] & 0x00FF0000) >> 16);
410 SD_CardInfo
.SD_csd
.DeviceSize
|= (Temp
);
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;
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;
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);
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;
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);
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);
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;
459 Temp
= (uint8_t)((SD_Handle
.CID
[0] & 0xFF000000) >> 24);
460 SD_CardInfo
.SD_cid
.ManufacturerID
= Temp
;
463 Temp
= (uint8_t)((SD_Handle
.CID
[0] & 0x00FF0000) >> 16);
464 SD_CardInfo
.SD_cid
.OEM_AppliID
= Temp
<< 8;
467 Temp
= (uint8_t)((SD_Handle
.CID
[0] & 0x000000FF00) >> 8);
468 SD_CardInfo
.SD_cid
.OEM_AppliID
|= Temp
;
471 Temp
= (uint8_t)(SD_Handle
.CID
[0] & 0x000000FF);
472 SD_CardInfo
.SD_cid
.ProdName1
= Temp
<< 24;
475 Temp
= (uint8_t)((SD_Handle
.CID
[1] & 0xFF000000) >> 24);
476 SD_CardInfo
.SD_cid
.ProdName1
|= Temp
<< 16;
479 Temp
= (uint8_t)((SD_Handle
.CID
[1] & 0x00FF0000) >> 16);
480 SD_CardInfo
.SD_cid
.ProdName1
|= Temp
<< 8;
483 Temp
= (uint8_t)((SD_Handle
.CID
[1] & 0x0000FF00) >> 8);
484 SD_CardInfo
.SD_cid
.ProdName1
|= Temp
;
487 Temp
= (uint8_t)(SD_Handle
.CID
[1] & 0x000000FF);
488 SD_CardInfo
.SD_cid
.ProdName2
= Temp
;
491 Temp
= (uint8_t)((SD_Handle
.CID
[2] & 0xFF000000) >> 24);
492 SD_CardInfo
.SD_cid
.ProdRev
= Temp
;
495 Temp
= (uint8_t)((SD_Handle
.CID
[2] & 0x00FF0000) >> 16);
496 SD_CardInfo
.SD_cid
.ProdSN
= Temp
<< 24;
499 Temp
= (uint8_t)((SD_Handle
.CID
[2] & 0x0000FF00) >> 8);
500 SD_CardInfo
.SD_cid
.ProdSN
|= Temp
<< 16;
503 Temp
= (uint8_t)(SD_Handle
.CID
[2] & 0x000000FF);
504 SD_CardInfo
.SD_cid
.ProdSN
|= Temp
<< 8;
507 Temp
= (uint8_t)((SD_Handle
.CID
[3] & 0xFF000000) >> 24);
508 SD_CardInfo
.SD_cid
.ProdSN
|= Temp
;
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;
516 Temp
= (uint8_t)((SD_Handle
.CID
[3] & 0x0000FF00) >> 8);
517 SD_CardInfo
.SD_cid
.ManufactDate
|= Temp
;
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;
527 SD_Error_t
SD_Init(void)
529 static bool sdInitAttempted
= false;
530 static SD_Error_t result
= SD_ERROR
;
532 if (sdInitAttempted
) {
536 sdInitAttempted
= true;
538 result
= SD_DoInit();
543 SD_Error_t
SD_CheckWrite(void) {
544 if (SD_Handle
.TXCplt
!= 0) return SD_BUSY
;
548 SD_Error_t
SD_CheckRead(void) {
549 if (SD_Handle
.RXCplt
!= 0) return SD_BUSY
;
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
) {
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
) {
612 * @brief Tx Transfer completed callback
613 * @param hsd: SD handle
616 void HAL_SD_TxCpltCallback(SD_HandleTypeDef
*hsd
)
620 SD_Handle
.TXCplt
= 0;
624 * @brief Rx Transfer completed callback
625 * @param hsd: SD handle
628 void HAL_SD_RxCpltCallback(SD_HandleTypeDef
*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
)
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
)
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
);