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"
37 #include "drivers/sdio.h"
38 #include "drivers/io.h"
39 #include "drivers/io_impl.h"
40 #include "drivers/nvic.h"
41 #include "drivers/time.h"
42 #include "drivers/rcc.h"
43 #include "drivers/dma.h"
45 #include "build/debug.h"
47 typedef struct SD_Handle_s
49 uint32_t CSD
[4]; // SD card specific data table
50 uint32_t CID
[4]; // SD card identification number table
51 volatile uint32_t RXCplt
; // SD RX Complete is equal 0 when no transfer
52 volatile uint32_t TXCplt
; // SD TX Complete is equal 0 when no transfer
55 SD_CardInfo_t SD_CardInfo
;
56 SD_CardType_t SD_CardType
;
58 static SD_Handle_t SD_Handle
;
59 static DMA_HandleTypeDef sd_dma
;
60 static SD_HandleTypeDef hsd
;
62 typedef struct sdioPin_s
{
72 #define SDIO_PIN_CMD 5
73 #define SDIO_PIN_COUNT 6
75 #define SDIO_MAX_PINDEFS 2
77 #define IOCFG_SDMMC IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL)
80 #define SDMMC_CLK_DIV SDMMC_TRANSFER_CLK_DIV
82 #if defined(SDCARD_SDIO_NORMAL_SPEED)
83 #define SDMMC_CLK_DIV SDMMC_NSpeed_CLK_DIV
85 #define SDMMC_CLK_DIV SDMMC_HSpeed_CLK_DIV
89 typedef struct sdioHardware_s
{
90 SDMMC_TypeDef
*instance
;
92 sdioPin_t sdioPinCK
[SDIO_MAX_PINDEFS
];
93 sdioPin_t sdioPinCMD
[SDIO_MAX_PINDEFS
];
94 sdioPin_t sdioPinD0
[SDIO_MAX_PINDEFS
];
95 sdioPin_t sdioPinD1
[SDIO_MAX_PINDEFS
];
96 sdioPin_t sdioPinD2
[SDIO_MAX_PINDEFS
];
97 sdioPin_t sdioPinD3
[SDIO_MAX_PINDEFS
];
100 // Possible pin assignments
102 #define PINDEF(device, pin, afnum) { DEFIO_TAG_E(pin), GPIO_AF ## afnum ## _SDMMC ## device }
105 static const sdioHardware_t sdioPinHardware
[SDIODEV_COUNT
] = {
109 .sdioPinCK
= { PINDEF(1, PC12
, 12) },
110 .sdioPinCMD
= { PINDEF(1, PD2
, 12) },
111 .sdioPinD0
= { PINDEF(1, PC8
, 12) },
112 .sdioPinD1
= { PINDEF(1, PC9
, 12) },
113 .sdioPinD2
= { PINDEF(1, PC10
, 12) },
114 .sdioPinD3
= { PINDEF(1, PC11
, 12) },
119 .sdioPinCK
= { PINDEF(2, PC1
, 9), PINDEF(2, PD6
, 11) },
120 .sdioPinCMD
= { PINDEF(2, PA0
, 9), PINDEF(2, PD7
, 11) },
121 .sdioPinD0
= { PINDEF(2, PB14
, 9) },
122 .sdioPinD1
= { PINDEF(2, PB15
, 9) },
123 .sdioPinD2
= { PINDEF(2, PB3
, 9) },
124 .sdioPinD3
= { PINDEF(2, PB4
, 9) },
130 static const sdioHardware_t sdioPinHardware
[SDIODEV_COUNT
] = {
134 .sdioPinCK
= { PINDEF(1, PC12
, 12) },
135 .sdioPinCMD
= { PINDEF(1, PD2
, 12) },
136 .sdioPinD0
= { PINDEF(1, PC8
, 12) },
137 .sdioPinD1
= { PINDEF(1, PC9
, 12) },
138 .sdioPinD2
= { PINDEF(1, PC10
, 12) },
139 .sdioPinD3
= { PINDEF(1, PC11
, 12) },
140 //.sdioPinD4 = { PINDEF(1, PB8, 12) },
141 //.sdioPinD5 = { PINDEF(1, PB9, 12) },
142 //.sdioPinD6 = { PINDEF(1, PC7, 12) },
143 //.sdioPinD7 = { PINDEF(1, PC11, 12) },
148 .sdioPinCK
= { PINDEF(2, PD6
, 11) },
149 .sdioPinCMD
= { PINDEF(2, PD7
, 11) },
150 .sdioPinD0
= { PINDEF(2, PB14
, 10), PINDEF(2, PG0
, 11) },
151 .sdioPinD1
= { PINDEF(2, PB15
, 10), PINDEF(2, PG10
, 11) },
152 .sdioPinD2
= { PINDEF(2, PB3
, 10), PINDEF(2, PG11
, 10) },
153 .sdioPinD3
= { PINDEF(2, PB4
, 10), PINDEF(2, PG12
, 11) },
160 // Active configuration
161 static const sdioHardware_t
*sdioHardware
;
162 static sdioPin_t sdioPin
[SDIO_PIN_COUNT
];
164 void sdioPinConfigure(void)
166 if (SDCARD_SDIO_DEVICE
== SDIOINVALID
) {
170 sdioHardware
= &sdioPinHardware
[SDCARD_SDIO_DEVICE
];
172 #ifdef SDCARD_SDIO2_CK_ALT
173 sdioPin
[SDIO_PIN_CK
] = sdioHardware
->sdioPinCK
[1];
175 sdioPin
[SDIO_PIN_CK
] = sdioHardware
->sdioPinCK
[0];
177 #ifdef SDCARD_SDIO2_CMD_ALT
178 sdioPin
[SDIO_PIN_CMD
] = sdioHardware
->sdioPinCMD
[1];
180 sdioPin
[SDIO_PIN_CMD
] = sdioHardware
->sdioPinCMD
[0];
182 sdioPin
[SDIO_PIN_D0
] = sdioHardware
->sdioPinD0
[0];
184 const IO_t clk
= IOGetByTag(sdioPin
[SDIO_PIN_CK
].pin
);
185 const IO_t cmd
= IOGetByTag(sdioPin
[SDIO_PIN_CMD
].pin
);
186 const IO_t d0
= IOGetByTag(sdioPin
[SDIO_PIN_D0
].pin
);
188 IOInit(clk
, OWNER_SDCARD
, RESOURCE_NONE
, 0);
189 IOInit(cmd
, OWNER_SDCARD
, RESOURCE_NONE
, 0);
190 IOInit(d0
, OWNER_SDCARD
, RESOURCE_NONE
, 0);
192 #ifdef SDCARD_SDIO_4BIT
193 sdioPin
[SDIO_PIN_D1
] = sdioHardware
->sdioPinD1
[0];
194 sdioPin
[SDIO_PIN_D2
] = sdioHardware
->sdioPinD2
[0];
195 sdioPin
[SDIO_PIN_D3
] = sdioHardware
->sdioPinD3
[0];
197 const IO_t d1
= IOGetByTag(sdioPin
[SDIO_PIN_D1
].pin
);
198 const IO_t d2
= IOGetByTag(sdioPin
[SDIO_PIN_D2
].pin
);
199 const IO_t d3
= IOGetByTag(sdioPin
[SDIO_PIN_D3
].pin
);
201 IOInit(d1
, OWNER_SDCARD
, RESOURCE_NONE
, 0);
202 IOInit(d2
, OWNER_SDCARD
, RESOURCE_NONE
, 0);
203 IOInit(d3
, OWNER_SDCARD
, RESOURCE_NONE
, 0);
207 // Setting all the SDIO pins to high for a short time results in more robust
211 IOConfigGPIO(d0
, IOCFG_OUT_PP
);
213 #ifdef SDCARD_SDIO_4BIT
217 IOConfigGPIO(d1
, IOCFG_OUT_PP
);
218 IOConfigGPIO(d2
, IOCFG_OUT_PP
);
219 IOConfigGPIO(d3
, IOCFG_OUT_PP
);
224 IOConfigGPIO(clk
, IOCFG_OUT_PP
);
225 IOConfigGPIO(cmd
, IOCFG_OUT_PP
);
228 void SDMMC_DMA_IRQHandler(DMA_t channel
)
232 HAL_DMA_IRQHandler(&sd_dma
);
235 void HAL_SD_MspInit(SD_HandleTypeDef
* hsd
)
241 if (sdioHardware
->instance
== SDMMC1
) {
242 __HAL_RCC_SDMMC1_CLK_DISABLE();
243 __HAL_RCC_SDMMC1_CLK_ENABLE();
245 __HAL_RCC_SDMMC1_FORCE_RESET();
246 __HAL_RCC_SDMMC1_RELEASE_RESET();
247 } else if (sdioHardware
->instance
== SDMMC2
) {
248 __HAL_RCC_SDMMC2_CLK_DISABLE();
249 __HAL_RCC_SDMMC2_CLK_ENABLE();
251 __HAL_RCC_SDMMC2_FORCE_RESET();
252 __HAL_RCC_SDMMC2_RELEASE_RESET();
255 const IO_t clk
= IOGetByTag(sdioPin
[SDIO_PIN_CK
].pin
);
256 const IO_t cmd
= IOGetByTag(sdioPin
[SDIO_PIN_CMD
].pin
);
257 const IO_t d0
= IOGetByTag(sdioPin
[SDIO_PIN_D0
].pin
);
258 const IO_t d1
= IOGetByTag(sdioPin
[SDIO_PIN_D1
].pin
);
259 const IO_t d2
= IOGetByTag(sdioPin
[SDIO_PIN_D2
].pin
);
260 const IO_t d3
= IOGetByTag(sdioPin
[SDIO_PIN_D3
].pin
);
262 IOConfigGPIOAF(clk
, IOCFG_SDMMC
, sdioPin
[SDIO_PIN_CK
].af
);
263 IOConfigGPIOAF(cmd
, IOCFG_SDMMC
, sdioPin
[SDIO_PIN_CMD
].af
);
264 IOConfigGPIOAF(d0
, IOCFG_SDMMC
, sdioPin
[SDIO_PIN_D0
].af
);
266 #ifdef SDCARD_SDIO_4BIT
267 IOConfigGPIOAF(d1
, IOCFG_SDMMC
, sdioPin
[SDIO_PIN_D1
].af
);
268 IOConfigGPIOAF(d2
, IOCFG_SDMMC
, sdioPin
[SDIO_PIN_D2
].af
);
269 IOConfigGPIOAF(d3
, IOCFG_SDMMC
, sdioPin
[SDIO_PIN_D3
].af
);
273 sd_dma
.Init
.Direction
= DMA_PERIPH_TO_MEMORY
;
274 sd_dma
.Init
.PeriphInc
= DMA_PINC_DISABLE
;
275 sd_dma
.Init
.MemInc
= DMA_MINC_ENABLE
;
276 sd_dma
.Init
.PeriphDataAlignment
= DMA_PDATAALIGN_WORD
;
277 sd_dma
.Init
.MemDataAlignment
= DMA_MDATAALIGN_WORD
;
278 sd_dma
.Init
.Mode
= DMA_PFCTRL
;
279 sd_dma
.Init
.Priority
= DMA_PRIORITY_LOW
;
280 sd_dma
.Init
.FIFOMode
= DMA_FIFOMODE_ENABLE
;
281 sd_dma
.Init
.FIFOThreshold
= DMA_FIFO_THRESHOLD_FULL
;
282 sd_dma
.Init
.MemBurst
= DMA_MBURST_INC4
;
283 sd_dma
.Init
.PeriphBurst
= DMA_PBURST_INC4
;
285 dmaInit(dmaGetByRef(sd_dma
.Instance
), OWNER_SDCARD
, 0);
286 if (HAL_DMA_Init(&sd_dma
) != HAL_OK
) {
289 dmaSetHandler(dmaGetByRef(sd_dma
.Instance
), SDMMC_DMA_IRQHandler
, 1, 0);
291 __HAL_LINKDMA(hsd
, hdmarx
, sd_dma
);
292 __HAL_LINKDMA(hsd
, hdmatx
, sd_dma
);
297 HAL_NVIC_SetPriority(sdioHardware
->irqn
, 2, 0);
298 HAL_NVIC_EnableIRQ(sdioHardware
->irqn
);
301 bool SD_Initialize_LL(DMA_t dma
)
304 sd_dma
.Instance
= dma
->ref
;
305 sd_dma
.Init
.Channel
= dmaGetChannelByTag(SDCARD_SDIO_DMA
);
312 bool SD_GetState(void)
314 HAL_SD_CardStateTypedef cardState
= HAL_SD_GetCardState(&hsd
);
316 return (cardState
== HAL_SD_CARD_TRANSFER
);
321 memset(&hsd
, 0, sizeof(hsd
));
323 hsd
.Instance
= sdioHardware
->instance
;
325 // falling seems to work better ?? no idea whats "right" here
326 hsd
.Init
.ClockEdge
= SDMMC_CLOCK_EDGE_FALLING
;
328 // drastically increases the time to respond from the sdcard
330 hsd
.Init
.ClockPowerSave
= SDMMC_CLOCK_POWER_SAVE_DISABLE
;
332 hsd
.Init
.ClockBypass
= SDMMC_CLOCK_BYPASS_DISABLE
;
334 hsd
.Init
.BusWide
= SDMMC_BUS_WIDE_1B
;
335 hsd
.Init
.HardwareFlowControl
= SDMMC_HARDWARE_FLOW_CONTROL_ENABLE
;
336 hsd
.Init
.ClockDiv
= SDMMC_CLK_DIV
;
338 // Will call HAL_SD_MspInit
339 if (HAL_SD_Init(&hsd
) != HAL_OK
) {
342 if (hsd
.SdCard
.BlockNbr
== 0) {
346 #ifdef SDCARD_SDIO_4BIT
347 if (HAL_SD_ConfigWideBusOperation(&hsd
, SDMMC_BUS_WIDE_4B
) != HAL_OK
) {
352 switch(hsd
.SdCard
.CardType
) {
354 switch (hsd
.SdCard
.CardVersion
) {
356 SD_CardType
= SD_STD_CAPACITY_V1_1
;
359 SD_CardType
= SD_STD_CAPACITY_V2_0
;
367 SD_CardType
= SD_HIGH_CAPACITY
;
374 // STATIC_ASSERT(sizeof(SD_Handle.CSD) == sizeof(hsd.CSD), hal-csd-size-error);
375 memcpy(&SD_Handle
.CSD
, &hsd
.CSD
, sizeof(SD_Handle
.CSD
));
377 // STATIC_ASSERT(sizeof(SD_Handle.CID) == sizeof(hsd.CID), hal-cid-size-error);
378 memcpy(&SD_Handle
.CID
, &hsd
.CID
, sizeof(SD_Handle
.CID
));
383 SD_Error_t
SD_GetCardInfo(void)
385 SD_Error_t ErrorState
= SD_OK
;
387 // fill in SD_CardInfo
392 Temp
= (SD_Handle
.CSD
[0] & 0xFF000000) >> 24;
393 SD_CardInfo
.SD_csd
.CSDStruct
= (uint8_t)((Temp
& 0xC0) >> 6);
394 SD_CardInfo
.SD_csd
.SysSpecVersion
= (uint8_t)((Temp
& 0x3C) >> 2);
395 SD_CardInfo
.SD_csd
.Reserved1
= Temp
& 0x03;
398 Temp
= (SD_Handle
.CSD
[0] & 0x00FF0000) >> 16;
399 SD_CardInfo
.SD_csd
.TAAC
= (uint8_t)Temp
;
402 Temp
= (SD_Handle
.CSD
[0] & 0x0000FF00) >> 8;
403 SD_CardInfo
.SD_csd
.NSAC
= (uint8_t)Temp
;
406 Temp
= SD_Handle
.CSD
[0] & 0x000000FF;
407 SD_CardInfo
.SD_csd
.MaxBusClkFrec
= (uint8_t)Temp
;
410 Temp
= (SD_Handle
.CSD
[1] & 0xFF000000) >> 24;
411 SD_CardInfo
.SD_csd
.CardComdClasses
= (uint16_t)(Temp
<< 4);
414 Temp
= (SD_Handle
.CSD
[1] & 0x00FF0000) >> 16;
415 SD_CardInfo
.SD_csd
.CardComdClasses
|= (uint16_t)((Temp
& 0xF0) >> 4);
416 SD_CardInfo
.SD_csd
.RdBlockLen
= (uint8_t)(Temp
& 0x0F);
419 Temp
= (SD_Handle
.CSD
[1] & 0x0000FF00) >> 8;
420 SD_CardInfo
.SD_csd
.PartBlockRead
= (uint8_t)((Temp
& 0x80) >> 7);
421 SD_CardInfo
.SD_csd
.WrBlockMisalign
= (uint8_t)((Temp
& 0x40) >> 6);
422 SD_CardInfo
.SD_csd
.RdBlockMisalign
= (uint8_t)((Temp
& 0x20) >> 5);
423 SD_CardInfo
.SD_csd
.DSRImpl
= (uint8_t)((Temp
& 0x10) >> 4);
424 SD_CardInfo
.SD_csd
.Reserved2
= 0; /*!< Reserved */
426 if((SD_CardType
== SD_STD_CAPACITY_V1_1
) || (SD_CardType
== SD_STD_CAPACITY_V2_0
)) {
427 SD_CardInfo
.SD_csd
.DeviceSize
= (Temp
& 0x03) << 10;
430 Temp
= (uint8_t)(SD_Handle
.CSD
[1] & 0x000000FF);
431 SD_CardInfo
.SD_csd
.DeviceSize
|= (Temp
) << 2;
434 Temp
= (uint8_t)((SD_Handle
.CSD
[2] & 0xFF000000) >> 24);
435 SD_CardInfo
.SD_csd
.DeviceSize
|= (Temp
& 0xC0) >> 6;
437 SD_CardInfo
.SD_csd
.MaxRdCurrentVDDMin
= (Temp
& 0x38) >> 3;
438 SD_CardInfo
.SD_csd
.MaxRdCurrentVDDMax
= (Temp
& 0x07);
441 Temp
= (uint8_t)((SD_Handle
.CSD
[2] & 0x00FF0000) >> 16);
442 SD_CardInfo
.SD_csd
.MaxWrCurrentVDDMin
= (Temp
& 0xE0) >> 5;
443 SD_CardInfo
.SD_csd
.MaxWrCurrentVDDMax
= (Temp
& 0x1C) >> 2;
444 SD_CardInfo
.SD_csd
.DeviceSizeMul
= (Temp
& 0x03) << 1;
447 Temp
= (uint8_t)((SD_Handle
.CSD
[2] & 0x0000FF00) >> 8);
448 SD_CardInfo
.SD_csd
.DeviceSizeMul
|= (Temp
& 0x80) >> 7;
450 SD_CardInfo
.CardCapacity
= (SD_CardInfo
.SD_csd
.DeviceSize
+ 1) ;
451 SD_CardInfo
.CardCapacity
*= (1 << (SD_CardInfo
.SD_csd
.DeviceSizeMul
+ 2));
452 SD_CardInfo
.CardBlockSize
= 1 << (SD_CardInfo
.SD_csd
.RdBlockLen
);
453 SD_CardInfo
.CardCapacity
= SD_CardInfo
.CardCapacity
* SD_CardInfo
.CardBlockSize
/ 512; // In 512 byte blocks
454 } else if(SD_CardType
== SD_HIGH_CAPACITY
) {
456 Temp
= (uint8_t)(SD_Handle
.CSD
[1] & 0x000000FF);
457 SD_CardInfo
.SD_csd
.DeviceSize
= (Temp
& 0x3F) << 16;
460 Temp
= (uint8_t)((SD_Handle
.CSD
[2] & 0xFF000000) >> 24);
462 SD_CardInfo
.SD_csd
.DeviceSize
|= (Temp
<< 8);
465 Temp
= (uint8_t)((SD_Handle
.CSD
[2] & 0x00FF0000) >> 16);
467 SD_CardInfo
.SD_csd
.DeviceSize
|= (Temp
);
470 Temp
= (uint8_t)((SD_Handle
.CSD
[2] & 0x0000FF00) >> 8);
472 SD_CardInfo
.CardCapacity
= ((uint64_t)SD_CardInfo
.SD_csd
.DeviceSize
+ 1) * 1024;
473 SD_CardInfo
.CardBlockSize
= 512;
475 // Not supported card type
476 ErrorState
= SD_ERROR
;
479 SD_CardInfo
.SD_csd
.EraseGrSize
= (Temp
& 0x40) >> 6;
480 SD_CardInfo
.SD_csd
.EraseGrMul
= (Temp
& 0x3F) << 1;
483 Temp
= (uint8_t)(SD_Handle
.CSD
[2] & 0x000000FF);
484 SD_CardInfo
.SD_csd
.EraseGrMul
|= (Temp
& 0x80) >> 7;
485 SD_CardInfo
.SD_csd
.WrProtectGrSize
= (Temp
& 0x7F);
488 Temp
= (uint8_t)((SD_Handle
.CSD
[3] & 0xFF000000) >> 24);
489 SD_CardInfo
.SD_csd
.WrProtectGrEnable
= (Temp
& 0x80) >> 7;
490 SD_CardInfo
.SD_csd
.ManDeflECC
= (Temp
& 0x60) >> 5;
491 SD_CardInfo
.SD_csd
.WrSpeedFact
= (Temp
& 0x1C) >> 2;
492 SD_CardInfo
.SD_csd
.MaxWrBlockLen
= (Temp
& 0x03) << 2;
495 Temp
= (uint8_t)((SD_Handle
.CSD
[3] & 0x00FF0000) >> 16);
496 SD_CardInfo
.SD_csd
.MaxWrBlockLen
|= (Temp
& 0xC0) >> 6;
497 SD_CardInfo
.SD_csd
.WriteBlockPaPartial
= (Temp
& 0x20) >> 5;
498 SD_CardInfo
.SD_csd
.Reserved3
= 0;
499 SD_CardInfo
.SD_csd
.ContentProtectAppli
= (Temp
& 0x01);
502 Temp
= (uint8_t)((SD_Handle
.CSD
[3] & 0x0000FF00) >> 8);
503 SD_CardInfo
.SD_csd
.FileFormatGrouop
= (Temp
& 0x80) >> 7;
504 SD_CardInfo
.SD_csd
.CopyFlag
= (Temp
& 0x40) >> 6;
505 SD_CardInfo
.SD_csd
.PermWrProtect
= (Temp
& 0x20) >> 5;
506 SD_CardInfo
.SD_csd
.TempWrProtect
= (Temp
& 0x10) >> 4;
507 SD_CardInfo
.SD_csd
.FileFormat
= (Temp
& 0x0C) >> 2;
508 SD_CardInfo
.SD_csd
.ECC
= (Temp
& 0x03);
511 Temp
= (uint8_t)(SD_Handle
.CSD
[3] & 0x000000FF);
512 SD_CardInfo
.SD_csd
.CSD_CRC
= (Temp
& 0xFE) >> 1;
513 SD_CardInfo
.SD_csd
.Reserved4
= 1;
516 Temp
= (uint8_t)((SD_Handle
.CID
[0] & 0xFF000000) >> 24);
517 SD_CardInfo
.SD_cid
.ManufacturerID
= Temp
;
520 Temp
= (uint8_t)((SD_Handle
.CID
[0] & 0x00FF0000) >> 16);
521 SD_CardInfo
.SD_cid
.OEM_AppliID
= Temp
<< 8;
524 Temp
= (uint8_t)((SD_Handle
.CID
[0] & 0x000000FF00) >> 8);
525 SD_CardInfo
.SD_cid
.OEM_AppliID
|= Temp
;
528 Temp
= (uint8_t)(SD_Handle
.CID
[0] & 0x000000FF);
529 SD_CardInfo
.SD_cid
.ProdName1
= Temp
<< 24;
532 Temp
= (uint8_t)((SD_Handle
.CID
[1] & 0xFF000000) >> 24);
533 SD_CardInfo
.SD_cid
.ProdName1
|= Temp
<< 16;
536 Temp
= (uint8_t)((SD_Handle
.CID
[1] & 0x00FF0000) >> 16);
537 SD_CardInfo
.SD_cid
.ProdName1
|= Temp
<< 8;
540 Temp
= (uint8_t)((SD_Handle
.CID
[1] & 0x0000FF00) >> 8);
541 SD_CardInfo
.SD_cid
.ProdName1
|= Temp
;
544 Temp
= (uint8_t)(SD_Handle
.CID
[1] & 0x000000FF);
545 SD_CardInfo
.SD_cid
.ProdName2
= Temp
;
548 Temp
= (uint8_t)((SD_Handle
.CID
[2] & 0xFF000000) >> 24);
549 SD_CardInfo
.SD_cid
.ProdRev
= Temp
;
552 Temp
= (uint8_t)((SD_Handle
.CID
[2] & 0x00FF0000) >> 16);
553 SD_CardInfo
.SD_cid
.ProdSN
= Temp
<< 24;
556 Temp
= (uint8_t)((SD_Handle
.CID
[2] & 0x0000FF00) >> 8);
557 SD_CardInfo
.SD_cid
.ProdSN
|= Temp
<< 16;
560 Temp
= (uint8_t)(SD_Handle
.CID
[2] & 0x000000FF);
561 SD_CardInfo
.SD_cid
.ProdSN
|= Temp
<< 8;
564 Temp
= (uint8_t)((SD_Handle
.CID
[3] & 0xFF000000) >> 24);
565 SD_CardInfo
.SD_cid
.ProdSN
|= Temp
;
568 Temp
= (uint8_t)((SD_Handle
.CID
[3] & 0x00FF0000) >> 16);
569 SD_CardInfo
.SD_cid
.Reserved1
|= (Temp
& 0xF0) >> 4;
570 SD_CardInfo
.SD_cid
.ManufactDate
= (Temp
& 0x0F) << 8;
573 Temp
= (uint8_t)((SD_Handle
.CID
[3] & 0x0000FF00) >> 8);
574 SD_CardInfo
.SD_cid
.ManufactDate
|= Temp
;
577 Temp
= (uint8_t)(SD_Handle
.CID
[3] & 0x000000FF);
578 SD_CardInfo
.SD_cid
.CID_CRC
= (Temp
& 0xFE) >> 1;
579 SD_CardInfo
.SD_cid
.Reserved2
= 1;
584 SD_Error_t
SD_CheckWrite(void) {
585 if (SD_Handle
.TXCplt
!= 0) return SD_BUSY
;
589 SD_Error_t
SD_CheckRead(void) {
590 if (SD_Handle
.RXCplt
!= 0) return SD_BUSY
;
594 SD_Error_t
SD_WriteBlocks_DMA(uint64_t WriteAddress
, uint32_t *buffer
, uint32_t BlockSize
, uint32_t NumberOfBlocks
)
596 SD_Error_t ErrorState
= SD_OK
;
597 SD_Handle
.TXCplt
= 1;
599 if (BlockSize
!= 512) {
600 return SD_ERROR
; // unsupported.
604 if ((uint32_t)buffer
& 0x1f) {
605 return SD_ADDR_MISALIGNED
;
609 // Ensure the data is flushed to main memory
610 SCB_CleanDCache_by_Addr(buffer
, NumberOfBlocks
* BlockSize
);
613 if (sd_dma
.Init
.Direction
!= DMA_MEMORY_TO_PERIPH
) {
614 sd_dma
.Init
.Direction
= DMA_MEMORY_TO_PERIPH
;
615 if (HAL_DMA_Init(&sd_dma
) != HAL_OK
) {
620 if (HAL_SD_WriteBlocks_DMA(&hsd
, (uint8_t *)buffer
, WriteAddress
, NumberOfBlocks
) != HAL_OK
) {
630 uint32_t NumberOfBlocks
;
631 } sdReadParameters_t
;
633 sdReadParameters_t sdReadParameters
;
635 SD_Error_t
SD_ReadBlocks_DMA(uint64_t ReadAddress
, uint32_t *buffer
, uint32_t BlockSize
, uint32_t NumberOfBlocks
)
637 SD_Error_t ErrorState
= SD_OK
;
639 if (BlockSize
!= 512) {
640 return SD_ERROR
; // unsupported.
644 if ((uint32_t)buffer
& 0x1f) {
645 return SD_ADDR_MISALIGNED
;
649 SD_Handle
.RXCplt
= 1;
651 sdReadParameters
.buffer
= buffer
;
652 sdReadParameters
.BlockSize
= BlockSize
;
653 sdReadParameters
.NumberOfBlocks
= NumberOfBlocks
;
656 if (sd_dma
.Init
.Direction
!= DMA_PERIPH_TO_MEMORY
) {
657 sd_dma
.Init
.Direction
= DMA_PERIPH_TO_MEMORY
;
658 if (HAL_DMA_Init(&sd_dma
) != HAL_OK
) {
663 if (HAL_SD_ReadBlocks_DMA(&hsd
, (uint8_t *)buffer
, ReadAddress
, NumberOfBlocks
) != HAL_OK
) {
671 * @brief Tx Transfer completed callback
672 * @param hsd: SD handle
675 void HAL_SD_TxCpltCallback(SD_HandleTypeDef
*hsd
)
679 SD_Handle
.TXCplt
= 0;
683 * @brief Rx Transfer completed callback
684 * @param hsd: SD handle
687 void HAL_SD_RxCpltCallback(SD_HandleTypeDef
*hsd
)
691 SD_Handle
.RXCplt
= 0;
694 the SCB_InvalidateDCache_by_Addr() requires a 32-Byte aligned address,
695 adjust the address and the D-Cache size to invalidate accordingly.
697 uint32_t alignedAddr
= (uint32_t)sdReadParameters
.buffer
& ~0x1F;
698 SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr
, sdReadParameters
.NumberOfBlocks
* sdReadParameters
.BlockSize
+ ((uint32_t)sdReadParameters
.buffer
- alignedAddr
));
701 void HAL_SD_AbortCallback(SD_HandleTypeDef
*hsd
)
705 SD_Handle
.TXCplt
= 0;
706 SD_Handle
.RXCplt
= 0;
709 void SDMMC1_IRQHandler(void)
711 HAL_SD_IRQHandler(&hsd
);
714 void SDMMC2_IRQHandler(void)
716 HAL_SD_IRQHandler(&hsd
);