cancel
Showing results for 
Search instead for 
Did you mean: 

DMA to external SRAM misses bytes part-way through transfer

Danish1
Lead II

I have a stm32f427 with 1Mx16 external SRAM and SDMMC.

I am reading the SDMMC by DMA into the SRAM in two blocks of 512 bytes into a 1024 byte buffer.

The SRAM is mapped from 0x64000000 - 0x641fffff. Address and data are not multiplexed

I have now discovered that if I set the start of the buffer to 0x64033c98, the 8 bytes from 0x64034000 to 0x64034007 never get updated. Everything else is rock-solid and correct including all the way up to 0x64034097.

The processor is clocked at 144 MHz.

I set up the FMC with:

    FMC_Bank1->BTCR[0] &= ~FMC_BCR1_MBKEN;  // Bank 1 SRAM 1 enabled by default but we use Bank 1 SRAM 2
    FMC_Bank1->BTCR[2] = (FMC_Bank1->BTCR[2] & 0xffe70080) | FMC_BCR2_WREN | FMC_BCR2_MWID_0 * 1 | FMC_BCR2_MBKEN;
    FMC_Bank1->BTCR[3] = FMC_BTR2_CLKDIV_0 * 1 | FMC_BTR2_DATAST_0 * 2 | FMC_BTR2_ADDHLD_0 * 1 | FMC_BTR2_ADDSET_0 * 1; // reliable at 144 MHz

The fact that the missed bytes are aligned to the FMC address makes me think the problem lies at the FMC end rather than the SDMMC end. I don't see anything specific in the errata. Any thoughts as to what I might be doing wrong?

I don't have a logic-analyser to see if that particular write is ever requested, but if I probe random address and data lines with an oscilloscope everything looks good.

My current workaround is to DMA it to internal RAM and then use the processor to copy the words to external RAM; that seems to work, but internal RAM is tight and I don't like to waste cycles!

Thanks for your attention,

Danish

1 ACCEPTED SOLUTION

Accepted Solutions
Danish1
Lead II

I think I have found out why it was failing. The buffer I was reading-to was not aligned on a 16-byte boundary - it was only aligned on an 8-byte boundary.

All other buffers in my code are aligned to 16-byte boundaries, and changing that restores correct behaviour.

I think I read about that somewhere in the documentation. I would expect it to be in the Reference Manual.

There is mention in the section on DMA 10.3.11 that when burst transfers are used, the data must be aligned to the size of the transfer and a burst bust not cross a 1k boundary. And I had set bursts of 4 transfers:

DMA2_Stream3->dmaCR = 0/* | double-buffer - not yet */
        | DMA_SxCR_PFCTRL   /* let the SDIO peripheral say when everything is transferred */
        | DMA_SxCR_MBURST_0 | DMA_SxCR_PBURST_0     /* bursts of 4 transfers */
        | DMA_SxCR_PL_0
        | DMA_SxCR_MSIZE_1 | DMA_SxCR_PSIZE_1 | DMA_SxCR_MINC | DMA_SxCR_TCIE | DMA_SxCR_TEIE;

So problem solved. Thanks for anyone who looked.

View solution in original post

2 REPLIES 2
Danish1
Lead II

I think I have found out why it was failing. The buffer I was reading-to was not aligned on a 16-byte boundary - it was only aligned on an 8-byte boundary.

All other buffers in my code are aligned to 16-byte boundaries, and changing that restores correct behaviour.

I think I read about that somewhere in the documentation. I would expect it to be in the Reference Manual.

There is mention in the section on DMA 10.3.11 that when burst transfers are used, the data must be aligned to the size of the transfer and a burst bust not cross a 1k boundary. And I had set bursts of 4 transfers:

DMA2_Stream3->dmaCR = 0/* | double-buffer - not yet */
        | DMA_SxCR_PFCTRL   /* let the SDIO peripheral say when everything is transferred */
        | DMA_SxCR_MBURST_0 | DMA_SxCR_PBURST_0     /* bursts of 4 transfers */
        | DMA_SxCR_PL_0
        | DMA_SxCR_MSIZE_1 | DMA_SxCR_PSIZE_1 | DMA_SxCR_MINC | DMA_SxCR_TCIE | DMA_SxCR_TEIE;

So problem solved. Thanks for anyone who looked.

I'm glad to know that your issue is solved 😊 I marked your post as Best Answer.

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen