[DONE] Issue with SDIO Hal(for STM32) in chibios 2.6.1
Posted: Thu Dec 05, 2013 5:45 am
While working on a custom STM32F4 based board we encountered some issues with timings in SDIO HAL. SDIO is used in IO mode so small changes were required to enable CMD52 and 53. Everything seemed to work fine at low SDIO clock settings (up to 3MHz) but at higher clocks SDIO Controller started returning CRC fail error.
After debugging we found the issue in function "sdc_lld_read_aligned" in sdc_lld.c. Here is details of problems and possible fix.
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?
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?