cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F427 SDIO Block Write with DMA not responding properly

Joe.H
Senior

0690X000008wPbiQAE.png

0690X000008wPbsQAE.png

0690X000008wPbxQAE.png

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

  1. Stream6 NDTR is 0xff82 which suggests to me it pushed more data than the 128 transactions it was instructed to transfer (I'm of the belief that DMA_HISR_TCIF6 fires when NDTR == 0) -- see picture below
  2. SDIO DCOUNT is 0x000c - which says it expects 12 more bytes. It's loaded based on the Block size of 512 and then counts down as data is transferred.-- see picture below
  3. SDIO FIFOCNT is zero so all data has been transferred. -- see picture below

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;
  
}

5 REPLIES 5

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

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

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.

Joe.H
Senior

Can anyone share some light on the following:

  1. DMA NDTR set to 128 transactions - why is the NDTR register at 0xfff8 when the end of transfer interrupt fires? To me - that says the DMA made 255 transactions (128 count down to zero and then another 127 to get to 0xff8).
  2. If the DMA made the 128 transactions (128 32-bit words = 512 bytes) - why does the SDIO DCOUNT show 0xc which to me says it is waiting for 12 more bytes (or 3 more 32-bit transactions) to complete its Block Write?

Thanks.

I feel if I can understand the above two behaviors, I should be able to fix my issue.

AWied.1
Associate II

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

Joe.H
Senior

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.