STM32H7 - SDMMC Fix the short busy loop being compiled out by newer
versions of GCC. STM32H7 - Don't go into an infinite loop if an SDIO read fails. STM32H7 - Generate compiliation error for non-8Mhz crystals when SDCARD via SDIO is used. Prevents accidental overclocking of hardware. Avoid double-init of SD card when CONFIG_IN_SDCARD is used. Note: There's no SD_DeInit() function. STM32H7 - Fix MSC SD initialisation when using USE_DMA_SPEC.
This commit is contained in:
parent
c9d7267cf9
commit
91483d2e8e
|
@ -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.
|
// 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
|
// 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
|
// loop code below only takes 2 CPU cycles to run. All of which will likely be wrong, but right enough most of the time.
|
||||||
// when considering other processing overheads.
|
// 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;
|
register uint32_t count = 32U;
|
||||||
do
|
for (unsigned i = 0; i < count; i++) {
|
||||||
{
|
__asm__ volatile("" : "+g" (i) : :);
|
||||||
count--;
|
}
|
||||||
} while(count > 0);
|
|
||||||
// DC - See errata 2.11.4
|
// DC - See errata 2.11.4
|
||||||
|
|
||||||
/* Write to SDMMC DCTRL */
|
/* Write to SDMMC DCTRL */
|
||||||
|
|
|
@ -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;
|
SD_Error_t errorState;
|
||||||
|
|
||||||
|
@ -1704,6 +1704,22 @@ SD_Error_t SD_Init(void)
|
||||||
return errorState;
|
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.
|
* @brief This function handles SD card interrupt request.
|
||||||
|
|
|
@ -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;
|
SD_Error_t errorState;
|
||||||
|
|
||||||
|
@ -1683,6 +1683,23 @@ SD_Error_t SD_Init(void)
|
||||||
return errorState;
|
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.
|
* @brief This function handles SD card interrupt request.
|
||||||
|
|
|
@ -47,6 +47,9 @@ typedef struct SD_Handle_s
|
||||||
uint32_t CID[4]; // SD card identification number table
|
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 RXCplt; // SD RX Complete is equal 0 when no transfer
|
||||||
volatile uint32_t TXCplt; // SD TX 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_Handle_t;
|
||||||
|
|
||||||
SD_HandleTypeDef hsd1;
|
SD_HandleTypeDef hsd1;
|
||||||
|
@ -54,7 +57,7 @@ SD_HandleTypeDef hsd1;
|
||||||
SD_CardInfo_t SD_CardInfo;
|
SD_CardInfo_t SD_CardInfo;
|
||||||
SD_CardType_t SD_CardType;
|
SD_CardType_t SD_CardType;
|
||||||
|
|
||||||
static SD_Handle_t SD_Handle;
|
SD_Handle_t SD_Handle;
|
||||||
|
|
||||||
typedef struct sdioPin_s {
|
typedef struct sdioPin_s {
|
||||||
ioTag_t pin;
|
ioTag_t pin;
|
||||||
|
@ -260,7 +263,7 @@ bool SD_GetState(void)
|
||||||
return (cardState == HAL_SD_CARD_TRANSFER);
|
return (cardState == HAL_SD_CARD_TRANSFER);
|
||||||
}
|
}
|
||||||
|
|
||||||
SD_Error_t SD_Init(void)
|
static SD_Error_t SD_DoInit(void)
|
||||||
{
|
{
|
||||||
HAL_StatusTypeDef status;
|
HAL_StatusTypeDef status;
|
||||||
|
|
||||||
|
@ -516,6 +519,22 @@ SD_Error_t SD_GetCardInfo(void)
|
||||||
return ErrorState;
|
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) {
|
SD_Error_t SD_CheckWrite(void) {
|
||||||
if (SD_Handle.TXCplt != 0) return SD_BUSY;
|
if (SD_Handle.TXCplt != 0) return SD_BUSY;
|
||||||
return SD_OK;
|
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));
|
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)
|
void HAL_SD_AbortCallback(SD_HandleTypeDef *hsd)
|
||||||
{
|
{
|
||||||
UNUSED(hsd);
|
UNUSED(hsd);
|
||||||
|
|
|
@ -167,6 +167,9 @@ static int8_t STORAGE_Init (uint8_t lun)
|
||||||
LED0_OFF;
|
LED0_OFF;
|
||||||
|
|
||||||
#ifdef USE_DMA_SPEC
|
#ifdef USE_DMA_SPEC
|
||||||
|
#if defined(STM32H7) // H7 uses IDMA
|
||||||
|
SD_Initialize_LL(0);
|
||||||
|
#else
|
||||||
const dmaChannelSpec_t *dmaChannelSpec = dmaGetChannelSpecByPeripheral(DMA_PERIPH_SDIO, 0, sdioConfig()->dmaopt);
|
const dmaChannelSpec_t *dmaChannelSpec = dmaGetChannelSpecByPeripheral(DMA_PERIPH_SDIO, 0, sdioConfig()->dmaopt);
|
||||||
|
|
||||||
if (!dmaChannelSpec) {
|
if (!dmaChannelSpec) {
|
||||||
|
@ -174,6 +177,7 @@ static int8_t STORAGE_Init (uint8_t lun)
|
||||||
}
|
}
|
||||||
|
|
||||||
SD_Initialize_LL((DMA_ARCH_TYPE *)dmaChannelSpec->ref);
|
SD_Initialize_LL((DMA_ARCH_TYPE *)dmaChannelSpec->ref);
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
SD_Initialize_LL(SDCARD_SDIO_DMA_OPT);
|
SD_Initialize_LL(SDCARD_SDIO_DMA_OPT);
|
||||||
#endif
|
#endif
|
||||||
|
@ -181,7 +185,7 @@ static int8_t STORAGE_Init (uint8_t lun)
|
||||||
if (!sdcard_isInserted()) {
|
if (!sdcard_isInserted()) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (SD_Init() != 0) {
|
if (SD_Init() != SD_OK) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -596,6 +596,11 @@ void SystemClock_Config(void)
|
||||||
|
|
||||||
#ifdef USE_SDCARD_SDIO
|
#ifdef USE_SDCARD_SDIO
|
||||||
RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SDMMC;
|
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.PLL2M = 5;
|
||||||
RCC_PeriphClkInit.PLL2.PLL2N = 500;
|
RCC_PeriphClkInit.PLL2.PLL2N = 500;
|
||||||
RCC_PeriphClkInit.PLL2.PLL2P = 2; // 500Mhz
|
RCC_PeriphClkInit.PLL2.PLL2P = 2; // 500Mhz
|
||||||
|
@ -606,6 +611,8 @@ void SystemClock_Config(void)
|
||||||
RCC_PeriphClkInit.PLL2.PLL2FRACN = 0;
|
RCC_PeriphClkInit.PLL2.PLL2FRACN = 0;
|
||||||
RCC_PeriphClkInit.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL2;
|
RCC_PeriphClkInit.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL2;
|
||||||
HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
|
HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
|
||||||
|
#endif // 8Mhz HSE_VALUE
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Configure MCO clocks for clock test/verification
|
// Configure MCO clocks for clock test/verification
|
||||||
|
|
Loading…
Reference in New Issue