2021-09-30 07:51 AM
Hi,
I am trying to write, read and erase properly on a 4 GB Insignis EMMC (NSEC53K004-IT/-AT) with up to 250 MB/s read and 14 MB/s write.
I currently use the STM32Cube FW_H7 V1.9.0 and am unsure regarding the adjustments that need to be done to the generated code, as there have been fixes to described issues that I found here in the forums in other threads.
(where a DTMODE adjustment is described for DDR)
Would that still be necessary? The mode 3 still is not officially defined.
// in stm32h753xx.h
#define SDMMC_DCTRL_DTMODE_2 (0x3U << SDMMC_DCTRL_DTMODE_Pos)
//in stm32h7xx_ll_sdmmc.h
#define SDMMC_TRANSFER_MODE_BLOCK_STOP SDMMC_DCTRL_DTMODE_2
// in stm32h7xx_hal_mmc.c
// in read/write dma function set transfermode to:
config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK_STOP;
I am also unaware what is the current situation with this remark from the thread, as I don't see the call in with the current V1.9.0
Same as you, I noticed that the cmd16(SDMMC_CmdBlockLength()) in the write/read function must be put in an IF statement to be ignored if we are in DDR mode.
The 4 data pins in Cube IDE are configured for alternative push-pull and the global interrupt is enabled as well as hardware flow control. Rising transition and not power save for the CLK.
The only adjustment I made was this one in the MCC_InitCard() function, as the HAL_MMC_Init() call from the main now includes the HAL_MMC_ConfigWideBusOperation() call and it would not configure for DDR without these set bit calls.
/* Configure the SDMMC peripheral */
Init = hmmc->Init;
Init.BusWide = SDMMC_BUS_WIDE_1B;
(void)SDMMC_Init(hmmc->Instance, Init);
SET_BIT((hmmc)->Instance->CLKCR, SDMMC_CLKCR_DDR);
SET_BIT((hmmc)->Instance->CLKCR, SDMMC_CLKCR_BUSSPEED);
/* All cards are initialized */
return HAL_MMC_ERROR_NONE;
Writing seems to work, but is not faster than using 1-bit and default speed, I am very far away from 14 MB/s and therefore assume that DDR is not working at all. The CLK is set to 50 MHz, but I also tried 25 MHz using the EMMC CLK divider or setting it to 0.
Reading does not work, as even with single block reading, I get a busy response from the DMA Read function. My test code is as follows:
Interations refer to the block intertions to be written. I tested for 1 block writes and 8 block writes (4kB). MX_SDMMC2_MMC_Init() has been called.
for (int iteration = 0; iteration < iterations; iteration++) {
errorState = HAL_MMC_WriteBlocks_DMA(&hmmc2, wData, blockCount, blocksPerWrite);
while (HAL_MMC_GetCardState(&hmmc2) != HAL_MMC_CARD_TRANSFER) {
HAL_Delay(1);
}
if(errorState != 0){
HAL_Delay(50);
}
errorState = HAL_MMC_ReadBlocks_DMA(&hmmc2, rData, blockCount, blocksPerWrite);
while (HAL_MMC_GetCardState(&hmmc2) != HAL_MMC_CARD_TRANSFER) {
HAL_Delay(1);
}
if (memcmp(wData, rData, bytesPerWrite) == 0) {
status = 0;
}
else {
status = 1;
}
blockCount += blocksPerWrite;
}
I reckon that I need to implement HAL_MMC_RxCpltCallback to avoid timeout, but would this help with the DMA being busy?
Can somebody tell me what might be the issue here and which adjustments would be necessary to get the DDR up and running using DMA or even without it?
Best regards
2025-01-22 02:49 AM
I see the same happening on STM32H745I-Disco. Setting DDR mode in ConfigSpeedBusOperation will first try and set HighSpeed, which sets the ClockDiv from 8 to 2.
In MMC_HighSpeed(..):
sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC); // = 200 MHz
// and a few lines later:
Init.ClockDiv = (sdmmc_clk / (2U * MMC_HIGH_SPEED_FREQ)) + 1U; // = 2
Then, if successful, it will call MMC_DDR_Mode, which calls PwrClassUpdate, which calls MMC_ReadExtCSD.
It seems that MMC_ReadExtCSD does not work at this higher speed. Changing the ClockDiv back to 8 in the debugger, I can successfully initialize in DDR mode.
MMC_DDR_Mode does not set the ClockDiv like MMC_HighSpeed does, so that also needs to be added.
I might raise an issue/PR on github after I've fixed it for myself.