Sfoglia il codice sorgente

Fix scsi write issues

Michael McMaster 4 anni fa
parent
commit
8e245cbb02

+ 194 - 58
lib/SCSI2SD/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 

+ 2 - 1
lib/SCSI2SD/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);
 

+ 59 - 32
lib/SCSI2SD/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));
 }
 
 /**

+ 1 - 0
lib/SCSI2SD/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 

+ 172 - 29
lib/SCSI2SD/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)

+ 2 - 1
lib/SCSI2SD/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);
 

+ 63 - 31
lib/SCSI2SD/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));
 }
 
 /**

+ 194 - 58
lib/SCSI2SD/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 

+ 2 - 1
lib/SCSI2SD/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);
 

+ 59 - 32
lib/SCSI2SD/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));
 }
 
 /**

+ 1 - 0
lib/SCSI2SD/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 

+ 20 - 3
lib/SCSI2SD/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; 

+ 1 - 1
lib/SCSI2SD/src/firmware/config.c

@@ -36,7 +36,7 @@
 
 #include <string.h>
 
-static const uint16_t FIRMWARE_VERSION = 0x0642;
+static const uint16_t FIRMWARE_VERSION = 0x0643;
 
 // Optional static config
 extern uint8_t* __fixed_config;

+ 75 - 120
lib/SCSI2SD/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);