diff --git a/lib/main/STM32H7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_sdmmc.c b/lib/main/STM32H7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_sdmmc.c index 8f08dbcf9..44a4ecba4 100644 --- a/lib/main/STM32H7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_sdmmc.c +++ b/lib/main/STM32H7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_sdmmc.c @@ -446,13 +446,13 @@ HAL_StatusTypeDef SDMMC_ConfigData(SDMMC_TypeDef *SDMMCx, SDMMC_DataInitTypeDef* // DC - See errata 2.11.4 - 8 SDMMC clock cycles must elapse before DTEN can be set. // 32U below is used as a VERY rough guess that the SDMMC clock is 1/4 of the sytem clock, 8 * 4 = 32 and that the - // assembly below only takes 1 CPU cycle to run. All of which will be wrong, but right enough most of the time, especially - // when considering other processing overheads. + // loop code below only takes 2 CPU cycles to run. All of which will likely be wrong, but right enough most of the time. + // It's important that the code isn't optimized-out by the compiler or linker too, see + // https://stackoverflow.com/questions/7083482/how-to-prevent-gcc-from-optimizing-out-a-busy-wait-loop register uint32_t count = 32U; - do - { - count--; - } while(count > 0); + for (unsigned i = 0; i < count; i++) { + __asm__ volatile("" : "+g" (i) : :); + } // DC - See errata 2.11.4 /* Write to SDMMC DCTRL */ diff --git a/src/main/drivers/sdio_f4xx.c b/src/main/drivers/sdio_f4xx.c index 888d7c51c..72466b5d3 100644 --- a/src/main/drivers/sdio_f4xx.c +++ b/src/main/drivers/sdio_f4xx.c @@ -1654,7 +1654,7 @@ bool SD_GetState(void) /** -----------------------------------------------------------------------------------------------------------------*/ -SD_Error_t SD_Init(void) +static SD_Error_t SD_DoInit(void) { SD_Error_t errorState; @@ -1704,6 +1704,22 @@ SD_Error_t SD_Init(void) return errorState; } +SD_Error_t SD_Init(void) +{ + static bool sdInitAttempted = false; + static SD_Error_t result = SD_ERROR; + + if (sdInitAttempted) { + return result; + } + + sdInitAttempted = true; + + result = SD_DoInit(); + + return result; +} + /** -----------------------------------------------------------------------------------------------------------------*/ /** * @brief This function handles SD card interrupt request. diff --git a/src/main/drivers/sdio_f7xx.c b/src/main/drivers/sdio_f7xx.c index f8a0427b5..84d2a5cd1 100644 --- a/src/main/drivers/sdio_f7xx.c +++ b/src/main/drivers/sdio_f7xx.c @@ -1637,7 +1637,7 @@ bool SD_GetState(void) /** -----------------------------------------------------------------------------------------------------------------*/ -SD_Error_t SD_Init(void) +static SD_Error_t SD_DoInit(void) { SD_Error_t errorState; @@ -1683,6 +1683,23 @@ SD_Error_t SD_Init(void) return errorState; } +SD_Error_t SD_Init(void) +{ + static bool sdInitAttempted = false; + static SD_Error_t result = SD_ERROR; + + if (sdInitAttempted) { + return result; + } + + sdInitAttempted = true; + + result = SD_DoInit(); + + return result; +} + + /** -----------------------------------------------------------------------------------------------------------------*/ /** * @brief This function handles SD card interrupt request. diff --git a/src/main/drivers/sdio_h7xx.c b/src/main/drivers/sdio_h7xx.c index d069ad8b2..1511d4680 100644 --- a/src/main/drivers/sdio_h7xx.c +++ b/src/main/drivers/sdio_h7xx.c @@ -47,6 +47,9 @@ typedef struct SD_Handle_s uint32_t CID[4]; // SD card identification number table volatile uint32_t RXCplt; // SD RX Complete is equal 0 when no transfer volatile uint32_t TXCplt; // SD TX Complete is equal 0 when no transfer + + uint32_t RXErrors; + uint32_t TXErrors; } SD_Handle_t; SD_HandleTypeDef hsd1; @@ -54,7 +57,7 @@ SD_HandleTypeDef hsd1; SD_CardInfo_t SD_CardInfo; SD_CardType_t SD_CardType; -static SD_Handle_t SD_Handle; +SD_Handle_t SD_Handle; typedef struct sdioPin_s { ioTag_t pin; @@ -260,7 +263,7 @@ bool SD_GetState(void) return (cardState == HAL_SD_CARD_TRANSFER); } -SD_Error_t SD_Init(void) +static SD_Error_t SD_DoInit(void) { HAL_StatusTypeDef status; @@ -516,6 +519,22 @@ SD_Error_t SD_GetCardInfo(void) return ErrorState; } +SD_Error_t SD_Init(void) +{ + static bool sdInitAttempted = false; + static SD_Error_t result = SD_ERROR; + + if (sdInitAttempted) { + return result; + } + + sdInitAttempted = true; + + result = SD_DoInit(); + + return result; +} + SD_Error_t SD_CheckWrite(void) { if (SD_Handle.TXCplt != 0) return SD_BUSY; return SD_OK; @@ -615,6 +634,20 @@ void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd) SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr, sdReadParameters.NumberOfBlocks * sdReadParameters.BlockSize + ((uint32_t)sdReadParameters.buffer - alignedAddr)); } +void HAL_SD_ErrorCallback(SD_HandleTypeDef *hsd) +{ + UNUSED(hsd); + if (SD_Handle.RXCplt) { + SD_Handle.RXErrors++; + SD_Handle.RXCplt = 0; + } + + if (SD_Handle.TXCplt) { + SD_Handle.TXErrors++; + SD_Handle.TXCplt = 0; + } +} + void HAL_SD_AbortCallback(SD_HandleTypeDef *hsd) { UNUSED(hsd); diff --git a/src/main/msc/usbd_storage_sdio.c b/src/main/msc/usbd_storage_sdio.c index 53c1487a2..8fd371b83 100644 --- a/src/main/msc/usbd_storage_sdio.c +++ b/src/main/msc/usbd_storage_sdio.c @@ -167,13 +167,17 @@ static int8_t STORAGE_Init (uint8_t lun) LED0_OFF; #ifdef USE_DMA_SPEC - const dmaChannelSpec_t *dmaChannelSpec = dmaGetChannelSpecByPeripheral(DMA_PERIPH_SDIO, 0, sdioConfig()->dmaopt); +#if defined(STM32H7) // H7 uses IDMA + SD_Initialize_LL(0); +#else + const dmaChannelSpec_t *dmaChannelSpec = dmaGetChannelSpecByPeripheral(DMA_PERIPH_SDIO, 0, sdioConfig()->dmaopt); if (!dmaChannelSpec) { return 1; } SD_Initialize_LL((DMA_ARCH_TYPE *)dmaChannelSpec->ref); +#endif #else SD_Initialize_LL(SDCARD_SDIO_DMA_OPT); #endif @@ -181,7 +185,7 @@ static int8_t STORAGE_Init (uint8_t lun) if (!sdcard_isInserted()) { return 1; } - if (SD_Init() != 0) { + if (SD_Init() != SD_OK) { return 1; } diff --git a/src/main/startup/system_stm32h7xx.c b/src/main/startup/system_stm32h7xx.c index 9c30ff74e..367f36253 100644 --- a/src/main/startup/system_stm32h7xx.c +++ b/src/main/startup/system_stm32h7xx.c @@ -596,6 +596,11 @@ void SystemClock_Config(void) #ifdef USE_SDCARD_SDIO RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SDMMC; + +#if (HSE_VALUE != 8000000) +#error Unsupported external oscillator speed. The calculations below are based on 8Mhz resonators +// if you are seeing this, then calculate the PLL2 settings for your resonator and add support as required. +#else RCC_PeriphClkInit.PLL2.PLL2M = 5; RCC_PeriphClkInit.PLL2.PLL2N = 500; RCC_PeriphClkInit.PLL2.PLL2P = 2; // 500Mhz @@ -606,6 +611,8 @@ void SystemClock_Config(void) RCC_PeriphClkInit.PLL2.PLL2FRACN = 0; RCC_PeriphClkInit.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL2; HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit); +#endif // 8Mhz HSE_VALUE + #endif // Configure MCO clocks for clock test/verification