From e4ab5d2a49cab8c83479e2b2217b22d0ecaed503 Mon Sep 17 00:00:00 2001 From: Michael McMaster Date: Tue, 4 May 2021 16:06:42 +1000 Subject: [PATCH] Fix scsi write issues --- STM32CubeMX/2020c.diff | 252 ++++++++++++++---- .../Inc/stm32f2xx_hal_sd.h | 3 +- .../Src/stm32f2xx_hal_sd.c | 91 ++++--- .../Src/stm32f2xx_ll_sdmmc.c | 1 + STM32CubeMX/2021.diff | 201 ++++++++++++-- .../Inc/stm32f4xx_hal_sd.h | 3 +- .../Src/stm32f4xx_hal_sd.c | 94 ++++--- STM32CubeMX/revF.diff | 252 ++++++++++++++---- .../Inc/stm32f2xx_hal_sd.h | 3 +- .../Src/stm32f2xx_hal_sd.c | 91 ++++--- .../Src/stm32f2xx_ll_sdmmc.c | 1 + src/firmware/bsp_driver_sd.c | 23 +- src/firmware/config.c | 2 +- src/firmware/disk.c | 195 ++++++-------- 14 files changed, 845 insertions(+), 367 deletions(-) diff --git a/STM32CubeMX/2020c.diff b/STM32CubeMX/2020c.diff index 8e6da4cd..7e740bae 100644 --- a/STM32CubeMX/2020c.diff +++ b/STM32CubeMX/2020c.diff @@ -116,11 +116,25 @@ index eee1fd8..9567a95 100644 } return USBD_OK; } +diff --git a/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_sd.h b/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_sd.h +index a4317e4..7165538 100644 +--- a/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_sd.h ++++ b/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_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/2020c/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_ll_sdmmc.h b/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_ll_sdmmc.h -index c966c906..9d709100 100644 +index 181b4b7..d71c37b 100644 --- a/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_ll_sdmmc.h +++ b/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_ll_sdmmc.h -@@ -1074,6 +1074,7 @@ uint32_t SDMMC_CmdReadSingleBlock(SDIO_TypeDef *SDIOx, uint32_t ReadAdd); +@@ -1064,6 +1064,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); @@ -128,44 +142,8 @@ index c966c906..9d709100 100644 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/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c b/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c -index 4f23a455..614b6dce 100644 ---- a/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c -+++ b/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_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/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c b/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c -index d2a88d75..1a09028f 100644 +index 569c8b1..b10dd0e 100644 --- a/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c +++ b/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c @@ -430,6 +430,10 @@ HAL_StatusTypeDef HAL_SD_InitCard(SD_HandleTypeDef *hsd) @@ -179,7 +157,7 @@ index d2a88d75..1a09028f 100644 /* 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 +@@ -1227,22 +1231,21 @@ HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, u else { /* Enable SD DMA transfer */ @@ -190,7 +168,7 @@ index d2a88d75..1a09028f 100644 { add *= 512U; - } - +- - /* Set Block Size for Card */ - errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE); - if(errorstate != HAL_SD_ERROR_NONE) @@ -213,7 +191,7 @@ index d2a88d75..1a09028f 100644 } /* 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 +@@ -1252,6 +1255,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; @@ -225,10 +203,31 @@ index d2a88d75..1a09028f 100644 (void)SDIO_ConfigData(hsd->Instance, &config); /* Read Blocks in DMA mode */ -@@ -1343,6 +1352,19 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, +@@ -1301,18 +1309,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; +@@ -1323,15 +1324,29 @@ 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 */ @@ -242,15 +241,26 @@ index d2a88d75..1a09028f 100644 + } + } + - hsd->State = HAL_SD_STATE_BUSY; ++ // hsd->State = HAL_SD_STATE_BUSY; /* Initialize data control register */ -@@ -1367,17 +1389,17 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, + hsd->Instance->DCTRL = 0U; + + /* Enable SD Error interrupts */ +- __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)); + + /* 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 */ +@@ -1343,17 +1358,16 @@ 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) @@ -273,16 +283,72 @@ index d2a88d75..1a09028f 100644 } /* Write Blocks in Polling mode */ -@@ -1406,7 +1428,7 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, +@@ -1381,11 +1395,55 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, + return HAL_ERROR; } - /* Enable SDIO DMA transfer */ +- /* Enable SDIO DMA transfer */ - __HAL_SD_DMA_ENABLE(hsd); -+ // MM disabled, as this fails on fast cards. __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 */ ++ __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND)); ++ ++ /* 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) -@@ -1431,6 +1453,11 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, +- 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) + { + __HAL_SD_DISABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR)); + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); +@@ -1398,11 +1456,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; @@ -294,14 +360,84 @@ index d2a88d75..1a09028f 100644 (void)SDIO_ConfigData(hsd->Instance, &config); return HAL_OK; -@@ -1632,6 +1659,10 @@ void HAL_SD_IRQHandler(SD_HandleTypeDef *hsd) - HAL_SD_ErrorCallback(hsd); - #endif /* USE_HAL_SD_REGISTER_CALLBACKS */ - } +@@ -1588,16 +1651,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); -+ -+ hsd->State = HAL_SD_STATE_READY; -+ hsd->Context = SD_CONTEXT_NONE; ++ __HAL_SD_DMA_DISABLE(hsd); } if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) == 0U) && ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) == 0U)) { +@@ -2354,7 +2409,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); + } +@@ -2460,10 +2515,13 @@ 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)); ++ // __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/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c b/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c +index b060eae..de39f9d 100644 +--- a/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c ++++ b/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c +@@ -606,6 +606,32 @@ 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/2020c/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_sd.h b/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_sd.h index a4317e48..7165538a 100644 --- a/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_sd.h +++ b/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_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/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c b/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c index db67bf13..b10dd0e6 100644 --- a/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c +++ b/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c @@ -1236,7 +1236,6 @@ HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, u 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) @@ -1310,18 +1309,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; @@ -1345,15 +1337,16 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, } } - hsd->State = HAL_SD_STATE_BUSY; + // hsd->State = HAL_SD_STATE_BUSY; /* Initialize data control register */ hsd->Instance->DCTRL = 0U; /* Enable SD Error interrupts */ - __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)); /* 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 */ @@ -1365,7 +1358,6 @@ 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) @@ -1403,11 +1395,55 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, return HAL_ERROR; } - /* Enable SDIO DMA transfer */ - // MM disabled, as this fails on fast cards. __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 */ + __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND)); + + /* 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) { __HAL_SD_DISABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR)); __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); @@ -1420,7 +1456,7 @@ 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; @@ -1615,20 +1651,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); - - hsd->State = HAL_SD_STATE_READY; - hsd->Context = SD_CONTEXT_NONE; + __HAL_SD_DMA_DISABLE(hsd); } if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) == 0U) && ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) == 0U)) { @@ -2385,7 +2409,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); } @@ -2491,10 +2515,13 @@ 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)); + // __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/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c b/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c index ee78e9e0..de39f9d2 100644 --- a/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c +++ b/STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c @@ -631,6 +631,7 @@ uint32_t SDMMC_CmdSetBlockCount(SDIO_TypeDef *SDIOx, uint32_t appCmdArg, uint32_ 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.diff b/STM32CubeMX/2021.diff index 5d68fce7..53f7cbf0 100644 --- a/STM32CubeMX/2021.diff +++ b/STM32CubeMX/2021.diff @@ -115,8 +115,34 @@ index 5b10126..a2c4047 100644 } 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 d2a88d75..1a09028f 100644 +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) @@ -176,10 +202,31 @@ index d2a88d75..1a09028f 100644 (void)SDIO_ConfigData(hsd->Instance, &config); /* Read Blocks in DMA mode */ -@@ -1343,6 +1352,19 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, +@@ -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 */ @@ -193,10 +240,26 @@ index d2a88d75..1a09028f 100644 + } + } + - hsd->State = HAL_SD_STATE_BUSY; ++ // hsd->State = HAL_SD_STATE_BUSY; /* Initialize data control register */ -@@ -1367,17 +1389,17 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, + 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; @@ -224,16 +287,76 @@ index d2a88d75..1a09028f 100644 } /* Write Blocks in Polling mode */ -@@ -1406,7 +1428,7 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, +@@ -1405,11 +1421,59 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, + return HAL_ERROR; } - /* Enable SDIO DMA transfer */ +- /* Enable SDIO DMA transfer */ - __HAL_SD_DMA_ENABLE(hsd); -+ // MM disabled, as this fails on fast cards. __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) -@@ -1431,6 +1453,11 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, +- 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; @@ -245,31 +368,51 @@ index d2a88d75..1a09028f 100644 (void)SDIO_ConfigData(hsd->Instance, &config); return HAL_OK; -@@ -1632,6 +1659,10 @@ void HAL_SD_IRQHandler(SD_HandleTypeDef *hsd) - HAL_SD_ErrorCallback(hsd); - #endif /* USE_HAL_SD_REGISTER_CALLBACKS */ - } +@@ -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); -+ -+ hsd->State = HAL_SD_STATE_READY; -+ hsd->Context = SD_CONTEXT_NONE; ++ __HAL_SD_DMA_DISABLE(hsd); } if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) == 0U) && ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) == 0U)) { -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 c966c906..9d709100 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); +@@ -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 4f23a455..614b6dce 100644 +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) 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 2e254f19..fe133b05 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/Src/stm32f4xx_hal_sd.c b/STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c index 1a09028f..d039e87b 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 @@ -1330,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; @@ -1365,19 +1358,20 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, } } - hsd->State = HAL_SD_STATE_BUSY; + // 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 */ @@ -1427,11 +1421,59 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, return HAL_ERROR; } - /* Enable SDIO DMA transfer */ - // MM disabled, as this fails on fast cards. __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)); @@ -1448,7 +1490,7 @@ 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; @@ -1649,20 +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); - - hsd->State = HAL_SD_STATE_READY; - hsd->Context = SD_CONTEXT_NONE; + __HAL_SD_DMA_DISABLE(hsd); } if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) == 0U) && ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) == 0U)) { @@ -2438,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); } @@ -2544,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/revF.diff b/STM32CubeMX/revF.diff index 330f6453..8f93079c 100644 --- a/STM32CubeMX/revF.diff +++ b/STM32CubeMX/revF.diff @@ -98,11 +98,25 @@ index 03a1b12..1b01446 100644 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 +diff --git a/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_sd.h b/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_sd.h +index a4317e4..7165538 100644 +--- a/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_sd.h ++++ b/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_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/revF/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_ll_sdmmc.h b/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_ll_sdmmc.h -index c966c906..9d709100 100644 +index 181b4b7..d71c37b 100644 --- a/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_ll_sdmmc.h +++ b/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_ll_sdmmc.h -@@ -1074,6 +1074,7 @@ uint32_t SDMMC_CmdReadSingleBlock(SDIO_TypeDef *SDIOx, uint32_t ReadAdd); +@@ -1064,6 +1064,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); @@ -110,44 +124,8 @@ index c966c906..9d709100 100644 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/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c b/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c -index 4f23a455..614b6dce 100644 ---- a/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c -+++ b/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_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/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c b/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c -index d2a88d75..1a09028f 100644 +index 569c8b1..b10dd0e 100644 --- a/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c +++ b/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c @@ -430,6 +430,10 @@ HAL_StatusTypeDef HAL_SD_InitCard(SD_HandleTypeDef *hsd) @@ -161,7 +139,7 @@ index d2a88d75..1a09028f 100644 /* 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 +@@ -1227,22 +1231,21 @@ HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, u else { /* Enable SD DMA transfer */ @@ -172,7 +150,7 @@ index d2a88d75..1a09028f 100644 { add *= 512U; - } - +- - /* Set Block Size for Card */ - errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE); - if(errorstate != HAL_SD_ERROR_NONE) @@ -195,7 +173,7 @@ index d2a88d75..1a09028f 100644 } /* 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 +@@ -1252,6 +1255,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; @@ -207,10 +185,31 @@ index d2a88d75..1a09028f 100644 (void)SDIO_ConfigData(hsd->Instance, &config); /* Read Blocks in DMA mode */ -@@ -1343,6 +1352,19 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, +@@ -1301,18 +1309,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; +@@ -1323,15 +1324,29 @@ 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 */ @@ -224,15 +223,26 @@ index d2a88d75..1a09028f 100644 + } + } + - hsd->State = HAL_SD_STATE_BUSY; ++ // hsd->State = HAL_SD_STATE_BUSY; /* Initialize data control register */ -@@ -1367,17 +1389,17 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, + hsd->Instance->DCTRL = 0U; + + /* Enable SD Error interrupts */ +- __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)); + + /* 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 */ +@@ -1343,17 +1358,16 @@ 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) @@ -255,16 +265,72 @@ index d2a88d75..1a09028f 100644 } /* Write Blocks in Polling mode */ -@@ -1406,7 +1428,7 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, +@@ -1381,11 +1395,55 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, + return HAL_ERROR; } - /* Enable SDIO DMA transfer */ +- /* Enable SDIO DMA transfer */ - __HAL_SD_DMA_ENABLE(hsd); -+ // MM disabled, as this fails on fast cards. __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 */ ++ __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND)); ++ ++ /* 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) -@@ -1431,6 +1453,11 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, +- 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) + { + __HAL_SD_DISABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR)); + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); +@@ -1398,11 +1456,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; @@ -276,14 +342,84 @@ index d2a88d75..1a09028f 100644 (void)SDIO_ConfigData(hsd->Instance, &config); return HAL_OK; -@@ -1632,6 +1659,10 @@ void HAL_SD_IRQHandler(SD_HandleTypeDef *hsd) - HAL_SD_ErrorCallback(hsd); - #endif /* USE_HAL_SD_REGISTER_CALLBACKS */ - } +@@ -1588,16 +1651,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); -+ -+ hsd->State = HAL_SD_STATE_READY; -+ hsd->Context = SD_CONTEXT_NONE; ++ __HAL_SD_DMA_DISABLE(hsd); } if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) == 0U) && ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) == 0U)) { +@@ -2354,7 +2409,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); + } +@@ -2460,10 +2515,13 @@ 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)); ++ // __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/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c b/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c +index b060eae..de39f9d 100644 +--- a/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c ++++ b/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c +@@ -606,6 +606,32 @@ 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/revF/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_sd.h b/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_sd.h index a4317e48..7165538a 100644 --- a/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_sd.h +++ b/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_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/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c b/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c index db67bf13..b10dd0e6 100644 --- a/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c +++ b/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c @@ -1236,7 +1236,6 @@ HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, u 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) @@ -1310,18 +1309,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; @@ -1345,15 +1337,16 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, } } - hsd->State = HAL_SD_STATE_BUSY; + // hsd->State = HAL_SD_STATE_BUSY; /* Initialize data control register */ hsd->Instance->DCTRL = 0U; /* Enable SD Error interrupts */ - __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)); /* 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 */ @@ -1365,7 +1358,6 @@ 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) @@ -1403,11 +1395,55 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, return HAL_ERROR; } - /* Enable SDIO DMA transfer */ - // MM disabled, as this fails on fast cards. __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 */ + __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND)); + + /* 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) { __HAL_SD_DISABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR)); __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); @@ -1420,7 +1456,7 @@ 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; @@ -1615,20 +1651,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); - - hsd->State = HAL_SD_STATE_READY; - hsd->Context = SD_CONTEXT_NONE; + __HAL_SD_DMA_DISABLE(hsd); } if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) == 0U) && ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) == 0U)) { @@ -2385,7 +2409,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); } @@ -2491,10 +2515,13 @@ 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)); + // __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/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c b/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c index ee78e9e0..de39f9d2 100644 --- a/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c +++ b/STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c @@ -631,6 +631,7 @@ uint32_t SDMMC_CmdSetBlockCount(SDIO_TypeDef *SDIOx, uint32_t appCmdArg, uint32_ return errorstate; } + /** * @brief Send the Write Multi Block command and check the response * @param SDIOx: Pointer to SDIO register base diff --git a/src/firmware/bsp_driver_sd.c b/src/firmware/bsp_driver_sd.c index 5c561bfe..dda58d9d 100755 --- a/src/firmware/bsp_driver_sd.c +++ b/src/firmware/bsp_driver_sd.c @@ -265,7 +265,7 @@ uint8_t BSP_SD_WriteBlocks_DMA(uint8_t *pData, uint64_t BlockAddr, uint32_t NumO uint8_t SD_state = MSD_OK; /* Write block(s) in DMA transfer mode */ - if(HAL_SD_WriteBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks) != HAL_OK) + if(HAL_SD_WriteBlocks_DMA(&hsd, BlockAddr, NumOfBlocks) != HAL_OK) { SD_state = MSD_ERROR; } @@ -273,7 +273,25 @@ uint8_t BSP_SD_WriteBlocks_DMA(uint8_t *pData, uint64_t BlockAddr, uint32_t NumO /* Wait until transfer is complete */ if(SD_state == MSD_OK) { - while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {} + for (int i = 0; i < NumOfBlocks; ++i) + { + while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {} + + HAL_SD_CardStateTypeDef cardState = HAL_SD_GetCardState(&hsd); + while (cardState == HAL_SD_CARD_PROGRAMMING) + { + // Wait while the SD card is writing buffer to flash + // The card may remain in the RECEIVING state (even though it's programming) if + // it has buffer space to receive more data available. + + cardState = HAL_SD_GetCardState(&hsd); + } + + HAL_SD_WriteBlocks_Data(&hsd, pData + (i * 512)); + } + + while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {} // Wait for DMA to complete + SDMMC_CmdStopTransfer(hsd.Instance); if(HAL_SD_GetState(&hsd) == HAL_SD_STATE_ERROR) { @@ -293,7 +311,6 @@ uint8_t BSP_SD_WriteBlocks_DMA(uint8_t *pData, uint64_t BlockAddr, uint32_t NumO cardState = HAL_SD_GetCardState(&hsd); } - } return SD_state; diff --git a/src/firmware/config.c b/src/firmware/config.c index 5f25635a..ea9a9f56 100755 --- a/src/firmware/config.c +++ b/src/firmware/config.c @@ -36,7 +36,7 @@ #include -static const uint16_t FIRMWARE_VERSION = 0x0642; +static const uint16_t FIRMWARE_VERSION = 0x0643; // Optional static config extern uint8_t* __fixed_config; diff --git a/src/firmware/disk.c b/src/firmware/disk.c index b853fea5..66683650 100755 --- a/src/firmware/disk.c +++ b/src/firmware/disk.c @@ -553,31 +553,6 @@ int scsiDiskCommand() return commandHandled; } -static uint32_t -calcReadahead(uint32_t totalBytes, uint32_t sdSpeedKBs, uint32_t scsiSpeedKBs) -{ - if (!(scsiDev.boardCfg.flags6 & S2S_CFG_ENABLE_BLIND_WRITES) || - (scsiSpeedKBs == 0) || - (scsiDev.hostSpeedMeasured == 0)) - { - return totalBytes; - } - - // uint32_t readAheadBytes = totalBytes * (1 - scsiSpeedKBs / sdSpeedKBs); - // Won't overflow with 65536 max bytes, 20000 max scsi speed. - uint32_t readAheadBytes = totalBytes - totalBytes * scsiSpeedKBs / sdSpeedKBs; - - // Round up to nearest FIFO size (* 4 for safety) - readAheadBytes = ((readAheadBytes / SCSI_FIFO_DEPTH) + 4) * SCSI_FIFO_DEPTH; - - if (readAheadBytes > totalBytes) - { - readAheadBytes = totalBytes; - } - - return readAheadBytes; -} - void scsiDiskPoll() { uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector; @@ -740,6 +715,7 @@ void scsiDiskPoll() transfer.lba); int i = 0; int clearBSY = 0; + int disconnected = 0; int parityError = 0; int enableParity = scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY; @@ -767,97 +743,85 @@ void scsiDiskPoll() // KEEP GOING to ensure FIFOs are in a good state. // likely(!parityError || !enableParity)) { - uint32_t rem = totalSDSectors - i; - uint32_t sectors = rem < maxSectors ? rem : maxSectors; - if (bytesPerSector == SD_SECTOR_SIZE) { - // We assume the SD card is faster than the SCSI interface, but has - // no flow control. This can be handled if a) the scsi interface - // doesn't block and b) we read enough SCSI sectors first so that - // the SD interface cannot catch up. - uint32_t totalBytes = sectors * SD_SECTOR_SIZE; + uint32_t maxXferSectors = SCSI_XFER_MAX / SD_SECTOR_SIZE; + uint32_t rem = totalSDSectors - i; + uint32_t sectors = rem < maxXferSectors ? rem : maxXferSectors; - uint32_t sdSpeedKBs = s2s_getSdRateKBs() + (scsiDev.sdUnderrunCount * 256); - uint32_t readAheadBytes = calcReadahead( - totalBytes, - sdSpeedKBs, - scsiDev.hostSpeedKBs); + uint32_t totalBytes = sectors * SD_SECTOR_SIZE; if (useSlowDataCount) { - DWT->CYCCNT = 0; // Start counting cycles scsiSetDataCount(totalBytes); } - uint32_t scsiBytesRead = 0; - if (readAheadBytes > 0) - { - scsiReadPIO( - &scsiDev.data[scsiBytesRead], - readAheadBytes, - &parityError); - scsiBytesRead += readAheadBytes; - - if (i == 0 && !useSlowDataCount) - { - uint32_t elapsedCycles = DWT->CYCCNT; - - // uint32_t rateKBs = (readAheadBytes / 1000) / (elapsedCycles / HAL_RCC_GetHCLKFreq()); - // Scaled by 4 to avoid overflow w/ max 65536 at 108MHz. - uint32_t rateKBs = ((readAheadBytes / 4) * (HAL_RCC_GetHCLKFreq() / 1000) / elapsedCycles) * 4; - - scsiDev.hostSpeedKBs = (scsiDev.hostSpeedKBs + rateKBs) / 2; - scsiDev.hostSpeedMeasured = 1; - - if (rateKBs < scsiDev.hostSpeedKBs) - { - // Our readahead was too slow; assume remaining bytes - // will be as well. - if (readAheadBytes < totalBytes) - { - uint32_t properReadahead = calcReadahead( - totalBytes, - sdSpeedKBs, - rateKBs); - - if (properReadahead > readAheadBytes) - { - uint32_t diff = properReadahead - readAheadBytes; - readAheadBytes = properReadahead; - scsiReadPIO( - &scsiDev.data[scsiBytesRead], - diff, - &parityError); - scsiBytesRead += diff; - } - } - } - } - } - - HAL_SD_WriteBlocks_DMA(&hsd, (&scsiDev.data[0]), i + sdLBA, sectors); - - int underrun = 0; - if (scsiBytesRead < totalBytes && !scsiDev.resetFlag) - { - scsiReadPIO( - &scsiDev.data[scsiBytesRead], - totalBytes - readAheadBytes, - &parityError); - - // Oh dear, SD finished first. - underrun = HAL_DMA_GetState(hsd.hdmatx) == HAL_DMA_STATE_BUSY; - - scsiBytesRead += (totalBytes - readAheadBytes); - } + HAL_SD_WriteBlocks_DMA(&hsd, i + sdLBA, sectors); + int j = 0; + int prep = 0; + int sdActive = 0; + uint32_t dmaFinishTime = 0; + while (j < sectors && !scsiDev.resetFlag) + { + if (sdActive && + HAL_SD_GetState(&hsd) != HAL_SD_STATE_BUSY) + { + HAL_SD_CardStateTypeDef tmpCardState = HAL_SD_GetCardState(&hsd); + if (tmpCardState != HAL_SD_CARD_PROGRAMMING) + { + j += sdActive; + sdActive = 0; + } + } + if (!sdActive && ((prep - j) > 0)) + { + // Start an SD transfer if we have space. + HAL_SD_WriteBlocks_Data(&hsd, &scsiDev.data[SD_SECTOR_SIZE * (j % maxSectors)]); + + sdActive = 1; + } + + if (((prep - j) < maxSectors) && + (prep < sectors)) + { + scsiReadPIO( + &scsiDev.data[(prep % maxSectors) * SD_SECTOR_SIZE], + SD_SECTOR_SIZE, + &parityError); + prep++; + if (prep == sectors) + { + dmaFinishTime = s2s_getTime_ms(); + } + } + + if (i + prep >= totalSDSectors && + !disconnected && + (!parityError || !enableParity) && + s2s_elapsedTime_ms(dmaFinishTime) >= 180) + { + // We're transferring over the SCSI bus faster than the SD card + // can write. All data is buffered, and we're just waiting for + // the SD card to complete. The host won't let us disconnect. + // Some drivers set a 250ms timeout on transfers to complete. + // SD card writes are supposed to complete + // within 200ms, but sometimes they don't. + // Just pretend we're finished. + process_Status(); + clearBSY = process_MessageIn(0); // Will go to BUS_FREE state but keep BSY asserted. + disconnected = 1; + } + } - uint32_t dmaFinishTime = s2s_getTime_ms(); - while ((HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) && - s2s_elapsedTime_ms(dmaFinishTime) < 180) - { - // Wait while keeping BSY. - } + if (scsiDev.resetFlag) + { + HAL_SD_Abort(&hsd); + } + else + { + while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {} // Waits for DMA to complete + SDMMC_CmdStopTransfer(hsd.Instance); + } HAL_SD_CardStateTypeDef cardState = HAL_SD_GetCardState(&hsd); while ((cardState == HAL_SD_CARD_PROGRAMMING || cardState == HAL_SD_CARD_RECEIVING) && @@ -869,8 +833,8 @@ void scsiDiskPoll() cardState = HAL_SD_GetCardState(&hsd); } - if (i + sectors >= totalSDSectors && - !underrun && + if (!disconnected && + i + sectors >= totalSDSectors && (!parityError || !enableParity)) { // We're transferring over the SCSI bus faster than the SD card @@ -884,11 +848,6 @@ void scsiDiskPoll() clearBSY = process_MessageIn(0); // Will go to BUS_FREE state but keep BSY asserted. } - while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) - { - // Wait while keeping BSY. - } - cardState = HAL_SD_GetCardState(&hsd); while (cardState == HAL_SD_CARD_PROGRAMMING || cardState == HAL_SD_CARD_RECEIVING) { @@ -898,13 +857,6 @@ void scsiDiskPoll() cardState = HAL_SD_GetCardState(&hsd); } - if (underrun && (!parityError || !enableParity)) - { - // Try again. Data is still in memory. - BSP_SD_WriteBlocks_DMA(&scsiDev.data[0], i + sdLBA, sectors); - scsiDev.sdUnderrunCount++; - } - i += sectors; } else @@ -914,6 +866,9 @@ void scsiDiskPoll() // possible in each SD card transaction. // use sg_dd from sg_utils3 tools to test. + uint32_t rem = totalSDSectors - i; + uint32_t sectors = rem < maxSectors ? rem : maxSectors; + if (useSlowDataCount) { scsiSetDataCount(sectors * bytesPerSector); -- 2.38.5