2024-11-12 08:50 AM
Hello,
I'm migrating the code from stm32f4 to stm32h7 and stuck with SDMMC ACMD51 command. This command reads SD configuration register via data lines (8 bytes total).
Is there is any way to configure this request to set DBCKCEND flag when it receives all bytes? Or FIFO flags polling only the way?
Here is my attempt to do it:
#define SDIO SDMMC1
#define SD_ACMD51 51|SDMMC_RESPONSE_SHORT|SDMMC_WAIT_NO|SDMMC_CPSM_ENABLE|SDMMC_CMDTRANS
SDIO->DTIMER = 0xFFFFFF;
SDIO->DLEN = 8;
SDIO->DCTRL = SDMMC_DCTRL_RWSTART|(3<<SDMMC_DCTRL_DBLOCKSIZE_Pos)|SDMMC_DCTRL_DTDIR;
result= sdio_send_acmd_blocking(SD_ACMD51, 0);
if(result!=0) return result;
result = wait_for_sd_data_ready(); //waiting for DBCKCEND interrupt
2024-11-14 08:13 AM
So, I found a solution by using IDMA:
SDIO->ICR= SDMMC_ICR_DATAENDC;
//32 bytes minimum burst, but if DLEN < 32 bytes it will only transfer DLEN bytes
//see page 2408 of RM0433
SDIO->IDMABSIZE = 1<<5;
SDIO->IDMABASE0 = (size_t)&SDIO_m.SCR[0].word;
SDIO->IDMACTRL = SDMMC_IDMA_IDMAEN;
SDIO->DLEN = 8;
SDIO->DCTRL = (3<<4)|(1<<1);
// need to set CMDTRANS bit that after this command
//it will enable Data Path State Machine
result= sdio_send_acmd_blocking(SD_ACMD51|SDMMC_CMD_CMDTRANS, 0);
if(result!=0)
return result;
if((SDIO_m.sdio_last_status)&SDIO_ERR_FLAGS)
return ((SDIO_m.sdio_last_status)&SDIO_ERR_FLAGS);
SDIO->MASK |= SDMMC_MASK_DATAENDIE;
result = wait_for_sd_data_ready(); //waiting for DATAEND interrupt
SDIO->IDMACTRL = 0;
SDIO->MASK &= ~SDMMC_MASK_DATAENDIE;
if((SDIO_m.sdio_last_status)&SDIO_ERR_FLAGS)
return ((SDIO_m.sdio_last_status)&SDIO_ERR_FLAGS);
SDIO_m.SCR[1].word = __REV(SDIO_m.SCR[1].word);
SDIO_m.SCR[0].word = __REV(SDIO_m.SCR[0].word);
swap_words(&SDIO_m.SCR[0].word);
Data transfer end will rise DATAEND flag.