Skip to content

Commit 34676ad

Browse files
committed
fix(sdcard): migrate dmaInit() to ownership-checked dmaAllocate()
sdcard.c (SPI-mode) and sdio_f4xx.c/sdio_f7xx.c (SDIO-mode) called dmaInit(), which silently overwrites any existing DMA owner. Replace with dmaAllocate() + dmaEnable(), matching the pattern already used by ADC, transponder, LED strip, and motors. sdcard.c falls back to polled SPI (clearing useDMAForTx) on claim failure instead of aborting card init entirely -- useDMAForTx is already checked as a runtime gate at every transfer/completion site, so this is a supported fallback, not a new code path. Losing DMA acceleration is preferable to losing the SD card (and blackbox logging) over an unrelated DMA conflict. sdio_f4xx.c/sdio_f7xx.c change SD_Initialize_LL() from void to bool, matching BF's return type, with the claim check moved to the very top before any RCC/GPIO/DMA register access. sdio_h7xx.c's no-op stub (H7 uses internal IDMA) is now bool too, matching BF exactly. The claim intentionally resolves the DMA identifier from the `dma` parameter, not a file-scope static -- BF 4.5-maintenance's own equivalent computes it from a stale static assigned only after the check, making dmaAllocate() operate on an invalid identifier and the function always return false. That bug was fixed in BF master (PR#14990, function since renamed SD_InitialiseHardware) as a side effect of an unrelated DMA-API refactor, not a targeted fix. Not filed upstream per explicit instruction; tracked in BF45-SDIO-DMASTREAM-BUG.md instead. Two callers (usbd_storage_sdio.c, sdcard_sdio_baremetal.c) previously ignored SD_Initialize_LL()'s return value entirely. Since neither caller configures the DMA stream itself, a claim failure would leave the file-scope dma_stream pointer NULL, and the first real card transfer would dereference it in SD_StartBlockTransfert() -- both callers now check the return and bail to SDCARD_STATE_NOT_PRESENT (or an equivalent failure return) instead. sdcard_init() and SD_Initialize_LL() can each be called twice per boot (once from fc_init.c, once from the USB MSC passthrough path) for the same logical OWNER_SDCARD. Added sdcardDmaClaim()/ sdioDmaClaim(), matching the existing uartDmaClaim()/dshotDmaClaim() pattern: a stream already held by the same owner+resourceIndex is treated as an already-successful claim, so the second call is not mistaken for a real conflict.
1 parent a4ca6ad commit 34676ad

7 files changed

Lines changed: 58 additions & 14 deletions

File tree

src/main/drivers/sdcard.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,15 @@ static bool sdcard_checkInitDone(void) {
473473
return status == 0x00;
474474
}
475475

476+
// sdcard_init() can be called from both boot init and the USB MSC passthrough path -- a
477+
// stream already held by this same owner must be re-claimable.
478+
static bool sdcardDmaClaim(dmaIdentifier_e identifier, resourceOwner_e owner, uint8_t resourceIndex) {
479+
if (dmaGetOwner(identifier) == owner && dmaGetResourceIndex(identifier) == resourceIndex) {
480+
return true;
481+
}
482+
return dmaAllocate(identifier, owner, resourceIndex);
483+
}
484+
476485
/**
477486
* Begin the initialization process for the SD card. This must be called first before any other sdcard_ routine.
478487
*/
@@ -489,11 +498,17 @@ void sdcard_init(const sdcardConfig_t *config) {
489498
sdcard.useDMAForTx = config->useDma;
490499
#endif
491500
if (sdcard.useDMAForTx) {
501+
if (sdcardDmaClaim(config->dmaIdentifier, OWNER_SDCARD, 0)) {
492502
#if defined(STM32F4) || defined(STM32F7)
493-
sdcard.dmaChannel = config->dmaChannel;
503+
sdcard.dmaChannel = config->dmaChannel;
494504
#endif
495-
sdcard.dma = dmaGetDescriptorByIdentifier(config->dmaIdentifier);
496-
dmaInit(config->dmaIdentifier, OWNER_SDCARD, 0);
505+
sdcard.dma = dmaGetDescriptorByIdentifier(config->dmaIdentifier);
506+
dmaEnable(config->dmaIdentifier);
507+
} else {
508+
// Stream already owned by another peripheral -- fall back to polled SPI
509+
// rather than losing the card (and blackbox logging) entirely.
510+
sdcard.useDMAForTx = false;
511+
}
497512
}
498513
if (config->chipSelectTag) {
499514
sdcard.chipSelectPin = IOGetByTag(config->chipSelectTag);

src/main/drivers/sdcard_sdio_baremetal.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,14 @@ void sdcard_init(const sdcardConfig_t *config) {
286286
sdcard.useCache = 0;
287287
}
288288
#if defined(STM32H7)
289-
SD_Initialize_LL(NULL);
289+
if (!SD_Initialize_LL(NULL)) {
290290
#else
291-
SD_Initialize_LL(dmaGetRefByIdentifier(sdcard.dma));
291+
if (!SD_Initialize_LL(dmaGetRefByIdentifier(sdcard.dma))) {
292292
#endif
293+
sdcard.state = SDCARD_STATE_NOT_PRESENT;
294+
sdcard.failureCount++;
295+
return;
296+
}
293297
if (SD_IsDetected()) {
294298
if (SD_Init() != 0) {
295299
sdcard.state = SDCARD_STATE_NOT_PRESENT;

src/main/drivers/sdio_f4xx.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,11 +1305,24 @@ static SD_Error_t SD_IsCardProgramming(uint8_t *pStatus)
13051305
}
13061306
*/
13071307

1308+
// SD_Initialize_LL() can be called from both the sdcard driver's own init and the USB MSC
1309+
// passthrough path -- a stream already held by this same owner must be re-claimable.
1310+
static bool sdioDmaClaim(dmaIdentifier_e identifier, resourceOwner_e owner, uint8_t resourceIndex) {
1311+
if (dmaGetOwner(identifier) == owner && dmaGetResourceIndex(identifier) == resourceIndex) {
1312+
return true;
1313+
}
1314+
return dmaAllocate(identifier, owner, resourceIndex);
1315+
}
1316+
13081317
/** -----------------------------------------------------------------------------------------------------------------*/
13091318
/**
13101319
* @brief Initialize the SDIO module, DMA, and IO
13111320
*/
1312-
void SD_Initialize_LL(DMA_Stream_TypeDef *dma) {
1321+
bool SD_Initialize_LL(DMA_Stream_TypeDef *dma) {
1322+
if (!(dma == DMA2_Stream3 || dma == DMA2_Stream6) || !sdioDmaClaim(dmaGetIdentifier(dma), OWNER_SDCARD, 0)) {
1323+
return false;
1324+
}
1325+
dmaEnable(dmaGetIdentifier(dma));
13131326
// Reset SDIO Module
13141327
RCC->APB2RSTR |= RCC_APB2RSTR_SDIORST;
13151328
delay(1);
@@ -1362,7 +1375,6 @@ void SD_Initialize_LL(DMA_Stream_TypeDef *dma) {
13621375
DMA_MBURST_INC4 | DMA_PBURST_INC4 |
13631376
DMA_MEMORY_TO_PERIPH);
13641377
DMA2_Stream3->FCR = (DMA_SxFCR_DMDIS | DMA_SxFCR_FTH); // Configuration FIFO control register
1365-
dmaInit(dmaGetIdentifier(DMA2_Stream3), OWNER_SDCARD, 0);
13661378
dmaSetHandler(dmaGetIdentifier(DMA2_Stream3), SDIO_DMA_ST3_IRQHandler, 1, 0);
13671379
} else {
13681380
// Initialize DMA2 channel 6
@@ -1375,9 +1387,9 @@ void SD_Initialize_LL(DMA_Stream_TypeDef *dma) {
13751387
DMA_MBURST_INC4 | DMA_PBURST_INC4 |
13761388
DMA_MEMORY_TO_PERIPH);
13771389
DMA2_Stream6->FCR = (DMA_SxFCR_DMDIS | DMA_SxFCR_FTH); // Configuration FIFO control register
1378-
dmaInit(dmaGetIdentifier(DMA2_Stream6), OWNER_SDCARD, 0);
13791390
dmaSetHandler(dmaGetIdentifier(DMA2_Stream6), SDIO_DMA_ST6_IRQHandler, 1, 0);
13801391
}
1392+
return true;
13811393
}
13821394

13831395

src/main/drivers/sdio_f7xx.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,11 +1326,24 @@ static SD_Error_t SD_IsCardProgramming(uint8_t *pStatus)
13261326
}
13271327
*/
13281328

1329+
// SD_Initialize_LL() can be called from both the sdcard driver's own init and the USB MSC
1330+
// passthrough path -- a stream already held by this same owner must be re-claimable.
1331+
static bool sdioDmaClaim(dmaIdentifier_e identifier, resourceOwner_e owner, uint8_t resourceIndex) {
1332+
if (dmaGetOwner(identifier) == owner && dmaGetResourceIndex(identifier) == resourceIndex) {
1333+
return true;
1334+
}
1335+
return dmaAllocate(identifier, owner, resourceIndex);
1336+
}
1337+
13291338
/** -----------------------------------------------------------------------------------------------------------------*/
13301339
/**
13311340
* @brief Initialize the SDMMC1 module, DMA, and IO
13321341
*/
1333-
void SD_Initialize_LL(DMA_Stream_TypeDef *dma) {
1342+
bool SD_Initialize_LL(DMA_Stream_TypeDef *dma) {
1343+
if (!(dma == DMA2_Stream3 || dma == DMA2_Stream6) || !sdioDmaClaim(dmaGetIdentifier(dma), OWNER_SDCARD, 0)) {
1344+
return false;
1345+
}
1346+
dmaEnable(dmaGetIdentifier(dma));
13341347
// Reset SDMMC1 Module
13351348
RCC->APB2RSTR |= RCC_APB2RSTR_SDMMC1RST;
13361349
delay(1);
@@ -1386,7 +1399,6 @@ void SD_Initialize_LL(DMA_Stream_TypeDef *dma) {
13861399
DMA_MBURST_INC4 | DMA_PBURST_INC4 |
13871400
DMA_MEMORY_TO_PERIPH);
13881401
DMA2_Stream3->FCR = (DMA_SxFCR_DMDIS | DMA_SxFCR_FTH); // Configuration FIFO control register
1389-
dmaInit(dmaGetIdentifier(DMA2_Stream3), OWNER_SDCARD, 0);
13901402
dmaSetHandler(dmaGetIdentifier(DMA2_Stream3), SDMMC_DMA_ST3_IRQHandler, 1, 0);
13911403
} else {
13921404
// Initialize DMA2 channel 6
@@ -1399,9 +1411,9 @@ void SD_Initialize_LL(DMA_Stream_TypeDef *dma) {
13991411
DMA_MBURST_INC4 | DMA_PBURST_INC4 |
14001412
DMA_MEMORY_TO_PERIPH);
14011413
DMA2_Stream6->FCR = (DMA_SxFCR_DMDIS | DMA_SxFCR_FTH); // Configuration FIFO control register
1402-
dmaInit(dmaGetIdentifier(DMA2_Stream6), OWNER_SDCARD, 0);
14031414
dmaSetHandler(dmaGetIdentifier(DMA2_Stream6), SDMMC_DMA_ST6_IRQHandler, 1, 0);
14041415
}
1416+
return true;
14051417
}
14061418

14071419

src/main/drivers/sdio_h7xx.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -734,9 +734,10 @@ bool SD_IsDetected(void) {
734734
return status;
735735
}
736736

737-
void SD_Initialize_LL(DMA_Stream_TypeDef *dma) {
737+
bool SD_Initialize_LL(DMA_Stream_TypeDef *dma) {
738738
UNUSED(dma);
739739
// H7 uses SDMMC internal DMA (IDMA) — no external DMA stream configuration needed.
740+
return true;
740741
}
741742

742743
void SDMMC1_IRQHandler(void)

src/main/drivers/sdmmc_sdio.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ typedef struct {
216216
extern SD_CardInfo_t SD_CardInfo;
217217
extern SD_CardType_t SD_CardType;
218218

219-
void SD_Initialize_LL (DMA_Stream_TypeDef *dma);
219+
bool SD_Initialize_LL (DMA_Stream_TypeDef *dma);
220220
SD_Error_t SD_Init (void);
221221
bool SD_IsDetected (void);
222222
bool SD_GetState (void);

src/main/msc/usbd_storage_sdio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ static int8_t STORAGE_Init (uint8_t lun) {
152152
#endif
153153
UNUSED(lun);
154154
LED0_OFF;
155-
SD_Initialize_LL(SDIO_DMA);
155+
if (!SD_Initialize_LL(SDIO_DMA)) return 1;
156156
if (SD_Init() != 0) return 1;
157157
LED0_ON;
158158
return 0;

0 commit comments

Comments
 (0)