Possible shortcoming in HAL SD library
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-05-14 02:59 AM
Been trying to get an test application working on a STM32F469NIH Discovery board.
Should be fairly simple - Write a file to the SD Card, with FatFS, the read back:
Try as I might, I couldn't get things working.
After a bit of debugging, I think the issue lies with the DMA callback functions. I'm using FW_F4 V1.27.1, on CubeIDE, and it seems that the supplied SD_DMATransmitCplt() function isn't quite complete, when compared to the SD_DMAReceiveCplt() function.
There seems to be a couple of things missing - Firstly the call to the callback function - This is a must for the SD interface, because there's a queue that is waited on. Without the callback function being called, nothing is ever put on the queue, so a timeout error is received.
The other important bit seems to be the line of code that unlocks the HAL. A sensible thing to do, as we've just finished transferring data. Again, without it, some other bits of code later on fail as the HAL is still locked.
So I copied the code from the RX complete, and that seems to make things work - See attached text file
The question is, am I on the right track here? I'd like to help improve things, but at the same time, I don't want to fix things worse. A proper fix is better than a band-aid.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-07-07 05:44 AM
Hello MClar,
I'm analyzing the issue that you mentioned.
Could you pls give me the DMA configuration that you are using the both cases Transmit and Receive?
Best regards,
Ismail
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-05-24 01:16 AM
Hi,
Was there any solution to this issue?
I think I have a similar issue where within `SD_write` in `sd_diskio.c`, my program hangs on line `status = osMessageQueueGet(SDQueueID, (void *)&event, NULL, SD_TIMEOUT);` (line 463) because nothing ever gets put into the queue `SDQueueID`.
`BSP_SD_WriteCpltCallback` never gets called.
Like @MClar.3 I see that `SD_DMATransmitCplt` DOES get called. Is there some code missing there or is there some other configuration error?
I am using an STM32F427GT6, with STM32CubeIDE 1.12.0.
I am using FreeRTOS and FatFS.
Here is my `HAL_SD_MspInit` function
/**
* @brief SD MSP Initialization
* This function configures the hardware resources used in this example
* @param hsd: SD handle pointer
* @retval None
*/
void HAL_SD_MspInit(SD_HandleTypeDef* hsd)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hsd->Instance==SDIO)
{
/* USER CODE BEGIN SDIO_MspInit 0 */
/* USER CODE END SDIO_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_SDIO_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**SDIO GPIO Configuration
PC8 ------> SDIO_D0
PC9 ------> SDIO_D1
PC10 ------> SDIO_D2
PC11 ------> SDIO_D3
PC12 ------> SDIO_CK
PD2 ------> SDIO_CMD
*/
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* SDIO DMA Init */
/* SDIO_RX Init */
hdma_sdio_rx.Instance = DMA2_Stream3;
hdma_sdio_rx.Init.Channel = DMA_CHANNEL_4;
hdma_sdio_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_sdio_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sdio_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_sdio_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sdio_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sdio_rx.Init.Mode = DMA_PFCTRL;
hdma_sdio_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_sdio_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_sdio_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sdio_rx.Init.MemBurst = DMA_MBURST_INC4;
hdma_sdio_rx.Init.PeriphBurst = DMA_PBURST_INC4;
if (HAL_DMA_Init(&hdma_sdio_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hsd,hdmarx,hdma_sdio_rx);
/* SDIO_TX Init */
hdma_sdio_tx.Instance = DMA2_Stream6;
hdma_sdio_tx.Init.Channel = DMA_CHANNEL_4;
hdma_sdio_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_sdio_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sdio_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_sdio_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sdio_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sdio_tx.Init.Mode = DMA_PFCTRL;
hdma_sdio_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_sdio_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_sdio_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sdio_tx.Init.MemBurst = DMA_MBURST_INC4;
hdma_sdio_tx.Init.PeriphBurst = DMA_PBURST_INC4;
if (HAL_DMA_Init(&hdma_sdio_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hsd,hdmatx,hdma_sdio_tx);
/* USER CODE BEGIN SDIO_MspInit 1 */
// DMA priority above set to VERY_HIGH as suggested by
// https://community.st.com/t5/stm32-mcus-embedded-software/stm32f4-sdio-fat-write-problem/td-p/406687/page/2
/* USER CODE END SDIO_MspInit 1 */
}
}
By modifying the `SD_DMATransmitCplt` function in the `stm32f4xx_hal_sd.c` file so that the `Tx` handler is called (similar but not quite the same as @MClar.3 modification)
static void SD_DMATransmitCplt(DMA_HandleTypeDef *hdma)
{
SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent);
// /* Enable DATAEND Interrupt */
// __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DATAEND));
/* Disable the DMA transfer for transmit request by setting the DMAEN bit
in the SD DCTRL register */
hsd->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
/* Clear all the static flags */
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
hsd->State = HAL_SD_STATE_READY;
hsd->Context = SD_CONTEXT_NONE;
#if (USE_HAL_SD_REGISTER_CALLBACKS == 1)
hsd->TxCpltCallback(hsd);
#else
HAL_SD_TxCpltCallback(hsd);
#endif
}
then writes are working.
However is this the proper solution?
Many thanks,
Ollie
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-06-17 12:53 AM
Hi @I.KHACHINE
Apologies for the (very long) delay in a reply...
Here's the SD DMA init from the sdio.c that CubeMX generates:
/* SDIO DMA Init */
/* SDIO_RX Init */
hdma_sdio_rx.Instance = DMA2_Stream3;
hdma_sdio_rx.Init.Channel = DMA_CHANNEL_4;
hdma_sdio_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_sdio_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sdio_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_sdio_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sdio_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sdio_rx.Init.Mode = DMA_PFCTRL;
hdma_sdio_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_sdio_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_sdio_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sdio_rx.Init.MemBurst = DMA_MBURST_INC4;
hdma_sdio_rx.Init.PeriphBurst = DMA_PBURST_INC4;
if (HAL_DMA_Init(&hdma_sdio_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(sdHandle,hdmarx,hdma_sdio_rx);
/* SDIO_TX Init */
hdma_sdio_tx.Instance = DMA2_Stream6;
hdma_sdio_tx.Init.Channel = DMA_CHANNEL_4;
hdma_sdio_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_sdio_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sdio_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_sdio_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sdio_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sdio_tx.Init.Mode = DMA_PFCTRL;
hdma_sdio_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_sdio_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_sdio_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sdio_tx.Init.MemBurst = DMA_MBURST_INC4;
hdma_sdio_tx.Init.PeriphBurst = DMA_PBURST_INC4;
if (HAL_DMA_Init(&hdma_sdio_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(sdHandle,hdmatx,hdma_sdio_tx);
I've just updated the code to the latest I have on CubeIDE 1.15.1, which is STM32F4 MCU package 1.28.0 (previously 1.27.1) and FATFs R0.12c. The SD_DMATransmitCplt() function still looks a bit bare. I've had other issues on the project (with a lithium battery power path / charger IC misbehaving and randomly powering on when it should be off), so it's been back burner for a while.
@OTedd.1, I'll reload the new MCU package onto the dev board, and see if I can get a better solution - Maybe we can get a proper fix in place.
Is it possible to submit changes / pull requests to ST's GIT repo to include a fix?