Merge pull request #10558 from iNavFlight/MrD_Correct-comments-on-OSD-symbols
[inav.git] / src / main / drivers / sdcard / sdmmc_sdio_hal.c
bloba0813bd35d83752dcfe80089a238f4cb0d109c5b
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 "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
53 } SD_Handle_t;
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 {
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 #define IOCFG_SDMMC IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL)
79 #ifdef STM32F7
80 #define SDMMC_CLK_DIV SDMMC_TRANSFER_CLK_DIV
81 #else
82 #if defined(SDCARD_SDIO_NORMAL_SPEED)
83 #define SDMMC_CLK_DIV SDMMC_NSpeed_CLK_DIV
84 #else
85 #define SDMMC_CLK_DIV SDMMC_HSpeed_CLK_DIV
86 #endif
87 #endif
89 typedef struct sdioHardware_s {
90 SDMMC_TypeDef *instance;
91 IRQn_Type irqn;
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];
98 } sdioHardware_t;
100 // Possible pin assignments
102 #define PINDEF(device, pin, afnum) { DEFIO_TAG_E(pin), GPIO_AF ## afnum ## _SDMMC ## device }
104 #ifdef STM32H7
105 static const sdioHardware_t sdioPinHardware[SDIODEV_COUNT] = {
107 .instance = SDMMC1,
108 .irqn = SDMMC1_IRQn,
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) },
117 .instance = SDMMC2,
118 .irqn = SDMMC2_IRQn,
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) },
127 #endif
129 #ifdef STM32F7
130 static const sdioHardware_t sdioPinHardware[SDIODEV_COUNT] = {
132 .instance = SDMMC1,
133 .irqn = SDMMC1_IRQn,
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) },
146 .instance = SDMMC2,
147 .irqn = SDMMC2_IRQn,
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) },
156 #endif
158 #undef PINDEF
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) {
167 return;
170 sdioHardware = &sdioPinHardware[SDCARD_SDIO_DEVICE];
172 #ifdef SDCARD_SDIO2_CK_ALT
173 sdioPin[SDIO_PIN_CK] = sdioHardware->sdioPinCK[1];
174 #else
175 sdioPin[SDIO_PIN_CK] = sdioHardware->sdioPinCK[0];
176 #endif
177 #ifdef SDCARD_SDIO2_CMD_ALT
178 sdioPin[SDIO_PIN_CMD] = sdioHardware->sdioPinCMD[1];
179 #else
180 sdioPin[SDIO_PIN_CMD] = sdioHardware->sdioPinCMD[0];
181 #endif
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);
204 #endif
207 // Setting all the SDIO pins to high for a short time results in more robust
208 // initialisation.
210 IOHi(d0);
211 IOConfigGPIO(d0, IOCFG_OUT_PP);
213 #ifdef SDCARD_SDIO_4BIT
214 IOHi(d1);
215 IOHi(d2);
216 IOHi(d3);
217 IOConfigGPIO(d1, IOCFG_OUT_PP);
218 IOConfigGPIO(d2, IOCFG_OUT_PP);
219 IOConfigGPIO(d3, IOCFG_OUT_PP);
220 #endif
222 IOHi(clk);
223 IOHi(cmd);
224 IOConfigGPIO(clk, IOCFG_OUT_PP);
225 IOConfigGPIO(cmd, IOCFG_OUT_PP);
228 void SDMMC_DMA_IRQHandler(DMA_t channel)
230 UNUSED(channel);
232 HAL_DMA_IRQHandler(&sd_dma);
235 void HAL_SD_MspInit(SD_HandleTypeDef* hsd)
237 if (!sdioHardware) {
238 return;
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);
270 #endif
272 #ifdef STM32F7
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) {
287 return;
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);
293 #else
294 UNUSED(hsd);
295 #endif
297 HAL_NVIC_SetPriority(sdioHardware->irqn, 2, 0);
298 HAL_NVIC_EnableIRQ(sdioHardware->irqn);
301 bool SD_Initialize_LL(DMA_t dma)
303 #ifdef STM32F7
304 sd_dma.Instance = dma->ref;
305 sd_dma.Init.Channel = dmaGetChannelByTag(SDCARD_SDIO_DMA);
306 #else
307 UNUSED(dma);
308 #endif
309 return true;
312 bool SD_GetState(void)
314 HAL_SD_CardStateTypedef cardState = HAL_SD_GetCardState(&hsd);
316 return (cardState == HAL_SD_CARD_TRANSFER);
319 bool SD_Init(void)
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
329 // lets leave it off
330 hsd.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
331 #ifdef STM32F7
332 hsd.Init.ClockBypass = SDMMC_CLOCK_BYPASS_DISABLE;
333 #endif
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) {
340 return SD_ERROR;
342 if (hsd.SdCard.BlockNbr == 0) {
343 return SD_ERROR;
346 #ifdef SDCARD_SDIO_4BIT
347 if (HAL_SD_ConfigWideBusOperation(&hsd, SDMMC_BUS_WIDE_4B) != HAL_OK) {
348 return SD_ERROR;
350 #endif
352 switch(hsd.SdCard.CardType) {
353 case CARD_SDSC:
354 switch (hsd.SdCard.CardVersion) {
355 case CARD_V1_X:
356 SD_CardType = SD_STD_CAPACITY_V1_1;
357 break;
358 case CARD_V2_X:
359 SD_CardType = SD_STD_CAPACITY_V2_0;
360 break;
361 default:
362 return SD_ERROR;
364 break;
366 case CARD_SDHC_SDXC:
367 SD_CardType = SD_HIGH_CAPACITY;
368 break;
370 default:
371 return SD_ERROR;
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));
380 return SD_OK;
383 SD_Error_t SD_GetCardInfo(void)
385 SD_Error_t ErrorState = SD_OK;
387 // fill in SD_CardInfo
389 uint32_t Temp = 0;
391 // Byte 0
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;
397 // Byte 1
398 Temp = (SD_Handle.CSD[0] & 0x00FF0000) >> 16;
399 SD_CardInfo.SD_csd.TAAC = (uint8_t)Temp;
401 // Byte 2
402 Temp = (SD_Handle.CSD[0] & 0x0000FF00) >> 8;
403 SD_CardInfo.SD_csd.NSAC = (uint8_t)Temp;
405 // Byte 3
406 Temp = SD_Handle.CSD[0] & 0x000000FF;
407 SD_CardInfo.SD_csd.MaxBusClkFrec = (uint8_t)Temp;
409 // Byte 4
410 Temp = (SD_Handle.CSD[1] & 0xFF000000) >> 24;
411 SD_CardInfo.SD_csd.CardComdClasses = (uint16_t)(Temp << 4);
413 // Byte 5
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);
418 // Byte 6
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;
429 // Byte 7
430 Temp = (uint8_t)(SD_Handle.CSD[1] & 0x000000FF);
431 SD_CardInfo.SD_csd.DeviceSize |= (Temp) << 2;
433 // Byte 8
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);
440 // Byte 9
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;
446 // Byte 10
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) {
455 // Byte 7
456 Temp = (uint8_t)(SD_Handle.CSD[1] & 0x000000FF);
457 SD_CardInfo.SD_csd.DeviceSize = (Temp & 0x3F) << 16;
459 // Byte 8
460 Temp = (uint8_t)((SD_Handle.CSD[2] & 0xFF000000) >> 24);
462 SD_CardInfo.SD_csd.DeviceSize |= (Temp << 8);
464 // Byte 9
465 Temp = (uint8_t)((SD_Handle.CSD[2] & 0x00FF0000) >> 16);
467 SD_CardInfo.SD_csd.DeviceSize |= (Temp);
469 // Byte 10
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;
474 } else {
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;
482 // Byte 11
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);
487 // Byte 12
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;
494 // Byte 13
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);
501 // Byte 14
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);
510 // Byte 15
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;
515 // Byte 0
516 Temp = (uint8_t)((SD_Handle.CID[0] & 0xFF000000) >> 24);
517 SD_CardInfo.SD_cid.ManufacturerID = Temp;
519 // Byte 1
520 Temp = (uint8_t)((SD_Handle.CID[0] & 0x00FF0000) >> 16);
521 SD_CardInfo.SD_cid.OEM_AppliID = Temp << 8;
523 // Byte 2
524 Temp = (uint8_t)((SD_Handle.CID[0] & 0x000000FF00) >> 8);
525 SD_CardInfo.SD_cid.OEM_AppliID |= Temp;
527 // Byte 3
528 Temp = (uint8_t)(SD_Handle.CID[0] & 0x000000FF);
529 SD_CardInfo.SD_cid.ProdName1 = Temp << 24;
531 // Byte 4
532 Temp = (uint8_t)((SD_Handle.CID[1] & 0xFF000000) >> 24);
533 SD_CardInfo.SD_cid.ProdName1 |= Temp << 16;
535 // Byte 5
536 Temp = (uint8_t)((SD_Handle.CID[1] & 0x00FF0000) >> 16);
537 SD_CardInfo.SD_cid.ProdName1 |= Temp << 8;
539 // Byte 6
540 Temp = (uint8_t)((SD_Handle.CID[1] & 0x0000FF00) >> 8);
541 SD_CardInfo.SD_cid.ProdName1 |= Temp;
543 // Byte 7
544 Temp = (uint8_t)(SD_Handle.CID[1] & 0x000000FF);
545 SD_CardInfo.SD_cid.ProdName2 = Temp;
547 // Byte 8
548 Temp = (uint8_t)((SD_Handle.CID[2] & 0xFF000000) >> 24);
549 SD_CardInfo.SD_cid.ProdRev = Temp;
551 // Byte 9
552 Temp = (uint8_t)((SD_Handle.CID[2] & 0x00FF0000) >> 16);
553 SD_CardInfo.SD_cid.ProdSN = Temp << 24;
555 // Byte 10
556 Temp = (uint8_t)((SD_Handle.CID[2] & 0x0000FF00) >> 8);
557 SD_CardInfo.SD_cid.ProdSN |= Temp << 16;
559 // Byte 11
560 Temp = (uint8_t)(SD_Handle.CID[2] & 0x000000FF);
561 SD_CardInfo.SD_cid.ProdSN |= Temp << 8;
563 // Byte 12
564 Temp = (uint8_t)((SD_Handle.CID[3] & 0xFF000000) >> 24);
565 SD_CardInfo.SD_cid.ProdSN |= Temp;
567 // Byte 13
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;
572 // Byte 14
573 Temp = (uint8_t)((SD_Handle.CID[3] & 0x0000FF00) >> 8);
574 SD_CardInfo.SD_cid.ManufactDate |= Temp;
576 // Byte 15
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;
581 return ErrorState;
584 SD_Error_t SD_CheckWrite(void) {
585 if (SD_Handle.TXCplt != 0) return SD_BUSY;
586 return SD_OK;
589 SD_Error_t SD_CheckRead(void) {
590 if (SD_Handle.RXCplt != 0) return SD_BUSY;
591 return SD_OK;
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.
603 #ifndef STM32F7
604 if ((uint32_t)buffer & 0x1f) {
605 return SD_ADDR_MISALIGNED;
607 #endif
609 // Ensure the data is flushed to main memory
610 SCB_CleanDCache_by_Addr(buffer, NumberOfBlocks * BlockSize);
612 #ifdef STM32F7
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) {
616 return SD_ERROR;
619 #endif
620 if (HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t *)buffer, WriteAddress, NumberOfBlocks) != HAL_OK) {
621 return SD_ERROR;
624 return ErrorState;
627 typedef struct {
628 uint32_t *buffer;
629 uint32_t BlockSize;
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.
643 #ifndef STM32F7
644 if ((uint32_t)buffer & 0x1f) {
645 return SD_ADDR_MISALIGNED;
647 #endif
649 SD_Handle.RXCplt = 1;
651 sdReadParameters.buffer = buffer;
652 sdReadParameters.BlockSize = BlockSize;
653 sdReadParameters.NumberOfBlocks = NumberOfBlocks;
655 #ifdef STM32F7
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) {
659 return SD_ERROR;
662 #endif
663 if (HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t *)buffer, ReadAddress, NumberOfBlocks) != HAL_OK) {
664 return SD_ERROR;
667 return ErrorState;
671 * @brief Tx Transfer completed callback
672 * @param hsd: SD handle
673 * @retval None
675 void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
677 UNUSED(hsd);
679 SD_Handle.TXCplt = 0;
683 * @brief Rx Transfer completed callback
684 * @param hsd: SD handle
685 * @retval None
687 void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
689 UNUSED(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)
703 UNUSED(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);
719 #endif