Skip to main content
Graduate
January 9, 2021
Solved

STM32L4 SDMMC + FATFS

  • January 9, 2021
  • 2 replies
  • 2074 views

Hi,

I would like using SD card with FATFS and read/write to SD card.

If i have bare-metal FW without DMA template enable it is work.

But if I enable DMA template f_mount, f_open return FR_OK but f_write, f_read Disc_error.

I setted in CubeMX SDMMC1- SD 1bit.

In DMA window added shared DMA channel (RX/TX SDMMC)

In Fatfs enabled dma template.

But doesnt work.

If in FatFS disable dma template, read/write is work propertly.

I using STM32L496RG

CubeMX 6.1.1

FW package 1.16.0

Please help.

thank you

    This topic has been closed for replies.
    Best answer by lorant124

    I have found the solution to this problem:

    2 way (RX,TX) dma doesnt work, I dont known why...

    But shared DMA channel yes but in BSP_driver_cd.c CubeMX doesnt generate propertly Write *** Read function.

    in file bsp_driver_sd.c in function modify BSP_SD_WriteBlocks_DMA(...):

    __weak uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
    {
     uint8_t sd_state = MSD_OK;
     
     // Since we are only using 1 DMA channel for SDMMC
     // Change DMA direction before calling SD Read
     // Direction can only be changed when DMA is disabled
     
     __HAL_DMA_DISABLE(hsd1.hdmatx);
     hsd1.hdmatx->Init.Direction = DMA_MEMORY_TO_PERIPH;
     hsd1.hdmatx->Instance->CCR |= (uint32_t)DMA_CCR_DIR;
     
     /* Write block(s) in DMA transfer mode */
     if (HAL_SD_WriteBlocks_DMA(&hsd1, (uint8_t *)pData, WriteAddr, NumOfBlocks) != HAL_OK)
     {
     sd_state = MSD_ERROR;
     }
     
     return sd_state;
    }

    in file bsp_driver_sd.c in function modify BSP_SD_ReadBlocks_DMA(...):

    __weak uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
    {
     uint8_t sd_state = MSD_OK;
     // Since we are only using 1 DMA channel for SDMMC
     // Change DMA direction before calling SD Read
     // Direction can only be changed when DMA is disabled
     
     __HAL_DMA_DISABLE(hsd1.hdmarx);
     hsd1.hdmarx->Init.Direction = DMA_PERIPH_TO_MEMORY;
     hsd1.hdmarx->Instance->CCR &= ~DMA_CCR_DIR;
     
     /* Read block(s) in DMA transfer mode */
     if (HAL_SD_ReadBlocks_DMA(&hsd1, (uint8_t *)pData, ReadAddr, NumOfBlocks) != HAL_OK)
     {
     sd_state = MSD_ERROR;
     }
     
     return sd_state;
    }

    Solution first posted superspud9 on reddit.

    thanks

    2 replies

    lorant124AuthorAnswer
    Graduate
    January 10, 2021

    I have found the solution to this problem:

    2 way (RX,TX) dma doesnt work, I dont known why...

    But shared DMA channel yes but in BSP_driver_cd.c CubeMX doesnt generate propertly Write *** Read function.

    in file bsp_driver_sd.c in function modify BSP_SD_WriteBlocks_DMA(...):

    __weak uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
    {
     uint8_t sd_state = MSD_OK;
     
     // Since we are only using 1 DMA channel for SDMMC
     // Change DMA direction before calling SD Read
     // Direction can only be changed when DMA is disabled
     
     __HAL_DMA_DISABLE(hsd1.hdmatx);
     hsd1.hdmatx->Init.Direction = DMA_MEMORY_TO_PERIPH;
     hsd1.hdmatx->Instance->CCR |= (uint32_t)DMA_CCR_DIR;
     
     /* Write block(s) in DMA transfer mode */
     if (HAL_SD_WriteBlocks_DMA(&hsd1, (uint8_t *)pData, WriteAddr, NumOfBlocks) != HAL_OK)
     {
     sd_state = MSD_ERROR;
     }
     
     return sd_state;
    }

    in file bsp_driver_sd.c in function modify BSP_SD_ReadBlocks_DMA(...):

    __weak uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
    {
     uint8_t sd_state = MSD_OK;
     // Since we are only using 1 DMA channel for SDMMC
     // Change DMA direction before calling SD Read
     // Direction can only be changed when DMA is disabled
     
     __HAL_DMA_DISABLE(hsd1.hdmarx);
     hsd1.hdmarx->Init.Direction = DMA_PERIPH_TO_MEMORY;
     hsd1.hdmarx->Instance->CCR &= ~DMA_CCR_DIR;
     
     /* Read block(s) in DMA transfer mode */
     if (HAL_SD_ReadBlocks_DMA(&hsd1, (uint8_t *)pData, ReadAddr, NumOfBlocks) != HAL_OK)
     {
     sd_state = MSD_ERROR;
     }
     
     return sd_state;
    }

    Solution first posted superspud9 on reddit.

    thanks

    Graduate II
    December 4, 2023

    This is great info. I don't know how we are supposed to find this out.

    Anyway, FWIW, since the functions in bsp_driver_sd.c are defined as weak, you can define them anywhere in your code that is called and it will override the implementations in bsp_driver_sd.c. That way you can avoid having to replace the code each time it is auto-generated.