Skip to content

SDMMC Data End Interrupt sometimes does not occur #94

Open
@by-gnome

Description

@by-gnome

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

bugSomething isn't workinghalHAL-LL driver-related issue or pull-request.internal bug trackerIssue confirmed and logged into the internal bug tracking systemsdmmcSecure Digital input/output Multimedia Card interface

Type

No type

Projects

Status

Analyzed

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions