2022-09-23 02:25 PM
From the example available at
I figured out how to configure SDMMC1 using STM32CubeIDE.
I set the clock for MMC for 200MHz, then set up the MMC clock divider to 2. It's identical like in the example.
I run MX_SDMMC1_MMC_Init(); and it completes without errors.
Then I run following code:
void MMCFormat()
{
debug("Formatting MMC...");
static TCHAR workBuffer[_MAX_SS];
FRESULT fr = f_mkfs(MMCPath, FM_EXFAT, 0, workBuffer, sizeof(workBuffer));
if (fr == FR_OK)
debug("eMMC formatted successfully.");
else
debug("ERROR: eMMC f_mkfs().");
}
That makes the MMC_write() function to fail with TX buffer underrun error.
Here's the original function from mmc_diskio.c file:
DRESULT MMC_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
{
DRESULT res = RES_ERROR;
WriteStatus = 0;
/*
* since the MPU is configured as write-through, see main.c file, there isn't any need
* to maintain the cache as its content is always coherent with the memory.
* If needed, check the file "Middlewares/Third_Party/FatFs/src/drivers/sd_diskio_dma_template.c"
* to see how the cache is maintained during the write operations.
*/
while (HAL_HSEM_FastTake(EMMC_HSEM_ID) != HAL_OK)
{
}
if(BSP_MMC_WriteBlocks(0, (uint32_t*)buff,
(uint32_t)(sector),
count) == BSP_ERROR_NONE)
{
while(BSP_MMC_GetCardState(0) != BSP_ERROR_NONE)
{
}
res = RES_OK;
}
HAL_HSEM_Release(EMMC_HSEM_ID, 0);
if (res != 0)
{
debug("ERROR: MMC_write().");
}
return res;
}
As I read the BSP_MMC_WriteBlocks() function is unreliable, it gets buffer underrun errors, so I replaced it with BSP_MMC_WriteBlocks_DMA().
Then the interesting thing happens, the first call passes, but another one fails on following check:
if (hmmc->State == HAL_MMC_STATE_READY)
The state is HAL_MMC_STATE_BUSY.
Why is that? Where to go from there?
UPDATE:
I've done something completely silly! I overwritten the hmmc->State with HAL_MMC_STATE_READY. Just like that, just look at the MMC_write() function:
DRESULT MMC_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
{
DRESULT res = RES_ERROR;
WriteStatus = 0;
/*
* since the MPU is configured as write-through, see main.c file, there isn't any need
* to maintain the cache as its content is always coherent with the memory.
* If needed, check the file "Middlewares/Third_Party/FatFs/src/drivers/sd_diskio_dma_template.c"
* to see how the cache is maintained during the write operations.
*/
while (HAL_HSEM_FastTake(EMMC_HSEM_ID) != HAL_OK)
{
}
// while (hsd_sdmmc[0].State == HAL_MMC_STATE_BUSY) { osDelay(1); }
hsd_sdmmc[0].State = HAL_MMC_STATE_READY;
if(BSP_MMC_WriteBlocks_DMA(0, (uint32_t*)buff,
(uint32_t)(sector),
count) == BSP_ERROR_NONE)
{
while(BSP_MMC_GetCardState(0) != BSP_ERROR_NONE)
{
}
res = RES_OK;
}
HAL_HSEM_Release(EMMC_HSEM_ID, 0);
if (res != 0)
{
debug("ERROR: MMC_write().");
}
return res;
}
Of course I've changed also the MMC_read function accordingly.
f_disk() passes. But well, f_mount() returns FR_NO_FILESYSTEM then. Still not there.
2022-09-24 02:10 PM
OK, I've solved the case.
Here are steps to make it work:
Of course it's valid only when using RTOS, that is a default option for TouchGFX and that board. The FatFS functions are available when RTOS kernel is running, I mount the eMMC FS in RTOS task. I mounted actually 2 file systems, to access the files I need to provide full path, like "0:/file.dat" or "1:/file.dat", because when I used the file name alone it looked for it on wrong file system (USB disk that was not present at the time).
Parts I missed that costed me over 100 hours of banging my head against the wall:
When f_mount() or f_mkfs() is called, the first function in the driver that is called is MMC_initialize(). The template has DISABLE_MMC_INIT macro to skip internal initialization. That is crucial when the SDMMC1 is already initialized in main(). This macro MUST be defined. On MMC_initialize() only HAL_MMC_GetCardState() should be called.