}
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);
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)
/* 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 */
{
add *= 512U;
- }
-
+-
- /* Set Block Size for Card */
- errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
- if(errorstate != HAL_SD_ERROR_NONE)
}
/* 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;
(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 */
+ }
+ }
+
- 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)
}
/* 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;
(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
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);
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)
* @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;
}
}
- 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 */
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)
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);
{
/* 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;
{
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))
{
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);
}
*/
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));
}
/**
return errorstate;
}
+
/**
* @brief Send the Write Multi Block command and check the response
* @param SDIOx: Pointer to SDIO register base
}
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)
(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 */
+ }
+ }
+
- 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;
}
/* 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;
(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)
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);
* @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;
}
}
- 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 */
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));
{
/* 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;
{
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))
{
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);
}
*/
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));
}
/**
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);
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)
/* 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 */
{
add *= 512U;
- }
-
+-
- /* Set Block Size for Card */
- errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
- if(errorstate != HAL_SD_ERROR_NONE)
}
/* 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;
(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 */
+ }
+ }
+
- 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)
}
/* 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;
(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
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);
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)
* @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;
}
}
- 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 */
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)
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);
{
/* 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;
{
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))
{
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);
}
*/
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));
}
/**
return errorstate;
}
+
/**
* @brief Send the Write Multi Block command and check the response
* @param SDIOx: Pointer to SDIO register base
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;
}
/* 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)
{
cardState = HAL_SD_GetCardState(&hsd);
}
-
}
return SD_state;
\r
#include <string.h>\r
\r
-static const uint16_t FIRMWARE_VERSION = 0x0642;\r
+static const uint16_t FIRMWARE_VERSION = 0x0643;\r
\r
// Optional static config\r
extern uint8_t* __fixed_config;\r
return commandHandled;\r
}\r
\r
-static uint32_t\r
-calcReadahead(uint32_t totalBytes, uint32_t sdSpeedKBs, uint32_t scsiSpeedKBs)\r
-{\r
- if (!(scsiDev.boardCfg.flags6 & S2S_CFG_ENABLE_BLIND_WRITES) ||\r
- (scsiSpeedKBs == 0) ||\r
- (scsiDev.hostSpeedMeasured == 0))\r
- {\r
- return totalBytes;\r
- }\r
-\r
- // uint32_t readAheadBytes = totalBytes * (1 - scsiSpeedKBs / sdSpeedKBs);\r
- // Won't overflow with 65536 max bytes, 20000 max scsi speed.\r
- uint32_t readAheadBytes = totalBytes - totalBytes * scsiSpeedKBs / sdSpeedKBs;\r
-\r
- // Round up to nearest FIFO size (* 4 for safety)\r
- readAheadBytes = ((readAheadBytes / SCSI_FIFO_DEPTH) + 4) * SCSI_FIFO_DEPTH;\r
-\r
- if (readAheadBytes > totalBytes)\r
- {\r
- readAheadBytes = totalBytes;\r
- }\r
-\r
- return readAheadBytes;\r
-}\r
-\r
void scsiDiskPoll()\r
{\r
uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
transfer.lba);\r
int i = 0;\r
int clearBSY = 0;\r
+ int disconnected = 0;\r
\r
int parityError = 0;\r
int enableParity = scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY;\r
// KEEP GOING to ensure FIFOs are in a good state.\r
// likely(!parityError || !enableParity))\r
{\r
- uint32_t rem = totalSDSectors - i;\r
- uint32_t sectors = rem < maxSectors ? rem : maxSectors;\r
-\r
if (bytesPerSector == SD_SECTOR_SIZE)\r
{\r
- // We assume the SD card is faster than the SCSI interface, but has\r
- // no flow control. This can be handled if a) the scsi interface\r
- // doesn't block and b) we read enough SCSI sectors first so that\r
- // the SD interface cannot catch up.\r
- uint32_t totalBytes = sectors * SD_SECTOR_SIZE;\r
+ uint32_t maxXferSectors = SCSI_XFER_MAX / SD_SECTOR_SIZE;\r
+ uint32_t rem = totalSDSectors - i;\r
+ uint32_t sectors = rem < maxXferSectors ? rem : maxXferSectors;\r
\r
- uint32_t sdSpeedKBs = s2s_getSdRateKBs() + (scsiDev.sdUnderrunCount * 256);\r
- uint32_t readAheadBytes = calcReadahead(\r
- totalBytes,\r
- sdSpeedKBs,\r
- scsiDev.hostSpeedKBs);\r
+ uint32_t totalBytes = sectors * SD_SECTOR_SIZE;\r
\r
if (useSlowDataCount)\r
{\r
- DWT->CYCCNT = 0; // Start counting cycles\r
scsiSetDataCount(totalBytes);\r
}\r
\r
- uint32_t scsiBytesRead = 0;\r
- if (readAheadBytes > 0)\r
- {\r
- scsiReadPIO(\r
- &scsiDev.data[scsiBytesRead],\r
- readAheadBytes,\r
- &parityError);\r
- scsiBytesRead += readAheadBytes;\r
-\r
- if (i == 0 && !useSlowDataCount)\r
- {\r
- uint32_t elapsedCycles = DWT->CYCCNT;\r
-\r
- // uint32_t rateKBs = (readAheadBytes / 1000) / (elapsedCycles / HAL_RCC_GetHCLKFreq());\r
- // Scaled by 4 to avoid overflow w/ max 65536 at 108MHz.\r
- uint32_t rateKBs = ((readAheadBytes / 4) * (HAL_RCC_GetHCLKFreq() / 1000) / elapsedCycles) * 4;\r
-\r
- scsiDev.hostSpeedKBs = (scsiDev.hostSpeedKBs + rateKBs) / 2;\r
- scsiDev.hostSpeedMeasured = 1;\r
-\r
- if (rateKBs < scsiDev.hostSpeedKBs)\r
- {\r
- // Our readahead was too slow; assume remaining bytes\r
- // will be as well.\r
- if (readAheadBytes < totalBytes)\r
- {\r
- uint32_t properReadahead = calcReadahead(\r
- totalBytes,\r
- sdSpeedKBs,\r
- rateKBs);\r
-\r
- if (properReadahead > readAheadBytes)\r
- {\r
- uint32_t diff = properReadahead - readAheadBytes;\r
- readAheadBytes = properReadahead;\r
- scsiReadPIO(\r
- &scsiDev.data[scsiBytesRead],\r
- diff,\r
- &parityError);\r
- scsiBytesRead += diff;\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- HAL_SD_WriteBlocks_DMA(&hsd, (&scsiDev.data[0]), i + sdLBA, sectors);\r
-\r
- int underrun = 0;\r
- if (scsiBytesRead < totalBytes && !scsiDev.resetFlag)\r
- {\r
- scsiReadPIO(\r
- &scsiDev.data[scsiBytesRead],\r
- totalBytes - readAheadBytes,\r
- &parityError);\r
-\r
- // Oh dear, SD finished first.\r
- underrun = HAL_DMA_GetState(hsd.hdmatx) == HAL_DMA_STATE_BUSY;\r
-\r
- scsiBytesRead += (totalBytes - readAheadBytes);\r
- }\r
+ HAL_SD_WriteBlocks_DMA(&hsd, i + sdLBA, sectors);\r
+ int j = 0;\r
+ int prep = 0;\r
+ int sdActive = 0;\r
+ uint32_t dmaFinishTime = 0;\r
+ while (j < sectors && !scsiDev.resetFlag)\r
+ {\r
+ if (sdActive &&\r
+ HAL_SD_GetState(&hsd) != HAL_SD_STATE_BUSY)\r
+ {\r
+ HAL_SD_CardStateTypeDef tmpCardState = HAL_SD_GetCardState(&hsd);\r
+ if (tmpCardState != HAL_SD_CARD_PROGRAMMING)\r
+ {\r
+ j += sdActive;\r
+ sdActive = 0;\r
+ }\r
+ }\r
+ if (!sdActive && ((prep - j) > 0))\r
+ {\r
+ // Start an SD transfer if we have space.\r
+ HAL_SD_WriteBlocks_Data(&hsd, &scsiDev.data[SD_SECTOR_SIZE * (j % maxSectors)]);\r
+\r
+ sdActive = 1;\r
+ }\r
+\r
+ if (((prep - j) < maxSectors) &&\r
+ (prep < sectors))\r
+ {\r
+ scsiReadPIO(\r
+ &scsiDev.data[(prep % maxSectors) * SD_SECTOR_SIZE],\r
+ SD_SECTOR_SIZE,\r
+ &parityError);\r
+ prep++;\r
+ if (prep == sectors)\r
+ {\r
+ dmaFinishTime = s2s_getTime_ms();\r
+ }\r
+ }\r
+ \r
+ if (i + prep >= totalSDSectors &&\r
+ !disconnected &&\r
+ (!parityError || !enableParity) &&\r
+ s2s_elapsedTime_ms(dmaFinishTime) >= 180)\r
+ {\r
+ // We're transferring over the SCSI bus faster than the SD card\r
+ // can write. All data is buffered, and we're just waiting for\r
+ // the SD card to complete. The host won't let us disconnect.\r
+ // Some drivers set a 250ms timeout on transfers to complete.\r
+ // SD card writes are supposed to complete\r
+ // within 200ms, but sometimes they don't.\r
+ // Just pretend we're finished.\r
+ process_Status();\r
+ clearBSY = process_MessageIn(0); // Will go to BUS_FREE state but keep BSY asserted.\r
+ disconnected = 1;\r
+ }\r
+ }\r
\r
- uint32_t dmaFinishTime = s2s_getTime_ms();\r
- while ((HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) &&\r
- s2s_elapsedTime_ms(dmaFinishTime) < 180)\r
- {\r
- // Wait while keeping BSY.\r
- }\r
+ if (scsiDev.resetFlag)\r
+ {\r
+ HAL_SD_Abort(&hsd);\r
+ }\r
+ else\r
+ {\r
+ while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {} // Waits for DMA to complete\r
+ SDMMC_CmdStopTransfer(hsd.Instance);\r
+ }\r
\r
HAL_SD_CardStateTypeDef cardState = HAL_SD_GetCardState(&hsd);\r
while ((cardState == HAL_SD_CARD_PROGRAMMING || cardState == HAL_SD_CARD_RECEIVING) &&\r
cardState = HAL_SD_GetCardState(&hsd);\r
}\r
\r
- if (i + sectors >= totalSDSectors &&\r
- !underrun &&\r
+ if (!disconnected && \r
+ i + sectors >= totalSDSectors &&\r
(!parityError || !enableParity))\r
{\r
// We're transferring over the SCSI bus faster than the SD card\r
clearBSY = process_MessageIn(0); // Will go to BUS_FREE state but keep BSY asserted.\r
}\r
\r
- while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY)\r
- {\r
- // Wait while keeping BSY.\r
- }\r
-\r
cardState = HAL_SD_GetCardState(&hsd);\r
while (cardState == HAL_SD_CARD_PROGRAMMING || cardState == HAL_SD_CARD_RECEIVING) \r
{\r
cardState = HAL_SD_GetCardState(&hsd);\r
}\r
\r
- if (underrun && (!parityError || !enableParity))\r
- {\r
- // Try again. Data is still in memory.\r
- BSP_SD_WriteBlocks_DMA(&scsiDev.data[0], i + sdLBA, sectors);\r
- scsiDev.sdUnderrunCount++;\r
- }\r
-\r
i += sectors;\r
}\r
else\r
// possible in each SD card transaction.\r
// use sg_dd from sg_utils3 tools to test.\r
\r
+ uint32_t rem = totalSDSectors - i;\r
+ uint32_t sectors = rem < maxSectors ? rem : maxSectors;\r
+\r
if (useSlowDataCount)\r
{\r
scsiSetDataCount(sectors * bytesPerSector);\r