Skip to main content
Danish1
Lead III
January 27, 2021
Solved

DMA to external SRAM misses bytes part-way through transfer

  • January 27, 2021
  • 1 reply
  • 1934 views

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

This topic has been closed for replies.
Best answer by Danish1

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.

1 reply

Danish1
Danish1AuthorBest answer
Lead III
January 29, 2021

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.

Technical Moderator
January 29, 2021

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

Imen

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks