Fix scsi write issues
authorMichael McMaster <michael@codesrc.com>
Tue, 4 May 2021 06:06:42 +0000 (16:06 +1000)
committerMichael McMaster <michael@codesrc.com>
Tue, 4 May 2021 06:06:42 +0000 (16:06 +1000)
14 files changed:
STM32CubeMX/2020c.diff
STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_sd.h
STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c
STM32CubeMX/2020c/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c
STM32CubeMX/2021.diff
STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sd.h
STM32CubeMX/2021/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c
STM32CubeMX/revF.diff
STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_sd.h
STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c
STM32CubeMX/revF/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_sdmmc.c
src/firmware/bsp_driver_sd.c
src/firmware/config.c
src/firmware/disk.c

index 8e6da4cddbc209692bff1beb4c0e6ce37d430909..7e740bae8d6ee355b146bd8be734469eb45a8342 100644 (file)
@@ -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 
index a4317e48bc2197be6a94e3e69f065ef604f29fe8..7165538a888d60cda84d2a7bf16b565500e318ef 100644 (file)
@@ -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);
 
index db67bf13dc83e4caee502b8ce294a1fd9af04a34..b10dd0e630ecbc82c6cfcbc0df59f2ebc9ba2344 100644 (file)
@@ -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));
 }
 
 /**
index ee78e9e0a2b71c6254dba0905d9d679b1c74c658..de39f9d2eeafc535ce1cad460dbc40f48d82c341 100644 (file)
@@ -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 
index 5d68fce7296a279a466c445f1774511b26e96907..53f7cbf06ba6c94ad51f4dc050571b09c342d223 100644 (file)
@@ -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)
index 2e254f196d144d8cf94ef76ba6b4e90711644528..fe133b051726cff4890d5d97c306890a7a9b1195 100644 (file)
@@ -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);
 
index 1a09028f3a7d6080689dd77419dc10429f14235a..d039e87be7d2707268bbd983cd49f289097bd63a 100644 (file)
@@ -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));
 }
 
 /**
index 330f6453bc82ec4779f6dd82447dbfd9a199a5a2..8f93079cf199c7e9c3b4a478102bd4b633884eaa 100644 (file)
@@ -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 
index a4317e48bc2197be6a94e3e69f065ef604f29fe8..7165538a888d60cda84d2a7bf16b565500e318ef 100644 (file)
@@ -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);
 
index db67bf13dc83e4caee502b8ce294a1fd9af04a34..b10dd0e630ecbc82c6cfcbc0df59f2ebc9ba2344 100644 (file)
@@ -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));
 }
 
 /**
index ee78e9e0a2b71c6254dba0905d9d679b1c74c658..de39f9d2eeafc535ce1cad460dbc40f48d82c341 100644 (file)
@@ -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 
index 5c561bfe456e98e3f2dfc5c1685ffe784e277d4c..dda58d9d7a2ba5e38cda919f88817e4564f339c4 100755 (executable)
@@ -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; 
index 5f25635af9b107420fd9cc6f0bac35eb446ff32b..ea9a9f56ff85fa3ed358d586ec13cc5d3c2c798f 100755 (executable)
@@ -36,7 +36,7 @@
 \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
index b853fea5b31e0e260a0b98e0a1b336c22b8c4f2c..666836503be6e9372b66471feb85a4bce5d83162 100755 (executable)
@@ -553,31 +553,6 @@ int scsiDiskCommand()
        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
@@ -740,6 +715,7 @@ void scsiDiskPoll()
                                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
@@ -767,97 +743,85 @@ void scsiDiskPoll()
                        // 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
@@ -869,8 +833,8 @@ void scsiDiskPoll()
                     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
@@ -884,11 +848,6 @@ void scsiDiskPoll()
                                        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
@@ -898,13 +857,6 @@ void scsiDiskPoll()
                     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
@@ -914,6 +866,9 @@ void scsiDiskPoll()
                                // 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