cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F7 SDMMC ignores eMMC's response to READ_SINGLE_BLOCK

David Littell
Senior III

MCU: STM32F777

Cube: 4.25.0

FW: v1.11.0

I'm seeing cases where the F7's SDMMC isn't setting any of the required Status Register bits as the result of

an R1 response to a READ_SINGLE_BLOCK command after having previously handled up to tens of thousands of

identical sequences. The SDMMC_GetCmdResp1() function in stm32f7xx_ll_sdmmc.c waits (with a sad excuse for a

timeout loop) for (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT) to appear in SDMMC_STA.

Aside from a belt & suspenders & duct tape & sandwich board problem-detection approach the SDMMC_GetCmdResp1()

timeout loop should never time out given that, at the very least, SDMMC_FLAG_CTIMEOUT must be asserted after 64

MMC clocks (according to RM0410 Section 39.3.1 and 39.8.11 Bit 2 CTIMEOUT description). And yet the sad

timeout loop does indeed pop.

Attached is a screenshot of a logic analyzer trace showing a CMD17/READ_SINGLE_BLOCK command to an eMMC device

along with its R1 response. The logic analyzer's trigger was SDMMC_GetCmdResp1()'s timeout. There's no MMC

command/response traffic between the R1 response and the trigger, so all interaction with the eMMC stopped

because the impossible happened: there's obviously a response from the eMMC but no indication of any sort made

its way to the SDMMC Status Register. If I understand things correctly, one of the three indications in the

SDMMC Status Register (SDMMC_STA) (CCRCFAIL, CTIMEOUT, and CMDREND) *must* be asserted within 65+48 MMC clocks

after the command is sent.

After SDMMC_GetCmdResp1()'s timeout the SDMMC_RESPCMD contains 0x11, indicating that the SDMMC did indeed

receive the response to the CMD17. The SDMMC seems to have just forgotten to set a Status Register bit.

Examined with an oscilloscope, both the eMMC's CMD and CLK signals look good from a signal integrity

standpoint. No power or noise problems have been noted on any boards. Further, this problem has been observed

on multiple boards, with eMMC's from multiple manufacturers, at different MMC clock rates, and at wildly

variable times while the tests are running.

Thanks,

Dave

18 REPLIES 18

There is a newer version of the library. There is on going evolution of the code as the try to unify the code across platforms. Seem to recall some of the if/then/else/die constructs being cleaned up a bit. Sorry I can't be more specific I've edited/viewed these files across a dozen releases through the prism of a merge tool.

You might want to compare/contrast the SD and MMC forks and see if they handle the bits differently.

I've opted to use the SD fork, and selectively compile in eMMC routines/commands at the handful of places they diverge. Some of the MMC releases don't deal with cards >2GB properly.

I have done GB's of reading/writing, although almost everything >1 sector at a time.

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

I spent some quality time with merge comparing F7's FW 1.11.0, 1.12.0, and the SD versus MMC forks. They're all the same with respect to the described problem, which is encouraging as I don't see that the code is doing anything wrong. The problem is bits that must be set by the SDMMC after receiving an R1 response aren't. The code is just sitting and polling for the bits until SDMMC_CMDTIMEOUT is reached, which cannot happen according to the Reference Manual and all the MMC spec information I can find.

Additional instrumentation in the code and more testing today showed that this behavior isn't isolated to READ_SINGLE_BLOCK. The block writes as well as SEND_STATUS and SET_BLOCKLEN all have been seen to have their R1 responses ignored by the SDMMC.

Is hardware flow control enabled? Seen issues with that on one of the platforms.

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

Yeah, we saw some problems before enabling flow control as well.

Clock Bypass: enabled (24 MHz MMC clock rate) but the problem still occurs at 48 MHz

Power Saving: disabled

Bus Width: 8 bits

Hardware Flow Control: enabled

mrmichaelblack
Associate II

Do you happen to be using an RTOS and the SDIO in DMA mode? I've just solved what I believe is the same problem in the STM32F4 HAL drivers.

The problem presents itself when an RTOS context switch happens AFTER SDIO_SendCommand() is called (which begins to clock out the CMD), but before the SDMMC_FLAG_CMDREND flag is set. If a task context switch happens at this time, and does not return to the current task before SD_DMAReceiveCplt() is called, the SDMMC_FLAG_CMDREND is cleared, and never "noticed" by the SDMMC_GetCmdResp1() timeout loop.

In the attached Saleae Logic capture:

ERROR is low after an SDIO timeout occurs.

SDIO wait_loop is low when entering the waiting loop in SDMMC_GetCmdResp1(), high when exiting

ClearSDIOFlags is low then high whenever the SDIO flags are cleared.

SD_CMD is the SDIO CMD line

SD_D0 is the SD_D0 line

PJ11 goes low then high each time the loop in SDMMC_GetCmdResp1() checks the flags in the loop.

When the error happens at the end of the capture, an RTOS context switch happens so the CPU executes another task shortly after SDIO_SendCommand() is called. The flags are not being checked at this point, and while they are properly set, they are eventually cleared by the SD_DMAReceiveCplt() ISR function before SDMMC_GetCmdResp1() ever gets back into the execution context.

Hope this helps.

Hi, can you share your solution? I have the same problem

maciek
Associate II

Hello guys. I am strugling with the same problem- random crashes/timeouts in SDMMC_GetCmdResp1 function. I am using FreeRTOS with DMA. Many people is reporting this bug around the forum, for example:

https://community.st.com/s/question/0D50X00009XkeZ4SAJ/stm32l4-sdmmc-command-timeout

Funny thing is that the OP of this topic describes the problem in the same way @mrmichaelblack​  is. He even finds a solution. But it does not work on F7 sadly.

@Community member​ 

Is there any chance the driver is fixed in near future?

I don't work for ST

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

Guys, sorry for the delay and the poor effort at a proper response, I'm traveling, but I think you'll get the idea.

My "workaround" was to add a flag in stm32f4xx_ll_sdmmc.c and check for that flag in the do/while loop of SDMMC_GetCmdResp1 function.

//FLAG AND SETTER

static uint32_t cmdRespStatus = 0;

void SDMMC_SetCmdResponseStatus() {

   cmdRespStatus = 1U;

}

//MODIFIED GETCMDRESP1

static uint32_t SDMMC_GetCmdResp1(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint32_t Timeout)

{

 uint32_t response_r1;

 /* 8 is the number of required instructions cycles for the below loop statement.

 The Timeout is expressed in ms */

 register uint32_t count = Timeout * (SystemCoreClock / 8U /1000U);

 do

 {

    if (count-- == 0U)

    {

       return SDMMC_ERROR_TIMEOUT;

    }

 }while((!__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) && (!cmdRespStatus)); //<<Workaround

Then set the flag in the SD_DMAReceiveCplt ISR callback function in stm32f4xx_hal_sd.c :

 /* Clear all the static flags */

 SDMMC_SetCmdResponseStatus(); //<<workaround

 __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);

This way whenever the RTOS switches it's context back to the do/while loop in SDMMC_GetCmdResp1 it will catch that the flag is set and exit properly.