cancel
Showing results for 
Search instead for 
Did you mean: 

FatFS on SDMMC not working with DMA on STM32L4A6ZGT6U

CKugl.1
Senior II

I'm on STM32CubeIDE Version: 1.9.0 Build: 12015_20220302_0855 (UTC), MCU STM32L4A6ZGTx, Firmware STM32Cube FW_L4 V1.17.1. I'm using a NUCLEO-L4A6ZG.

I'm trying to get FatFS working on SDMMC, with DMA, and having problems.

First, the bundled version of FatFS seems to be ancient. It is so old that it doesn't resemble the documented API at http://elm-chan.org/fsw/ff/00index_e.html. Is there a way I can update it such that my changes won't be wiped out each time I run or update the Device Configuration tool?

The big problem is that it won't work if I select "Use dma template" in Device Configuration Tool/Pinout & Configuration/FATFS/Advanced Settings. If I disable "Use dma template", it works OK (with polling).

With DMA enabled, it gets hung up here:

SD_write() at sd_diskio.c:351 0x80081c8

disk_write() at diskio.c:104 0x800837c

f_mkfs() at ff.c:5,661 0x8008af0

test() at test.c:23 0x80011fc

main() at main.c:103 0x8000914

where I see

if(BSP_SD_WriteBlocks_DMA((uint32_t*)buff,
                              (uint32_t)(sector),
                              count) == MSD_OK)
    {
      /* Wait that writing process is completed or a timeout occurs */
 
      timeout = HAL_GetTick();
      while((WriteStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT))
      {
      }
      /* in case of a timeout return error */
      if (WriteStatus == 0)
      {
        res = RES_ERROR;
      }

(SD_write() at sd_diskio.c:351 is line 8 in the snippet).

Apparently, it is waiting for BSP_SD_WriteCpltCallback (or HAL_SD_TxCpltCallback, HAL_SD_IRQHandler, SDMMC1_IRQHandler) which is never called:

void BSP_SD_WriteCpltCallback(void)
{
 
  WriteStatus = 1;
}

At this point, if I look at hsd1, I see:

Instance SDMMC_TypeDef * 0x40012800 (Hex)

POWER volatile uint32_t 0x3 (Hex)

CLKCR volatile uint32_t 0x4900 (Hex)

ARG volatile uint32_t 0x3f (Hex)

CMD volatile uint32_t 0x458 (Hex)

RESPCMD const volatile uint32_t 0x18 (Hex)

RESP1 const volatile uint32_t 0x900 (Hex)

RESP2 const volatile uint32_t 0x5b590000 (Hex)

RESP3 const volatile uint32_t 0x76b27f80 (Hex)

RESP4 const volatile uint32_t 0xa404012 (Hex)

DTIMER volatile uint32_t 0xffffffff (Hex)

DLEN volatile uint32_t 0x200 (Hex)

DCTRL volatile uint32_t 0x99 (Hex)

DCOUNT const volatile uint32_t 0x200 (Hex)

STA const volatile uint32_t 0x145000 (Hex)

ICR volatile uint32_t 0x0 (Hex)

MASK volatile uint32_t 0x1a (Hex)

RESERVED0 uint32_t [2] 0x40012840 (Hex)

FIFOCNT const volatile uint32_t 0x80 (Hex)

RESERVED1 uint32_t [13] 0x4001284c (Hex)

FIFO volatile uint32_t 0x4d90feeb (Hex)

I find it interesting that the MASK is Binary:11010, so only bits 1, 3, and 4 are set, which are:

  • Bit 1 DCRCFAILIE: Data CRC fail interrupt enable
  • Bit 3 DTIMEOUTIE: Data timeout interrupt enable
  • Bit 4 TXUNDERRIE: Tx FIFO underrun error interrupt enable

so this list does not include Bit 8 DATAENDIE: Data end interrupt enable.

STA is Binary:101000101000000000000, which is bits 12, 14, 18, and 20:

  • Bit 20 TXDAVL: Data available in transmit FIFO
  • Bit 18 TXFIFOE: Transmit FIFO empty
  • Bit 14 TXFIFOHE: Transmit FIFO half empty: at least 8 words can be written into the FIFO
  • Bit 12 TXACT: Data transmit in progress

It's trying to send a 512 byte block:

  • DLEN volatile uint32_t 0x200 (Hex)
  • DCOUNT const volatile uint32_t 0x200 (Hex)

Since DCOUNT has not decremented, it looks like no data has been transferred.

What could be the problem?

I put the project on GitHub: https://github.com/carlk3/STM32L4A6ZGTx_SDMMC. It should be complete enough to build. (Is that the best way to share code here? It's fairly painless with EGit: the Git integration for Eclipse).

40 REPLIES 40

IDMA sounds nice, especially since DMA with SDMMC is somewhat broken on the STM32L496xx/STM32L4A6xx.

In my "real" STM32L496xx/STM32L4A6xx project, I use SDMMCCLK clock divide factor 0 (SDMMC_CK frequency of 24 MHz).

I think I had it set to 14 for that example so that I could look at the bus with a cheap logic analyzer.

I have downloaded your example project. I was going to test it as is on my device, but it seems they are not pin compatible with the L5. 

Well, that example actually started life as https://github.com/STMicroelectronics/STM32CubeL4/tree/master/Projects/STM32L476G-EVAL/Applications/FatFs/FatFs_uSD_DMA_RTOS and I ported it to STM32CubeIDE and the NUCLEO-L496ZG/NUCLEO-L4A6ZG.

Zaher
Senior II

@Jimmy05​ @CKugl.1​ 

I used the BSP code for SDMMC available here: \STM32Cube_FW_L5_V1.4.0\Projects\STM32L552E-EV\Applications\FatFs\FatFs_uSD_RTOS and it works perfectly. I will experiment with DMA-based diskio examples later.

AWinc
Associate

Hi,

I would like to share with you about my experiences connected with SDIO and DMA (maybe it will help you with solving your problem).

I make test with following configuration:

a) hardware - STM32F767 with connected SDCard (SDIO1, note: lines don't have the pull-up resistors so I used GPIO pull-up's).

b) software - after SD card initialization is executed test which read and write sector/-s and allow verify reading/writing SD Card procedures.(see function: SDMMC1_SD_Tests)

Case 1

Project created by STM32CubeIDE (or CubeMX) - selected only SDIO and DMA.

Problem was with read and write using DMA.

Solution - in main.c the initialization DMA and SDIO order was incorrect.

Correct order:

 MX_DMA_Init();

 MX_SDMMC1_SD_Init();

Case 2

Project based on example from STMCube [1] - I tested only from it SDIO with DMA (all USB initializers are disable).

[1] - STM32Cube_FW_F7_V1.17.0\Projects\STM32746G-Discovery\Applications\USB_Device\MSC_Standalone

During debugging I observed symptoms similar like in case 1. But in this case the initialization of SDIO and DMA are combine together so the order was OK.

I found in main.c that CPU cache was enabled (function CPU_CACHE_Enable(void)) when I disable D-Cache (commented line with "SCB_EnableDCache();") everything started work OK.

I attached working copy of both project. Debug informations are writing to SVO.

Dont't forget changing priority timebase (if require) - according to description "..care must be taken if HAL_Delay() is called from a peripheral ISR process, the Tick interrupt line must have higher priority (numerically lower) than the peripheral interrupt."

AWinc
Associate

And second file

could you please repost the link to the workaround? seems like its broken. Thanks

Great detective work btw!

feuerwolf
Senior

Hi All, i found some time to update my inital STM32L496 SDMMC freeRTOS DMA Sd Card example and put it on Github.

Here you can find my interpretation:

feuerwolf/STM32L496-DMA-FreeRTOS-SDMMC-SdCard-Base-Project: STM32L496 DMA FreeRTOS SDMMC SdCard Base Project (github.com)

Cube_FatFs_uSD_DMA_RTOS_1DMA? I just tried clicking on it and it gave me this:

0693W00000QO7lQQAT.pngand when I clicked "Download" I got Cube_FatFs_uSD_DMA_RTOS_1DMA.zip, which seems to be complete. Maybe there is a permissions problem?

Hi, thanks, the link to your example still worked. I was more interested in STMs direct reply to your case.