cancel
Showing results for 
Search instead for 
Did you mean: 

SDMMC STM32f7 - SDMMC_GetCmdResp1() gets stuck

Konstantin Sachkov
Associate II
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
8 REPLIES 8
Konstantin Sachkov
Associate II
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.

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

Posted on May 27, 2018 at 20:28

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

Posted on May 27, 2018 at 21:19

I'm not super keen on ST's cache manipulation code, if you put the data in the DTCM memory much of this can be avoided.

Failure in the SDMMC/FATFS tends to be cascading, and so where you notice it usually isn't the initial point of failure, FATFS particular ploughs forward, and much code ignores result codes. I would instrument the exit points of SD_read/SD_write so it outputs on failure, and then engages more verbose output moving forward.

osGetMessage seems to have no recovery path if it gets a different message, and this could result in an exit before completion, and subsequent operations will fail.

Writing tends to be a problem as the DMA complete before the FIFO clears.

The SDMMC also doesn't support concurrent operation, access needs to be serialized, and in the ST implementation this really means than all your SDMMC/FATFS operation needs to be constrained to a single thread.

The interface itself is robust, I can have loggers running for months, and they only stop when the card capacity is reached. Which typically for me is filling tens or hundreds of GB depend on the card. Also not had issues saturation testing were a write 200GB in a continuous stream of files, and then validate the read back of that data.

Using F7+DMA here, not using FreeRTOS+Cache Invalidation.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Jur Div
Associate II
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?

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
Up vote any posts that you find helpful, it shows what's working..
206230CGIL3
Posted on July 16, 2018 at 15:35

>WWD_IRQHandler triggers

More probably it goes to the Default_Handler at the same address, which suggests one of the other IRQ Handlers (or macro) doesn't bind properly into the Vector Table. Check the stm32746g_discovery_sd.h file settings and that stm32f7xx_it.c pulls the include files so the macros expand into real handler names. Check them in the .MAP.

Do you have something like Hyperterm or RealTerm?

I have versions running at 200 MHz and driving the screen, not used with DCMI

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..