Skip to main content
Visitor II
September 19, 2022
Question

Interface SDMMC using FileX middleware issue in 4-bit bus width mode - STM32

  • September 19, 2022
  • 11 replies
  • 7223 views

Hi, i'm using STM32U575ZI-Q (in NUCLEO-U575), I want to write and read Fat32 files on SD using SDMMC interface, with FileX middleware. When I set the bus width in 1-bit the app work OK but when I switch the setting to 4-bit buswidth mode the app crashes, the debuging halt in the first reading command after SD initialization (in the HAL_SD_ReadBlocks function, it calls to SDMMC_CmdReadSingleBlock function and when it executes SDMMC_SendCommand the SDMMC bit transfer complete doesn't set)

I'm setting MCU CLK @ 160MHz (AHB & APB at 160MHz too), SDMMC CLK @ 6MHz (source PLL in 96MHz / (2* DIV) with DIV=8).

I repeat, in 1-bit buswidth the code working correctly ! But not in 4-bit mode

On the osciloscope I can see signals on pins D0-D3, so I can verify the 4-bit buswidth is set correctly.

I used a SDHC Standar and a SDHC UHS-1 and the result was the same.

The code includes fx_stm32_sd_driver_glue files.

int main(void)

{

 HAL_Init();

 SystemClock_Config();

 SystemPower_Config();

 MX_GPIO_Init();

 MX_USART1_UART_Init();

 MX_ICACHE_Init();

 MX_FileX_Init();

 MX_SDMMC1_SD_Init();

 HAL_GPIO_WritePin(LED_BLUE_GPIO_Port, LED_BLUE_Pin, GPIO_PIN_SET);

 HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_RESET);

 HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_RESET);

 fx_thread_entry(0);

 while(1)

 {

  HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin);

  HAL_Delay(400);

 }

 while (1)

 {

 }

}

void fx_thread_entry(ULONG thread_input)

{

 UINT status;

 ULONG bytes_read;

 CHAR read_buffer[32];

 CHAR buffer_SD[1560];

 CHAR data[] = "This is FileX working on STM32 \0";

 uint32_t a = 0;

 for (a = 0; a < 1560; ++a) {

 buffer_SD[a] = 'G';

 }

 buffer_SD[0] = 'd';

 buffer_SD[1] = 'i';

 buffer_SD[2] = 'v';

 buffer_SD[3] = '2';

 buffer_SD[1559] = '!';

 /* Open the SD disk driver. */

 status = fx_media_open(&sdio_disk, "STM32_SDIO_DISK", fx_stm32_sd_driver, 0,(VOID *) media_memory, sizeof(media_memory));

 /* Check the media open status. */

 if (status != FX_SUCCESS)

 {

  Error_Handler();

 }

 /* Create a file called STM32.TXT in the root directory. */

 status = fx_file_create(&sdio_disk, "STM32.TXT");

 /* Check the create status. */

 if (status != FX_SUCCESS)

 {

  /* Check for an already created status. This is expected on the

  second pass of this loop! */

  if (status != FX_ALREADY_CREATED)

  {

   /* Create error, call error handler. */

   Error_Handler();

  }

 }

 /* Open the test file. */

 status = fx_file_open(&sdio_disk, &fx_file, "STM32.TXT", FX_OPEN_FOR_WRITE);

 /* Check the file open status. */

 if (status != FX_SUCCESS)

 {

  /* Error opening file, call error handler. */

  Error_Handler();

 }

 /* Seek to the beginning of the test file. */

 status = fx_file_seek(&fx_file, 0);

 /* Check the file seek status. */

 if (status != FX_SUCCESS)

 {

  /* Error performing file seek, call error handler. */

  Error_Handler();

 }

 LED_BLUE_GPIO_Port->BRR |= LED_BLUE_Pin;

 /* Write a string to the test file. */

 status = fx_file_write(&fx_file, buffer_SD, sizeof(buffer_SD));

 /* Check the file write status. */

 if (status != FX_SUCCESS)

 {

  /* Error writing to a file, call error handler. */

  Error_Handler();

 }

 LED_BLUE_GPIO_Port->BSRR |= LED_BLUE_Pin;

 /* Close the test file. */

 status = fx_file_close(&fx_file);

 /* Check the file close status. */

 if (status != FX_SUCCESS)

 {

  /* Error closing the file, call error handler. */

  Error_Handler();

 }

 status = fx_media_flush(&sdio_disk);

 /* Check the media flush status. */

 if (status != FX_SUCCESS)

 {

  /* Error closing the file, call error handler. */

  Error_Handler();

 }

 /* Open the test file. */

 status = fx_file_open(&sdio_disk, &fx_file, "STM32.TXT", FX_OPEN_FOR_READ);

 /* Check the file open status. */

 if (status != FX_SUCCESS)

 {

  /* Error opening file, call error handler. */

  Error_Handler();

 }

 /* Seek to the beginning of the test file. */

 status = fx_file_seek(&fx_file, 0);

 /* Check the file seek status. */

 if (status != FX_SUCCESS)

 {

  /* Error performing file seek, call error handler. */

  Error_Handler();

 }

 /* Read the first 28 bytes of the test file. */

 status = fx_file_read(&fx_file, read_buffer, sizeof(data), &bytes_read);

 /* Check the file read status. */

 if ((status != FX_SUCCESS) || (bytes_read != sizeof(data)))

 {

  /* Error reading file, call error handler. */

  Error_Handler();

 }

 /* Close the test file. */

 status = fx_file_close(&fx_file);

 /* Check the file close status. */

 if (status != FX_SUCCESS)

 {

  /* Error closing the file, call error handler. */

  Error_Handler();

 }

 /* Close the media. */

 status = fx_media_close(&sdio_disk);

 /* Check the media close status. */

 if (status != FX_SUCCESS)

 {

  /* Error closing the media, call error handler. */

  Error_Handler();

 }

}

I guess the IDMA is not working properly but I'am not sure. If anyone can help me i appreciate it !

    This topic has been closed for replies.

    11 replies

    Visitor II
    December 13, 2022

    Were you able to resolve this issue? I'm seeing a similar issue on the same processor.

    ABust.3Author
    Visitor II
    December 13, 2022
    Hi JCout, I can't solve this issue, so I'm using other microcontroller (stm32h7b) and it works fine! This iC don't have FileX, the Middleware is the FATfs. (I am using binary files so i am not using the Middleware). Please comment your solution Regards Enviado desde Outlook Mobile<>
    Super User
    December 13, 2022

    >SDMMC CLK @ 6MHz

    this is very slow clk , sdcard should be at 50MHz , so 96 M source set div 1 ( = /2 ) -> 48M clk.

    try... maybe at first without dma setting/use , i had not much "luck" when dma template on.

    Visitor II
    March 27, 2023

    I have the very same problems using FileX and the glue driver too. I found out that when the driver reads a block from the SD card, data is shifted by 4 bits. When the FileX driver checks if there is a valid partition table, it reads a the following:

    partition_sector_ptr[510] = 0x5A

    partition_sector_ptr[511] = 0xA4

    According to a minimal partition table specification the values should be 0x55 at index 510 and 0xAA at index 511. So by curiosity I read the value at index 509, it was 0x05.

    So the data is shifted by 4 bits!

    Maybe this information can help ST to fix the problem...

    Visitor II
    March 27, 2023

    When changing to 1 bit mode, at least the partition table can be read, the driver fails a couple of lines later though.

    What is the point of CubeMX when we have to investigate the time we gained searching for all those terrible bugs in the HAL. ST has a serious code quality problem!

    Visitor II
    March 27, 2023
    /**
    * @brief Read Data from the SD device into a buffer.
    * @param UINT instance SD IP instance to read from.
    * @param UINT *buffer buffer into which the data is to be read.
    * @param UINT start_block the first block to start reading from.
    * @param UINT total_blocks total number of blocks to read.
    * @retval 0 on success error code otherwise
    */
    INT fx_stm32_sd_read_blocks(UINT instance, UINT *buffer, UINT start_block, UINT total_blocks)
    {
     INT ret = 0;
     
     /* USER CODE BEGIN PRE_READ_BLOCKS */
     /* USER CODE END PRE_READ_BLOCKS */
     sd_rx_cplt = 0;
     
     if(HAL_SD_ReadBlocks_DMA(&hsd1, (uint8_t *)buffer, start_block, total_blocks) != HAL_OK)
     {
     ret = 1;
     }
     
     /* USER CODE BEGIN POST_READ_BLOCKS */
     
     /* USER CODE END POST_READ_BLOCKS */
     
     return ret;
    }
     
    /**
    * @brief Write data buffer into the SD device.
    * @param UINT instance SD IP instance to write into.
    * @param UINT *buffer buffer to write into the SD device.
    * @param UINT start_block the first block to start writing into.
    * @param UINT total_blocks total number of blocks to write.
    * @retval 0 on success error code otherwise
    */
    INT fx_stm32_sd_write_blocks(UINT instance, UINT *buffer, UINT start_block, UINT total_blocks)
    {
     INT ret = 0;
     
     /* USER CODE BEGIN PRE_WRITE_BLOCKS */
     /* USER CODE END PRE_WRITE_BLOCKS */
     
     sd_tx_cplt = 0;
     
     if(HAL_SD_WriteBlocks_DMA(&hsd1, (uint8_t *)buffer, start_block, total_blocks) != HAL_OK)
     {
     ret = 1;
     }
     
     /* USER CODE BEGIN POST_WRITE_BLOCKS */
     
     /* USER CODE END POST_WRITE_BLOCKS */
     
     return ret;
    }

    @ST, you may want to add code to actually wait for completion here...

    Visitor II
    March 29, 2023

    How did you correct this? I corrected it by switching the HAL_SD_WriteBlocks_DMA to HAL_SD_WriteBlocks, (and the same on the read side) which works, but now I'm having massive performance issues, and am wondering if this is why.

    Visitor II
    March 29, 2023

    SDMMC without DMA is very slow, but for me it is even worse as I have buffer overruns on the MCU side, so with DMA it does not work and without DMA it does not work. The only configuration that works for me is 1 bit, no DMA with the driver code like you. I did try to use the DMA version by adding

    while(!sd_rx_cplt);

    and

    while(!sd_tx_cplt);

    respective just after the HAL_SD_{Read,Write}Blocks_DMA() function in order to wait for the DMA operation to complete. But that does only work exactly one single time as the ISR at the end of the file is only called the first time for the read operation. I do not know if we should acknowledge the ISR, but normally it is the HAL that does that,

    All in all I have a really hard time working with CubeMX and especially the ST HAL, I loose more time fixing such terrible bugs and searching all over the internet for examples as the documentation is really bad too as all the time I gain by configuring the project in the terrible slow CubeMX code generator.

    Visitor II
    March 27, 2023

    I can not believe how that code could be released by such a big enterprise. Do they hire 16 year old internships for the HAL?

    Visitor II
    March 27, 2023

    After fixing that bug I ran into a dangling pointer in the FileX library:

     /* Invoke media open callback. */
     if (media_ptr -> fx_media_open_notify)
     {
     media_ptr -> fx_media_open_notify(media_ptr);
     }

    If anyone has the same problem, you need to set that function pointer before using the function:

    FX_MEDIA media;
    fx_media_open_notify_set(&media, NULL);

    before calling the fx_media_open() function.

    :pouting_face:

    ST Employee
    April 6, 2023

    Hi @cm0x4d​,

    We have this example https://github.com/STMicroelectronics/STM32CubeU5/tree/main/Projects/STM32U575I-EV/Applications/FileX/Fx_File_Edit_Standalone

    working correctly with SDMMC configured in 4-bits width. This should easily portable on your NUCLEO board.

    Hope this helps you fixing your problem.

    Visitor II
    April 6, 2023

    Now lower your SDMMC clock and your example will not work either...

    I cannot run it in full clock speed as I am using cables to attach the SD card board and as the code to wait for completion is missing in your example's glue driver code too I highly doubt it will work at lower clock speeds, so no use to me.

    ST Employee
    April 6, 2023

    Thanks @cm0x4d​  for the prompt reply,

    Could you please share how did you lower your SDMMC clocking, that I can test in the same conditions as you?

    for the "wait for completion" it is not missing :smiling_face_with_smiling_eyes:, it is implemented here.

    https://github.com/STMicroelectronics/STM32CubeU5/blob/eb4d106d4ba5bbbc2eb2b0674ef5a3dcd2b3f4bd/Projects/STM32U575I-EV/Applications/FileX/Fx_File_Edit_Standalone/FileX/Target/fx_stm32_sd_driver.h#L127

    and here:

    https://github.com/STMicroelectronics/STM32CubeU5/blob/eb4d106d4ba5bbbc2eb2b0674ef5a3dcd2b3f4bd/Projects/STM32U575I-EV/Applications/FileX/Fx_File_Edit_Standalone/FileX/Target/fx_stm32_sd_driver.h#L143

    so maybe the default timeout should be increased, after lowering the SD Clock?

    regards

    Haithem.

    Visitor II
    April 6, 2023

    Well, makes perfect sense to implement the waiting in another file using a define :persevering_face:, this really helps to understand the code...

    I did set SDMMC clock divide factor to 1000.

    BUT in my fx_stm32_sd_driver.h, I have rather this code:

    /* Define how to notify about Read completion operation */
    #define FX_STM32_SD_READ_CPLT_NOTIFY()

    So why did CubeMX not generate the code to wait?

    ST Employee
    April 7, 2023

    Hi @cm0x4d​ 

    going to check with lower SDMMC Clocking. Meanwhile I checked the using STM32CubeMX 6.8.0 and the code is correctly generated. Below are screenshot of the configuration steps.

    • Enable SDMMC 4-bits wide config.


    _legacyfs_online_stmicro_images_0693W00000bhi2KQAQ.png

    • Select FileX MW and select SD interface.


    _legacyfs_online_stmicro_images_0693W00000bhi2eQAA.png

    • In the configuration panel select the " HAL DMA API" & "Global state variables" for respectively "Glue function Implementation" & "Transfer Completion Mechanism"


    _legacyfs_online_stmicro_images_0693W00000bhi3cQAA.png

    • After code generation Check the fx_stm32_driver.h file and the macros are there.


    _legacyfs_online_stmicro_images_0693W00000bhi3wQAA.pngHaithem.

    Graduate
    August 8, 2024

    I've got a similar problem on the Nucleo-U575ZI board. It always times out once I get to FX_STM32_SD_READ_CPLT_NOTIFY(). I used the same SD breakout board with the L496RG a couple of weeks ago and I got it to work. I'm using the Fx_File_Edit_Standalone from STM32U575I-EV as an example. Any ideas? Do I have to configure the DMA?

    Visitor II
    November 23, 2024

    Hi @WellLeithed and all,

     

    I have nearly the same problem on STM32H753I-EVAL2. I am using the latest HAL and the latest version of Azure RTOS. The only difference is that my system is able to stand 10-20 seconds of very intensive work with SD card but then it still stucks at the same point (FX_STM32_SD_READ_CPLT_NOTIFY()). The SD-clock is 96MHz and this board has a SD voltage converter. 

     

    The separate problem is that Azure RTOS does not generate SD card error callback so if error happens it will probably also stuck at this semaphore or return corrupted data. But I have checked for this, in my case no error callback happens. Looks like there is really no complete interrupt from SD controller.

     

    Regards,

    Dmitry