2018-04-14 02:13 PM
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.
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
#sd #stm32f7 #dma-sdmmc #sdmmc2018-04-26 06:55 AM
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.
2018-05-25 01:17 AM
Hi Konstantin, I have the same problem, please did you find a definitive solution at he problem?
Beast regards
2018-05-27 01:28 PM
Unfortunately, no. I've spent weeks and checked many solution with no success.
2018-05-27 02:19 PM
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.
2018-07-15 09:01 AM
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?2018-07-15 12:08 PM
Drop me an email at
mailto:sourcer32@gmail.com
I'll port the template over to V1.11.02018-07-16 05:26 AM
2018-07-16 08:35 AM
>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
2024-08-15 10:23 AM
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