After debugging we found the issue in function "sdc_lld_read_aligned" in sdc_lld.c. Here is details of problems and possible fix.
Code: Select all
bool_t sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk,
uint8_t *buf, uint32_t n) {
uint32_t resp[1];
chDbgCheck((n < (0x1000000 / MMCSD_BLOCK_SIZE)), "max transaction size");
SDIO->DTIMER = STM32_SDC_READ_TIMEOUT;
/* Checks for errors and waits for the card to be ready for reading.*/
if (_sdc_wait_for_transfer_state(sdcp))
return CH_FAILED;
/* Prepares the DMA channel for writing.*/
dmaStreamSetMemory0(sdcp->dma, buf);
dmaStreamSetTransactionSize(sdcp->dma,
(n * MMCSD_BLOCK_SIZE) / sizeof (uint32_t));
dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_P2M);
dmaStreamEnable(sdcp->dma);
/* Setting up data transfer.*/
SDIO->ICR = STM32_SDIO_ICR_ALL_FLAGS;
SDIO->MASK = SDIO_MASK_DCRCFAILIE |
SDIO_MASK_DTIMEOUTIE |
SDIO_MASK_STBITERRIE |
SDIO_MASK_RXOVERRIE |
SDIO_MASK_DATAENDIE;
SDIO->DLEN = n * MMCSD_BLOCK_SIZE;
/* Talk to card what we want from it.*/
if (sdc_lld_prepare_read(sdcp, startblk, n, resp) == TRUE)
goto error;
/* Transaction starts just after DTEN bit setting.*/
SDIO->DCTRL = SDIO_DCTRL_DTDIR |
SDIO_DCTRL_DBLOCKSIZE_3 |
SDIO_DCTRL_DBLOCKSIZE_0 |
SDIO_DCTRL_DMAEN |
SDIO_DCTRL_DTEN;
if (sdc_lld_wait_transaction_end(sdcp, n, resp) == TRUE)
goto error;
return CH_SUCCESS;
error:
sdc_lld_error_cleanup(sdcp, n, resp);
return CH_FAILED;
}In function "sdc_lld_prepare_read" SDIO sends command to peripheral to start transfer and peripheral starts sending data but at this point SDIO DCTRL is not yet configured. So by the time SDIO is ready to receive some data, peripheral has already transferred some data which results in data mismatch and hence CRC error.
We fixed it by configuring SDIO->DCTRL before "sdc_lld_prepare_read " call and transfer is successful at higher clock setting. In case of SDIO write calls no change is required since data flow is controlled by host side.
Can someone confirm that above fix works fine in case of SD cards/MMC does not cause any other issue and can we get a fix for this in subsequent ChibiOS release?
Later i found that in earlier versions of chibi(2.4.3) SDIO MASK and DCTRL registers were configured before sending read command to peripheral which should be the correct way. Was it changed due to some other issues in SDIO?