2021-04-19 12:45 AM
Hello!
I am using STM32-NUCLEO-F412ZG board. I want to use SDIO (only IO) functionality as host.
I am able to init, read, write to SDIO peripheral using polling.
Before asking question let me give some background of implementation,
int STM32WriteData(uint8_t func, uint32_t addr, const void *data, uint32_t len)
{
int i, err = 0;
uint32_t size = len;
uint16_t block_num = 0;
static SDIO_DataInitTypeDef sdio_data = {0};
uint32_t cmd53_flags = CMD53_WRITE /*BIT(31)*/;
/* Data timeout is kept sufficiently high
* */
sdio_data.DataTimeOut = SDMMC_DATATIMEOUT;
const uint32_t *p = data;
if ((uintptr_t)data & 3)
{
printf("%s: data must be 4-byte aligned!\n\r", __FUNCTION__);
return STM_FAIL_ALIGNMENT;
}
if (size == 0)
{
printf("%s: size cannot be 0!\n\r", __FUNCTION__);
return STM_FAIL_INVALID_ARG;
}
block_num = GetBlockNum(func, &size, 1, &sdio_data);
cmd53_flags |= CMD53_INCREMENTING /*BIT(26)*/;
SDIO->DCTRL = 0;
do {
if (block_num)
{
sdio_data.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
SendCMD53(func, addr, block_num, cmd53_flags | CMD53_BLOCKMODE/*BIT(27)*/);
}
else
{
sdio_data.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
SendCMD53(func, addr, size, cmd53_flags);
}
} while(WaitForResponse(__FUNCTION__,__LINE__));
/* Wait untill D0 pin is low
* */
while((uint32_t)HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_8) == (uint32_t)RESET);
sdio_data.DataLength = size;
sdio_data.DPSM = SDIO_DPSM_ENABLE;
sdio_data.TransferDir = SDIO_TRANSFER_DIR_TO_CARD;
SDIO_ConfigData(SDIO, &sdio_data);
while (size > 0)
{
while (__SDIO_GET_FLAG(SDIO, SDIO_FLAG_TXFIFOF) != RESET);
size -= 4;
/* Write 4 bytes to FIFO */
SDIO_WriteFIFO(SDIO, (uint32_t *)p);
p++;
/* Wait untill there is space in FIFO */
err += CheckError(__FUNCTION__,__LINE__);
if (err) {
break;
}
}
// commenting below line as ut some times get stuck in loop
//while (__SDIO_GET_FLAG(SDIO, SDIO_FLAG_TXACT) != RESET);
i = 0;
while (1)
{
if ((__SDIO_GET_FLAG(SDIO, SDIO_FLAG_DATAEND)) ||
(__SDIO_GET_FLAG(SDIO, SDIO_FLAG_DBCKEND)))
break;
err += CheckError(__FUNCTION__,__LINE__);
if (err) {
break;
}
i++;
if (i == CMD53_TIMEOUT /*10000000*/)
{
printf("%s: timeout!\n\r", __FUNCTION__);
err++;
break;
}
}
sdio_data.DPSM = SDIO_DPSM_DISABLE;
SDIO_ConfigData(SDIO, &sdio_data);
__SDIO_CLEAR_FLAG(SDIO, SDIO_FLAG_DATAEND | SDIO_FLAG_DBCKEND);
SDIO->DCTRL = SDIO_DCTRL_DTEN | SDIO_DCTRL_RWSTART | \
SDIO_DCTRL_SDIOEN | SDIO_DCTRL_DTDIR;
err += CheckError(__FUNCTION__,__LINE__);
if (err != 0) {
return STM_FAIL;
}
return STM_OK;
}
Question
After some rounds of read, writes I am stuck in below issues -
Reading CRC when failed, is not fatal but when write CRC error happens, SDIO hardware seem to go in non working state, from which I am not able to recover.
Additional info -
I had gone through the reference manual RM0402 rev 6 , which says the FIFO runs over PCLK2 and PLCK2 should abide,
PCLK2 > ((3*Width) /32) * SDIO_CK
i.e.
100MHz > (3*4/32)*25MHz
I had called `SDIO_Init` with SDIO_INIT_CLK_DIV = ((uint8_t)0x76 while doing initialisation and again for data operations as well (What I meant here is, even though SDIO clock in clock config is 25MHz, I am using very small clock to do init and later operations).
2021-04-20 02:21 AM
Anyone faced similar kind of problem?