Skip to main content
Konstantin Sachkov
Associate
April 14, 2018
Question

SDMMC STM32f7 - SDMMC_GetCmdResp1() gets stuck

  • April 14, 2018
  • 9 replies
  • 4622 views
Posted on April 14, 2018 at 23:13

Hey everyone,

My app based on STM32CubeF7 Firmware Package V1.11.0 / 23-February-2018 gets stuck in SDMMC_GetCmdResp1() during directory scan randomly - it can stuck just after switching on or after 2 minutes of working. I can do nothing with sd until I switch off and switch on SD power.

0690X0000060AXFQA2.png

I found a ''solution'' by adding delay:

uint32_t SDMMC_CmdSendStatus(SDMMC_TypeDef *SDMMCx, uint32_t Argument)

{

SDMMC_CmdInitTypeDef sdmmc_cmdinit;

uint32_t errorstate = SDMMC_ERROR_NONE;

sdmmc_cmdinit.Argument = (uint32_t)Argument;

sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEND_STATUS;

sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;

sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;

sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;

HAL_Delay(1);

SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);

/* Check for error conditions */

errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SEND_STATUS, SDMMC_CMDTIMEOUT);

return errorstate;

}

it works good, without any issues, but very slow.

The second solution is disabling all other FreeRTOS Tasks that use about 50% CPU.

How to make it work in real world?

UPDATE: I found that in some cases before timeout I get SDMMC_ERROR_CMD_CRC_FAIL

0690X0000060AarQAE.png

#sd #stm32f7 #dma-sdmmc #sdmmc
This topic has been closed for replies.

9 replies

Konstantin Sachkov
Associate
April 26, 2018
Posted on April 26, 2018 at 15:55

Eventually I found a solution on my own. It's strange, but not stranger than HAL libraries

Working code:

DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
{
 DRESULT res = RES_ERROR;
 osEvent event;
 uint32_t timer;
 uint32_t alignedAddr = (uint32_t)buff & ~0x1F;
if(count < 2)
{
if( BSP_SD_ReadBlocks((uint32_t*)buff,
(uint32_t) (sector),
count,SD_TIMEOUT) == MSD_OK)
timer = osKernelSysTick() + SD_TIMEOUT;
/* block until SDIO IP is ready or a timeout occur */
while(timer > osKernelSysTick())
{
 if (BSP_SD_GetCardState() == SD_TRANSFER_OK)
 {
res = RES_OK;
break;
 }
}
}
else
{
#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
 if((uint32_t)buff < 0x60000000 && (uint32_t)buff >= 0x20010000)
 {
 //buff not in uncacheable SDRAM or DTCMRAM
 alignedAddr = (uint32_t)buff & ~0x1F;
 //save data near the beginning and the end of a cache to RAM
 SCB_CleanDCache_by_Addr((uint32_t*)alignedAddr, 32);
 SCB_CleanDCache_by_Addr((uint32_t*)alignedAddr + count*BLOCKSIZE, 32);
 }
#endif
 //clean queue
 do{
 event = osMessageGet(SDQueueID, 0);
 }while(event.status == osEventMessage);
 if(BSP_SD_ReadBlocks_DMA((uint32_t*)buff,
(uint32_t) (sector),
count) == MSD_OK)
 {
/* wait for a message from the queue or a timeout */
event = osMessageGet(SDQueueID, SD_TIMEOUT);
if (event.status == osEventMessage)
{
 if (event.value.v == READ_CPLT_MSG)
 {
timer = osKernelSysTick() + SD_TIMEOUT;
/* block until SDIO IP is ready or a timeout occur */
while(timer > osKernelSysTick())
{
 if (BSP_SD_GetCardState() == SD_TRANSFER_OK)
 {
res = RES_OK;
#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
/*
 the SCB_InvalidateDCache_by_Addr() requires a 32-Byte aligned address,
 adjust the address and the D-Cache size to invalidate accordingly.
 */
if((uint32_t)buff < 0x60000000 && (uint32_t)buff >= 0x20010000)
{
//buff not in uncacheable SDRAM or DTCMRAM
SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr, count*BLOCKSIZE + ((uint32_t)buff - alignedAddr));
}
#endif
break;
 }
}
 }
}
 }
}
return res;
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

and

DRESULT SD_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
{
 DRESULT res = RES_ERROR;
 osEvent event;
 uint32_t timer;
#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
 uint32_t alignedAddr;
 /*
 the SCB_CleanDCache_by_Addr() requires a 32-Byte aligned address
 adjust the address and the D-Cache size to clean accordingly.
 */
 if((uint32_t)buff < 0x60000000 && (uint32_t)buff >= 0x20010000){
 alignedAddr = (uint32_t)buff & ~0x1F;
 SCB_CleanDCache_by_Addr((uint32_t*)alignedAddr, count*BLOCKSIZE + ((uint32_t)buff - alignedAddr));
 }
#endif
 if(count < 2)
 {
 if(BSP_SD_WriteBlocks((uint32_t*)buff,
 (uint32_t) (sector),
 count, SD_TIMEOUT) == MSD_OK)
 {
 uint32_t timer = osKernelSysTick() + SD_TIMEOUT;
 /* block until SDIO IP is ready or a timeout occur */
 while(timer > osKernelSysTick())
 {
 if (BSP_SD_GetCardState() == SD_TRANSFER_OK)
 {
 res = RES_OK;
 break;
 }
 }
 }
 }
 else
 {
 //clean queue
 do{
 event = osMessageGet(SDQueueID, 0);
 }while(event.status == osEventMessage);
 if(BSP_SD_WriteBlocks_DMA((uint32_t*)buff,
(uint32_t) (sector),
count) == MSD_OK)
 {
/* Get the message from the queue */
event = osMessageGet(SDQueueID, SD_TIMEOUT);
if (event.status == osEventMessage)
{
 if (event.value.v == WRITE_CPLT_MSG)
 {
timer = osKernelSysTick() + SD_TIMEOUT;
/* block until SDIO IP is ready or a timeout occur */
while(timer > osKernelSysTick())
{
 if (BSP_SD_GetCardState() == SD_TRANSFER_OK)
 {
res = RES_OK;
break;
 }
}
 }
}
 }
 }
 return res;
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

It works, not really perfectly, I get reading errors sometimes. Will update.

Alberto Mainoni
Visitor II
May 25, 2018
Posted on May 25, 2018 at 08:17

Hi Konstantin, I have the same problem, please did you find a definitive solution at he problem?

Beast regards

Konstantin Sachkov
Associate
May 27, 2018
Posted on May 27, 2018 at 20:28

Unfortunately, no. I've spent weeks and checked many solution with no success.

Jur Div
Associate II
July 15, 2018
Posted on July 15, 2018 at 18:01

I am trying to write an image to SD card and I have exactly the same error. Using STM32 F746 discovery, no RTOS. My program is based on the STM provided example STM32Cube_FW_F7_V1.11.0/Projects/STM32746G-Discovery/Applications/FatFs/FatFs_uSD.

The program was unstable, since I was receiving those sd underrun errors. I then tried reconfiguring the example to use DMA for reading/writing, but now I am getting stuck at the same point as original post here (SDMMC_GetCmdResp1() ).

I&39m a begginner and obviously I am not the only one struggling with this. I&39m really confused, since the DMA seems to be initialized correctly(?) in BSP_SD_MspInit() and I changed sd_diskio.c read and write functions from BSP_SD_ReadBlocks() to BSP_SD_ReadBlocks_DMA() (and the same for write). I also tried implementing test/empty IRQ callback, but the code never reaches them. Did I forget something obvious?

Turvey.Clive.002

  Would it be possible to get an working example with FatFS+SD card, no RTOS on STM32F746 discovery board?

Tesla DeLorean
Guru
July 15, 2018
Posted on July 15, 2018 at 19:08

Drop me an email at

mailto:sourcer32@gmail.com

I'll port the template over to V1.11.0
Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Jur Div
Associate II
July 16, 2018
206230CGIL3
Led
Associate III
August 15, 2024

Hi all,

Are there any solutions for the issue described here?

I face the same problem, getting SDMMC_ERROR_CMD_RSP_TIMEOUT in SDMMC_GetCmdResp1(). No matter whether I use DMA or not.

Goal of the application is to write sensor values to the uSD from my application and read the values via USB. I use Eclipse (Azure) ThreadX and FileX. I'm able to create files, but not writing into them.

However, accessing the uSD from USB with USBX works fine. I can write files, using the same SDIO functionality. (Assuring by my SW that not both (USBX and FileX) access SDIO at the same time).

Any help appreciated.
Denise