Description
Describe the set-up
The device based on STM32L496VG with high load application. ICCARM v8.32, STM32Cube_FW_L4_V1.18.1.
Describe the bug
Writing to an SD memory card using SDMMC+DMA sometimes times out in the SD_write() function. This happens because the DATAEND interrupt does not occur.
After some debugging I found that the SD_DMATransmitCplt() function enables the DATAEND interrupt by setting the DATAENDIE bit, but interrupt does not occur, and after the timeout in the SD_write() function the DATAEND bit is set and the DATAENDIE bit is not set.
How To Reproduce
SDMMC parameters:
- Clock source - HSI48 RC
- Clock transition - Rising
- Clock divider bypass - Enable
- Clock power save - Enable
- HW flow control - Enable
- Wide bus mode - 4 bit
- DMA - DMA2 channel 5
The application writes data to the SD card for 12-24 hours, with a data rate of 128 kB/s. After writing several gigabytes of data, a timeout occurs in the SD_write() function.
Additional context
Let's consider the SD_DMATransmitCplt() function:
static void SD_DMATransmitCplt(DMA_HandleTypeDef *hdma)
{
SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent);
/* Enable DATAEND Interrupt */
__HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DATAEND));
}
In case of abnormal operation, before setting DATAENDIE, the SDMMC_STA register has the state 0x00105400:
TXDAVL = 1, TXFIFOHE = 1, TXACT = 1, DBCKEND = 1 or 0 (doesn't matter)
and SDMMC_MASK register has the state 0x00000000 !!!
After setting DATAENDIE, the SDMMC_STA register has the state 0x00105400:
TXDAVL = 1, TXFIFOHE = 1, TXACT = 1, DBCKEND = 1 or 0 (doesn't matter)
and SDMMC_MASK register has the state 0x00000100:
DATAENDIE = 1
After timeout in SD_write the SDMMC_STA register has the state 0x00000500:
DBCKEND = 1, DATAEND = 1
and SDMMC_MASK register has the state 0x0000001A:
TXUNDERRIE = 1, DTIMEOUTIE = 1, DCRCFAILIE = 1
The correct values in the SDMMC_MASK register are 0x0000001A and 0x0000011A. Therefore, it can be assumed that in the SD_DMATransmitCplt() function, reading/writing the SDMMC_MASK register is sometimes disrupted.
Possible solution
If I set the DATAENDIE bit in the HAL_SD_WriteBlocks_DMA() function, the problem does not occur.
--- a/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_sd.c
+++ b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_sd.c
@@ -1566,7 +1566,7 @@ HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData,
(void)SDMMC_ConfigData(hsd->Instance, &config);
/* Enable SD Error interrupts */
- __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR));
+ __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));
#else
/* Enable transfer interrupts */
__HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));
@@ -3225,9 +3225,6 @@ HAL_StatusTypeDef HAL_SD_Abort_IT(SD_HandleTypeDef *hsd)
static void SD_DMATransmitCplt(DMA_HandleTypeDef *hdma)
{
SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent);
-
- /* Enable DATAEND Interrupt */
- __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DATAEND));
}
Metadata
Metadata
Assignees
Labels
Type
Projects
Status