diff --git a/STM32CubeMX/2021/Src/sdio.c b/STM32CubeMX/2021/Src/sdio.c index 01e3895..33fbae1 100644 --- a/STM32CubeMX/2021/Src/sdio.c +++ b/STM32CubeMX/2021/Src/sdio.c @@ -40,6 +40,8 @@ void MX_SDIO_SD_Init(void) hsd.Init.BusWide = SDIO_BUS_WIDE_1B; hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE; hsd.Init.ClockDiv = 0; + + /* if (HAL_SD_Init(&hsd) != HAL_OK) { Error_Handler(); @@ -47,8 +49,7 @@ void MX_SDIO_SD_Init(void) if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK) { Error_Handler(); - } - + }*/ } void HAL_SD_MspInit(SD_HandleTypeDef* sdHandle) diff --git a/STM32CubeMX/2021/Src/spi.c b/STM32CubeMX/2021/Src/spi.c index 2f9fbfb..aa786dd 100644 --- a/STM32CubeMX/2021/Src/spi.c +++ b/STM32CubeMX/2021/Src/spi.c @@ -37,6 +37,8 @@ void MX_SPI1_Init(void) hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH; hspi1.Init.CLKPhase = SPI_PHASE_2EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; + + // 22.5Mbaud. FPGA device allows up to 25MHz write hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; diff --git a/STM32CubeMX/2021/Src/usbd_conf.c b/STM32CubeMX/2021/Src/usbd_conf.c index 5b10126..a2c4047 100644 --- a/STM32CubeMX/2021/Src/usbd_conf.c +++ b/STM32CubeMX/2021/Src/usbd_conf.c @@ -466,9 +466,11 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) HAL_PCD_RegisterIsoOutIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOOUTIncompleteCallback); HAL_PCD_RegisterIsoInIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOINIncompleteCallback); #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */ + // Combined RX + TX fifo of 0x140 4-byte words (1280 bytes) HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x80); HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x40); - HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x80); + HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x40); + HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 2, 0x40); } if (pdev->id == DEVICE_HS) { /* Link the driver to the stack. */ @@ -506,9 +508,15 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) HAL_PCD_RegisterIsoOutIncpltCallback(&hpcd_USB_OTG_HS, PCD_ISOOUTIncompleteCallback); HAL_PCD_RegisterIsoInIncpltCallback(&hpcd_USB_OTG_HS, PCD_ISOINIncompleteCallback); #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */ + // Combined RX + TX fifo of 0x400 4-byte words (4096 bytes) HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_HS, 0x200); - HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_HS, 0, 0x80); - HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_HS, 1, 0x174); + HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_HS, 0, 0x40); + +// HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_HS, 1, 0x100); +// HOst requests 7 sectors, which is an odd number and doesn't fill the +// fifo, looks like it doesn't complete in this case !!!! + HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_HS, 1, 0x80); // 512 bytes + HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_HS, 2, 0x40); } return USBD_OK; } diff --git a/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sd.h b/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sd.h index 2e254f1..fe133b0 100644 --- a/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sd.h +++ b/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sd.h @@ -614,7 +614,8 @@ HAL_StatusTypeDef HAL_SD_ReadBlocks_IT(SD_HandleTypeDef *hsd, uint8_t *pData, ui HAL_StatusTypeDef HAL_SD_WriteBlocks_IT(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks); /* Non-Blocking mode: DMA */ HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks); -HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks); +HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint32_t BlockAdd, uint32_t NumberOfBlocks); +HAL_StatusTypeDef HAL_SD_WriteBlocks_Data(SD_HandleTypeDef *hsd, uint8_t *pData); void HAL_SD_IRQHandler(SD_HandleTypeDef *hsd); diff --git a/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_sdmmc.h b/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_sdmmc.h index c966c90..9d70910 100644 --- a/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_sdmmc.h +++ b/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_sdmmc.h @@ -1074,6 +1074,7 @@ uint32_t SDMMC_CmdReadSingleBlock(SDIO_TypeDef *SDIOx, uint32_t ReadAdd); uint32_t SDMMC_CmdReadMultiBlock(SDIO_TypeDef *SDIOx, uint32_t ReadAdd); uint32_t SDMMC_CmdWriteSingleBlock(SDIO_TypeDef *SDIOx, uint32_t WriteAdd); uint32_t SDMMC_CmdWriteMultiBlock(SDIO_TypeDef *SDIOx, uint32_t WriteAdd); +uint32_t SDMMC_CmdSetBlockCount(SDIO_TypeDef *SDIOx, uint32_t appCmdArg, uint32_t blockCount); uint32_t SDMMC_CmdEraseStartAdd(SDIO_TypeDef *SDIOx, uint32_t StartAdd); uint32_t SDMMC_CmdSDEraseStartAdd(SDIO_TypeDef *SDIOx, uint32_t StartAdd); uint32_t SDMMC_CmdEraseEndAdd(SDIO_TypeDef *SDIOx, uint32_t EndAdd); diff --git a/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c b/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c index d2a88d7..d039e87 100644 --- a/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c +++ b/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c @@ -430,6 +430,10 @@ HAL_StatusTypeDef HAL_SD_InitCard(SD_HandleTypeDef *hsd) /* Enable SDIO Clock */ __HAL_SD_ENABLE(hsd); + /* 1ms: required power up waiting time before starting the SD initialization + sequence */ + HAL_Delay(1); + /* Identify card operating voltage */ errorstate = SD_PowerON(hsd); if(errorstate != HAL_SD_ERROR_NONE) @@ -1247,22 +1251,22 @@ HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, u else { /* Enable SD DMA transfer */ - __HAL_SD_DMA_ENABLE(hsd); + // MM disabled, as this fails on fast cards. __HAL_SD_DMA_ENABLE(hsd); if(hsd->SdCard.CardType != CARD_SDHC_SDXC) { add *= 512U; - } - /* Set Block Size for Card */ - errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE); - if(errorstate != HAL_SD_ERROR_NONE) - { - /* Clear all the static flags */ - __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); - hsd->ErrorCode |= errorstate; - hsd->State = HAL_SD_STATE_READY; - return HAL_ERROR; + /* Set Block Size for Card */ + errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE); + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + return HAL_ERROR; + } } /* Configure the SD DPSM (Data Path State Machine) */ @@ -1272,6 +1276,11 @@ HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, u config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; config.DPSM = SDIO_DPSM_ENABLE; + + // We cannot enable DMA too early on UHS-I class 3 SD cards, or else the + // data is just discarded before the dpsm is started. + __HAL_SD_DMA_ENABLE(); + (void)SDIO_ConfigData(hsd->Instance, &config); /* Read Blocks in DMA mode */ @@ -1321,18 +1330,11 @@ HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, u * @param NumberOfBlocks: Number of blocks to write * @retval HAL status */ -HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks) +HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint32_t BlockAdd, uint32_t NumberOfBlocks) { - SDIO_DataInitTypeDef config; uint32_t errorstate; uint32_t add = BlockAdd; - if(NULL == pData) - { - hsd->ErrorCode |= HAL_SD_ERROR_PARAM; - return HAL_ERROR; - } - if(hsd->State == HAL_SD_STATE_READY) { hsd->ErrorCode = HAL_SD_ERROR_NONE; @@ -1343,19 +1345,33 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, return HAL_ERROR; } - hsd->State = HAL_SD_STATE_BUSY; + if(NumberOfBlocks > 1U && hsd->SdCard.CardType == CARD_SDHC_SDXC) + { + /* MM: Prepare for write */ + errorstate = SDMMC_CmdSetBlockCount(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd) << 16, NumberOfBlocks); + if(errorstate != HAL_SD_ERROR_NONE) + { + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + return HAL_ERROR; + } + } + + // hsd->State = HAL_SD_STATE_BUSY; /* Initialize data control register */ hsd->Instance->DCTRL = 0U; /* Enable SD Error interrupts */ #if defined(SDIO_STA_STBITERR) - __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_STBITERR)); + __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND | SDIO_IT_STBITERR)); #else /* SDIO_STA_STBITERR not defined */ - __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR)); + __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND)); #endif /* SDIO_STA_STBITERR */ /* Set the DMA transfer complete callback */ + // This callback now doesn't do anything - enabling DATAEND interrupt is set above to avoid race conditions hsd->hdmatx->XferCpltCallback = SD_DMATransmitCplt; /* Set the DMA error callback */ @@ -1367,17 +1383,17 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, if(hsd->SdCard.CardType != CARD_SDHC_SDXC) { add *= 512U; - } - /* Set Block Size for Card */ - errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE); - if(errorstate != HAL_SD_ERROR_NONE) - { - /* Clear all the static flags */ - __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); - hsd->ErrorCode |= errorstate; - hsd->State = HAL_SD_STATE_READY; - return HAL_ERROR; + /* Set Block Size for Card */ + errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE); + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + return HAL_ERROR; + } } /* Write Blocks in Polling mode */ @@ -1405,11 +1421,59 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, return HAL_ERROR; } - /* Enable SDIO DMA transfer */ - __HAL_SD_DMA_ENABLE(hsd); + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Writes block(s) to a specified address in a card. The Data transfer + * is managed by DMA mode. + * @note This API should be followed by a check on the card state through + * HAL_SD_GetCardState(). + * @note You could also check the DMA transfer process through the SD Tx + * interrupt event. + * @param hsd: Pointer to SD handle + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param BlockAdd: Block Address where data will be written + * @param NumberOfBlocks: Number of blocks to write + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_WriteBlocks_Data(SD_HandleTypeDef *hsd, uint8_t *pData) +{ + SDIO_DataInitTypeDef config; + + if(hsd->State == HAL_SD_STATE_READY) + { + hsd->ErrorCode = HAL_SD_ERROR_NONE; + + hsd->State = HAL_SD_STATE_BUSY; + + /* Initialize data control register */ + hsd->Instance->DCTRL = 0U; + + /* Enable SD Error interrupts */ +#if defined(SDIO_STA_STBITERR) + __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND | SDIO_IT_STBITERR)); +#else /* SDIO_STA_STBITERR not defined */ + __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND)); +#endif /* SDIO_STA_STBITERR */ + + /* Set the DMA transfer complete callback */ + // This callback now doesn't do anything - enabling DATAEND interrupt is set above to avoid race conditions + hsd->hdmatx->XferCpltCallback = SD_DMATransmitCplt; + + /* Set the DMA error callback */ + hsd->hdmatx->XferErrorCallback = SD_DMAError; + + /* Set the DMA Abort callback */ + hsd->hdmatx->XferAbortCallback = NULL; /* Enable the DMA Channel */ - if(HAL_DMA_Start_IT(hsd->hdmatx, (uint32_t)pData, (uint32_t)&hsd->Instance->FIFO, (uint32_t)(BLOCKSIZE * NumberOfBlocks)/4U) != HAL_OK) + if(HAL_DMA_Start_IT(hsd->hdmatx, (uint32_t)pData, (uint32_t)&hsd->Instance->FIFO, (uint32_t)(BLOCKSIZE)/4U) != HAL_OK) { #if defined(SDIO_STA_STBITERR) __HAL_SD_DISABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_STBITERR)); @@ -1426,11 +1490,16 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, { /* Configure the SD DPSM (Data Path State Machine) */ config.DataTimeOut = SDMMC_DATATIMEOUT; - config.DataLength = BLOCKSIZE * NumberOfBlocks; + config.DataLength = BLOCKSIZE; config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD; config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; config.DPSM = SDIO_DPSM_ENABLE; + + // We cannot enable DMA too early on UHS-I class 3 SD cards, or else the + // data is just discarded before the dpsm is started. + __HAL_SD_DMA_ENABLE(); + (void)SDIO_ConfigData(hsd->Instance, &config); return HAL_OK; @@ -1622,16 +1691,8 @@ void HAL_SD_IRQHandler(SD_HandleTypeDef *hsd) { if((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U) { - errorstate = SDMMC_CmdStopTransfer(hsd->Instance); - if(errorstate != HAL_SD_ERROR_NONE) - { - hsd->ErrorCode |= errorstate; -#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) - hsd->ErrorCallback(hsd); -#else - HAL_SD_ErrorCallback(hsd); -#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ - } + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS); + __HAL_SD_DMA_DISABLE(hsd); } if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) == 0U) && ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) == 0U)) { @@ -2407,7 +2468,7 @@ HAL_StatusTypeDef HAL_SD_Abort(SD_HandleTypeDef *hsd) hsd->Context = SD_CONTEXT_NONE; CardState = HAL_SD_GetCardState(hsd); - if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING)) + if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING) || (CardState == HAL_SD_CARD_PROGRAMMING)) { hsd->ErrorCode = SDMMC_CmdStopTransfer(hsd->Instance); } @@ -2513,10 +2574,12 @@ HAL_StatusTypeDef HAL_SD_Abort_IT(SD_HandleTypeDef *hsd) */ static void SD_DMATransmitCplt(DMA_HandleTypeDef *hdma) { - SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent); + // SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent); /* Enable DATAEND Interrupt */ - __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DATAEND)); + //WHAT IF IT ALREADY TRIGGERED ? Maybe it can't due to interrupt priorities ? + // Easier to just ignore it. + // __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DATAEND)); } /** diff --git a/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c b/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c index 4f23a45..614b6dc 100644 --- a/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c +++ b/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c @@ -606,6 +606,31 @@ uint32_t SDMMC_CmdWriteSingleBlock(SDIO_TypeDef *SDIOx, uint32_t WriteAdd) return errorstate; } +/** + * @brief Set the count of a multi-block write command + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdSetBlockCount(SDIO_TypeDef *SDIOx, uint32_t appCmdArg, uint32_t blockCount) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + errorstate = SDMMC_CmdAppCommand(SDIOx, appCmdArg); + if(errorstate == HAL_SD_ERROR_NONE) + { + sdmmc_cmdinit.Argument = blockCount; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SET_BLOCK_COUNT; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SET_BLOCK_COUNT, SDIO_CMDTIMEOUT); + } + + return errorstate; +} + /** * @brief Send the Write Multi Block command and check the response * @param SDIOx: Pointer to SDIO register base diff --git a/STM32CubeMX/2021/Src/fmc.c b/STM32CubeMX/2021/Src/fmc.c index dae179a..a527167 100644 --- a/STM32CubeMX/2021/Src/fmc.c +++ b/STM32CubeMX/2021/Src/fmc.c @@ -49,15 +49,33 @@ void MX_FMC_Init(void) hsram1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE; hsram1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE; hsram1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY; - hsram1.Init.WriteFifo = FMC_WRITE_FIFO_ENABLE; + hsram1.Init.WriteFifo = FMC_WRITE_FIFO_DISABLE; + hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE; /* Timing */ - Timing.AddressSetupTime = 2; - Timing.AddressHoldTime = 1; - Timing.DataSetupTime = 4; - Timing.BusTurnAroundDuration = 1; - Timing.CLKDivision = 16; - Timing.DataLatency = 17; + + // 1 clock to read the address, + 2 for synchroniser skew + Timing.AddressSetupTime = 6; + Timing.AddressHoldTime = 2; + + // Writes to device: + // 2 for synchroniser skew (dbx also delayed) + // 1 to skip hold time + // 1 to write data. + + // Reads from device: + // 1 to skip hold time + // 2 for synchroniser skew on OE + // 1 to write back to fsmc bus. + Timing.DataSetupTime = 8; + + // Allow a clock for us to release signals + // Need to avoid both devices acting as outputs + // on the multiplexed lines at the same time. + Timing.BusTurnAroundDuration = 2; + + Timing.CLKDivision = 16; // Ignored for async + Timing.DataLatency = 17; // Ignored for async Timing.AccessMode = FMC_ACCESS_MODE_A; /* ExtTiming */ @@ -107,6 +125,10 @@ static void HAL_FMC_MspInit(void){ PE0 ------> FMC_NBL0 PE1 ------> FMC_NBL1 */ + + // MM: GPIO_SPEED_FREQ_MEDIUM is rated up to 50MHz, which is fine as all the + // fsmc timings are > 1 (ie. so clock speed / 2 is around 50MHz). + /* GPIO_InitStruct */ GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14