2019-05-26 02:15 PM
I don't use libraries.
My SD card interface is set up with an SDIO clock of 16.67 mhz using the 4-bit interface.
My block write (SD command 24) works properly if I poll the data into the FIFO. The problem with that is the timing to push data into the FIFO and not get an TX underrun is very tight. An RTOS time tic can cause enough of a delay produce the error. I had to disable all interrupts before pushing the 512 bytes (128 32-bit writes) into the FIFO to remove all possibilities of the fault.
So -- use DMA.
The STM32F427 manual outlines the requirements for Master Write with DMA which I believe I have implemented properly.
The DMA fires at the end of the transaction but the SDIO does not reply with an SDIO_STA_DBCKEND flag and my timeout process aborts the write.
I'm using DMA2 Stream 6 channel 4.
Upon receiving the DMA Stream interrupt with flag DMA_HISR_TCIF6 set I wait (poll) for the SDIO_STA_DBCKEND which never arrives.
Here is were I'm puzzled because the following are register values for the Stream and SDIO
My code is posted below. If someone can help identify what I'm doing incorrectly I would appreciate it. I also have pictures below of the DMA and SDIO register states and a trace of the SDIO CLK, CMD and Dat0 lines for the write process listed. The trace shows 2 commands. the first is a SDIO CMD 13 for status followed by SDIO CMD 24.
Thanks for and help/comments.
byte SDHC_WriteBlock(dword *pData, word Count)
{
dword r = 0;
volatile dword S;
dword TimeOut = H_GetTime() + (20000 / portTICK_PERIOD_MS);
dword TM;
DMA2->HIFCR = DMA_HIFCR_CFEIF6 | DMA_HIFCR_CDMEIF6 | DMA_HIFCR_CTEIF6 | DMA_HIFCR_CHTIF6 | DMA_HIFCR_CTCIF6;
DMA2_Stream6->CR = DMA_SxCR_TEIE | DMA_SxCR_TCIE | (1 << DMA_SxCR_DIR_Pos) | DMA_SxCR_MINC | DMA_SxCR_PFCTRL | (2 << DMA_SxCR_PSIZE_Pos) | (2 << DMA_SxCR_MSIZE_Pos) | (2 << DMA_SxCR_PL_Pos) | (1 << DMA_SxCR_MBURST_Pos) | (1 << DMA_SxCR_PBURST_Pos) | (4 << DMA_SxCR_CHSEL_Pos);
DMA2_Stream6->M0AR = (dword)pData;
DMA2_Stream6->PAR = (dword)&SDIO->FIFO;
DMA2_Stream6->NDTR = Count; // count is 128 ... 128 32bit words = 512 bytes
SDIO->DCTRL |= SDIO_DCTRL_DMAEN; // enable dma
SDHC_DMA_Complete_or_Error = 0; // flag from DMA IRQ
DMA2_Stream6->CR |= DMA_SxCR_EN; // start transfer
while(SDHC_DMA_Complete_or_Error == 0)
{
TM = H_GetTime();
if(TM >= TimeOut) //SD_Timeout_Event)
{
DMA2_Stream6->CR = 0; // kill dma
r = SDHC_Error_Timed_Out;
goto bye;
}
}
if(SDHC_DMA_Complete_or_Error == 2)
{
r = SDHC_DMA_Write_Error;
goto bye;
}
if(SDHC_DMA_SD_Status & (SDIO_STA_TXUNDERR | SDIO_STA_STBITERR | SDIO_STA_DCRCFAIL))
{
r = SDHC_Error_Write_Block_A;
goto bye;
}
bye:
// get here when DMA transaction complete if r == 0. If r then error
while(r == 0)
{
S = SDIO->STA;
if(S & (SDIO_STA_STBITERR | SDIO_STA_DCRCFAIL))
{
r = SDHC_Error_Write_Block_B;
break;
}
if(S & SDIO_STA_DBCKEND) //data end and valid checksum
{
r = 0;
break;
}
TM = H_GetTime();
if(TM >= TimeOut) //SD_Timeout_Event)
{
r = SDHC_Error_Timed_Out; // !!!!!!!!!!!!!!!!!!!!!!!! this is were I currently exit with error
break;
}
}
return r;
}
2019-05-26 02:28 PM
Viewing the FIFO in the debugger is likely to break things.
For the F427 make sure NOT to enable HW FLOW CONTROL
DMA will complete well before SDIO is complete, you should spin on FIFO count until EMPTY
2019-05-26 04:38 PM
Clive:
HW Flow is NOT enabled.
Viewing FIFO in debugger is only after 20 second timeout expired.
I'm spinning on SDIO_STA_DBCKEND which is well after FIFO count goes to zero.
Thanks for your comments but I don't think they identify the issue.
Thanks for your comments.
2019-05-27 09:34 AM
Can anyone share some light on the following:
Thanks.
I feel if I can understand the above two behaviors, I should be able to fix my issue.
2020-03-12 05:51 AM
Hello Joe,
I'm having exact the same problem with communicating per DMA to my SDIO. But the problem only appears very seldom.
For example DCOUNT is set to 0x200 so 512 Bytes and FIFOCNT is already down to zero.
I'm using a STM32F439 Board.
Could you please tell me how you solved your issue?
Best regards
2020-03-12 08:03 AM
I resolved it by NOT using DMA.
I spent many hours attempting to discover root-cause but found nothing.
Since writing to an SD card in my application was not real-time critical - I elected to use simple polling and it works great.