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 f929d481fe..f8e9464245 100755 --- 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 5fc0321608..e392b3183f 100644 --- a/src/main/drivers/sdio_f4xx.c +++ b/src/main/drivers/sdio_f4xx.c @@ -1654,7 +1654,7 @@ bool SD_GetState(void) /** -----------------------------------------------------------------------------------------------------------------*/ -bool SD_Init(void) +static bool SD_DoInit(void) { SD_Error_t ErrorState; @@ -1695,6 +1695,22 @@ bool SD_Init(void) return ErrorState; } +bool 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 5549f1f88e..09308c5a4f 100644 --- a/src/main/drivers/sdio_f7xx.c +++ b/src/main/drivers/sdio_f7xx.c @@ -1637,7 +1637,7 @@ bool SD_GetState(void) /** -----------------------------------------------------------------------------------------------------------------*/ -bool SD_Init(void) +static bool SD_DoInit(void) { SD_Error_t ErrorState; @@ -1674,6 +1674,23 @@ bool SD_Init(void) return ErrorState; } +bool 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 7c6bca2393..7400797fad 100644 --- a/src/main/drivers/sdio_h7xx.c +++ b/src/main/drivers/sdio_h7xx.c @@ -46,6 +46,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; @@ -265,7 +268,7 @@ bool SD_GetState(void) * The F4/F7 code actually returns an SD_Error_t if the card is detected * SD_OK == 0, SD_* are non-zero and indicate errors. e.g. SD_ERROR = 42 */ -bool SD_Init(void) +static bool SD_DoInit(void) { bool failureResult = SD_ERROR; // FIXME fix the calling code, this false for success is bad. bool successResult = false; @@ -524,6 +527,22 @@ SD_Error_t SD_GetCardInfo(void) return ErrorState; } +bool 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; @@ -620,6 +639,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 53c1487a21..8fd371b83e 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 035c40e9ed..93412752a8 100644 --- a/src/main/startup/system_stm32h7xx.c +++ b/src/main/startup/system_stm32h7xx.c @@ -495,6 +495,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 @@ -505,6 +510,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