cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L4 FreeRTOS+DMA2 Channel 4 problem

kronikary
Associate III

I am using STM32L496 Nucelo, CubeMX 6.1.1; FATFS, DMA SDMMC with FreeRtos. For some reason I have problems when it comes to using DMA2 Channel 4 with FreeRtos.

When it is selected for SDMMC1_TX then I can mount SD card and read data without any problems. Although I can't write any data into SD card. I call:

fresult = f_open(&fit_record_file, "test.txt", FA_CREATE_ALWAYS | FA_WRITE);

Which return FR_OK but the file is not created. Next when I call:

fresult = f_write(&fit_record_file, &data_crc, sizeof(data_crc), &fit_record_br);

Program gets stucks for SD_TIMEOUT in function SD_read at status = osMessageQueueGet(SDQueueID, (void *)&event, NULL, SD_TIMEOUT); in sd_discio.c at 463 line. Callback BSP_SD_WriteCpltCallback is never called.

When DMA2 Channel 4 is selected for SDMMC1_RX then I can't mount SD and at the end program again waits SD_TIMEOUT for message, which never comes. Callback BSP_SD_ReadCpltCallback is never called.

After this tests it looks like there is a problem with DMA2 Channel 4, but I turned off FreeRtos and everything works fine no matter how DMA2 is configured.

Has anyone met this problem? Maybe you have any sugestions where might be the problem?

 EDIT: Problem is not related with FreeRTOS.

After turning off FreeRTOS, DMA template was turned off by CubeMX so I was making tests without DMA usage.

Now when I turned on DMA template and made tests without FreeRTOS problem still occurs.

  • Turning DMA2 Channel 4 on RX crashes reading
  • Turning DMA2 Channel 4 on TX crashes writing

So problem is related only with SDMMC DMA and FATFS - using DMA2 Channel 4 creates BUG.  Without DMA everything works fine.

1 ACCEPTED SOLUTION

Accepted Solutions
kronikary
Associate III

SOLUTION!

This post helped me:

https://community.st.com/s/question/0D50X00009XkXQ5/stm32-l476rg-dma-sdmmc-sdmmc-timeout-after-write

In above link I have found below information:

https://pastebin.com/yCxq9E6q

In maic.c paste this:

uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
{
 
	uint8_t sd_state = MSD_OK;
	  HAL_DMA_Abort(&hdma_sdmmc1_tx);
	    HAL_DMA_Abort(&hdma_sdmmc1_rx);
 
	    /* Deinitialize the Channel for new transfer */
	    HAL_DMA_DeInit(&hdma_sdmmc1_tx);
	    HAL_DMA_DeInit(&hdma_sdmmc1_rx);
 
	    HAL_DMA_Init(&hdma_sdmmc1_rx);
	  /* 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;
}
 uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
{
	  uint8_t sd_state = MSD_OK;
	  uint32_t tickstart = HAL_GetTick();
	    HAL_DMA_Abort(&hdma_sdmmc1_tx);
	    HAL_DMA_Abort(&hdma_sdmmc1_rx);
 
	    /* Deinitialize the Channel for new transfer */
	    HAL_DMA_DeInit(&hdma_sdmmc1_tx);
	    HAL_DMA_DeInit(&hdma_sdmmc1_rx);
 
	    /* Configure the DMA Channel */
	    HAL_DMA_Init(&hdma_sdmmc1_tx);
	  /* 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 stm32l4xx_it.c (interrupts for you stm; located in Core->Src->stm32.....) paste this code to DMA2_Channel4_IRQHandler:

if((hsd1.Context == (SD_CONTEXT_DMA | SD_CONTEXT_READ_SINGLE_BLOCK)) ||
	     (hsd1.Context == (SD_CONTEXT_DMA | SD_CONTEXT_READ_MULTIPLE_BLOCK)))
	  {
	     HAL_DMA_IRQHandler(&hdma_sdmmc1_rx);
	  }
	  else if((hsd1.Context == (SD_CONTEXT_DMA | SD_CONTEXT_WRITE_SINGLE_BLOCK)) ||
	          (hsd1.Context == (SD_CONTEXT_DMA | SD_CONTEXT_WRITE_MULTIPLE_BLOCK)))
	  {
	      HAL_DMA_IRQHandler(&hdma_sdmmc1_tx);
	  }

View solution in original post

3 REPLIES 3

Hello.

experienced similar issues

DMA template, at fatfs advanced settings must set to enable.

Give a try by changing the version of Freertos API version (v1 or v2) It worked in some cases.

and last, try to decrease sd clock by increasing divider. (because of the default settings of CUBEMX , block_sizes, etc, this solution works some times) .

Oh, my bad - after turning off FreeRTOS, DMA template was turned off by CubeMX so I was making tests without DMA usage.

Now when I turned on DMA template and made tests without FreeRTOS problem still occurs.

  • Turning DMA2 Channel 4 on RX crashes reading
  • Turning DMA2 Channel 4 on TX crashes writing

So problem is related only with SDMMC DMA and FATFS - using DMA2 Channel 4 creates BUG. Without DMA everything works fine.

I see I am not alone here: https://community.st.com/s/question/0D50X00009XkXQ5/stm32-l476rg-dma-sdmmc-sdmmc-timeout-after-write

kronikary
Associate III

SOLUTION!

This post helped me:

https://community.st.com/s/question/0D50X00009XkXQ5/stm32-l476rg-dma-sdmmc-sdmmc-timeout-after-write

In above link I have found below information:

https://pastebin.com/yCxq9E6q

In maic.c paste this:

uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
{
 
	uint8_t sd_state = MSD_OK;
	  HAL_DMA_Abort(&hdma_sdmmc1_tx);
	    HAL_DMA_Abort(&hdma_sdmmc1_rx);
 
	    /* Deinitialize the Channel for new transfer */
	    HAL_DMA_DeInit(&hdma_sdmmc1_tx);
	    HAL_DMA_DeInit(&hdma_sdmmc1_rx);
 
	    HAL_DMA_Init(&hdma_sdmmc1_rx);
	  /* 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;
}
 uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
{
	  uint8_t sd_state = MSD_OK;
	  uint32_t tickstart = HAL_GetTick();
	    HAL_DMA_Abort(&hdma_sdmmc1_tx);
	    HAL_DMA_Abort(&hdma_sdmmc1_rx);
 
	    /* Deinitialize the Channel for new transfer */
	    HAL_DMA_DeInit(&hdma_sdmmc1_tx);
	    HAL_DMA_DeInit(&hdma_sdmmc1_rx);
 
	    /* Configure the DMA Channel */
	    HAL_DMA_Init(&hdma_sdmmc1_tx);
	  /* 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 stm32l4xx_it.c (interrupts for you stm; located in Core->Src->stm32.....) paste this code to DMA2_Channel4_IRQHandler:

if((hsd1.Context == (SD_CONTEXT_DMA | SD_CONTEXT_READ_SINGLE_BLOCK)) ||
	     (hsd1.Context == (SD_CONTEXT_DMA | SD_CONTEXT_READ_MULTIPLE_BLOCK)))
	  {
	     HAL_DMA_IRQHandler(&hdma_sdmmc1_rx);
	  }
	  else if((hsd1.Context == (SD_CONTEXT_DMA | SD_CONTEXT_WRITE_SINGLE_BLOCK)) ||
	          (hsd1.Context == (SD_CONTEXT_DMA | SD_CONTEXT_WRITE_MULTIPLE_BLOCK)))
	  {
	      HAL_DMA_IRQHandler(&hdma_sdmmc1_tx);
	  }