cancel
Showing results for 
Search instead for 
Did you mean: 

stm32F7 USART RX data not being stored in DMA buffer

Atay.Stefan
Associate II

Hello,

I am using an STM32F767 (nucleo board). I am trying to configure a DMA channel as a circular buffer for USART RX data. Unfortunately, the data never appear in the specified DMA buffer location. A few pieces of information:

  • I am using the low-level (LL) drivers exclusively.
  • I have successfully configured and used the USART2 and USART3 without DMA buffering, so I am confident in my pin configuration, and that the data I send to the USART is correct (I'm using a virtual comm port to send characters from a terminal program).
  • I encounter the same problem using both USART2 and USART3 with DMA.
  • I have confirmed that the DMAx_Streamy->NDTR counter is correctly decrementing with each byte that is received by the USART RX.
  • I have confirmed that something (presumably the DMA) is clearing the USART RXNE flag upon receipt of each byte.
  • I have directly read the contents of the USARTx->RDR register and confirmed that the correct data is present in the register - but this data never appears in the DMA buffer.
  • I have directly read the contents pointed to by DMAx_Streamy->M0AR to confirm that it is pointing to the correct buffer location. The data is never updated despite sending bytes to the USART RX
  • I have confirmed that the circular buffer is resetting DMAx_Streamy->NDTR upon roll-under and continues to decrement with each byte sent to the USART RX.
  • I programmed an SMT32F4 part with an identical USART and DMA configuration, and did not have any problems.

Here is my DMA configuration function:

void Config_USART2_DMA(void)
{	
    LL_DMA_InitTypeDef DMA_InitStruct;	
	
    // u2_rx_buf[] is the DMA buffer, preloaded 
    u2_rx_buf[0]='a';
    u2_rx_buf[1]='b';
    u2_rx_buf[2]='c';
    u2_rx_buf[3]='d';
	
    //Enable the clock of DMA1
    LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
 
    //USART2 RX DMA channel - DMA1, channel 4, stream 5 (RX)
    LL_DMA_StructInit(&DMA_InitStruct);
    DMA_InitStruct.Channel= LL_DMA_CHANNEL_4;
    DMA_InitStruct.Direction= LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
    DMA_InitStruct.FIFOMode= LL_DMA_FIFOMODE_DISABLE; 		
    DMA_InitStruct.FIFOThreshold = LL_DMA_FIFOTHRESHOLD_FULL; 	
    DMA_InitStruct.MemBurst= LL_DMA_MBURST_SINGLE; 
    DMA_InitStruct.MemoryOrM2MDstAddress 	= (uint32_t)u2_rx_buf;	
    DMA_InitStruct.MemoryOrM2MDstDataSize 	= LL_DMA_MDATAALIGN_BYTE;			
    DMA_InitStruct.MemoryOrM2MDstIncMode 	= LL_DMA_MEMORY_INCREMENT;	
    DMA_InitStruct.Mode= LL_DMA_MODE_CIRCULAR; 	
    DMA_InitStruct.NbData= 4; 		
    DMA_InitStruct.PeriphBurst = LL_DMA_PBURST_SINGLE; 	
    DMA_InitStruct.PeriphOrM2MSrcAddress 	= (uint32_t)&USART2->RDR;  
    DMA_InitStruct.PeriphOrM2MSrcDataSize 	= LL_DMA_PDATAALIGN_BYTE;	
    DMA_InitStruct.PeriphOrM2MSrcIncMode 	= LL_DMA_PERIPH_NOINCREMENT;	
    DMA_InitStruct.Priority = LL_DMA_PRIORITY_HIGH;	
 
    LL_DMA_Init(DMA1,LL_DMA_STREAM_5,&DMA_InitStruct);
	
    // Clear all DMA flags
    LL_DMA_ClearFlag_HT5(DMA1);
    LL_DMA_ClearFlag_TC5(DMA1);
    LL_DMA_ClearFlag_TE5(DMA1);
    LL_DMA_ClearFlag_DME5(DMA1);
    LL_DMA_ClearFlag_FE5(DMA1);
    LL_DMA_DisableIT_TC(DMA1, LL_DMA_STREAM_5);
	
    // Enable the DMA
    LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_5); 
 
    //Enable USART for DMA - tells USART to generate DMA request upon receiving data
    LL_USART_EnableDMAReq_RX(USART2); 
}
	

Anyone have any ideas, or run into similar problems? I also compared my code with a stm32cube example for configures the USART using DMA. I don't see any significant difference.

Lastly, I found a thread (FAQ: DMA is not working on STM32H7 devices) indicating that there is a memory/cache issue on the SMT32H parts... Any possibility this is an issue here as well?

I appreciate any helpful responses. Thank you!

8 REPLIES 8

Sounds like caching issue. Use a non-cached portion of RAM.

JW

Atay.Stefan
Associate II

Hi Jan,

Thanks for the quick reply! I am not familiar with how to control where in memory a particular variable resides. Is that something that you can describe briefly? If not, can you point me to a resource for how to control whether or not a variable is in cached RAM? Thanks for your help!

The linker typically controls where data is placed via a scatter file, linker script, or via GUI configurations. At the compiler level direction can be made via attribute or #pragma directives.

It could be a cache coherency or write-through issue. Grep through the example sources for DCache and MPU_Config reference to see how ST addresses/solves these issues. Familiarize yourself with the CM7 caching, buffering, sharing architecture.

https://www.st.com/content/ccc/resource/technical/document/programming_manual/group0/78/47/33/dd/30/37/4c/66/DM00237416/files/DM00237416.pdf/jcr:content/translations/en.DM00237416.pdf

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

Hi Clive,

Thanks for the suggestions, I'll check it out!

BShar
Associate II

Hi Nickname16298,

Did you find a solution to your problem? I have seen similar problem on my board; The problem did not go away when I disabled data cache.

Let's better define "similar problem", because if it is different, the causes might also be different.

Pay attention to what memory you're using. On the F7 the DTCM RAM will work a lot more favourably with DMA as the CPU will be looking at the same memory.

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

Clive Two.Zero,

Actually, my problem was exactly same as Nickname16298's.

BTW, can you please point me to any documentation that mentions how different SRAM blocks behave differently with respect to DMA? Especially if some SRAM is no no for DMA.

The Reference Manual shows the plumbing, caches and write buffers can cause coherency issues when you're not paying attention. You just have to become more self-aware, and make sure that when the processor-memory-DMA interact. You have to flush (clean) or invalidate the cache side copy.

Green square is tightly coupled memory, it is not cached (see south side of processor) because it is already fast, and you want to apply the cache resources to slower memory. The Dark Orange is the path the DMA data takes to the core, and the Light Orange is the path back to the memory.

0690X000006CBLUQA4.jpg

You can use the SRAM, you just have to manage it. Review the code here

STM32Cube_FW_F7_V1.12.0\Middlewares\Third_Party\FatFs\src\drivers\sd_diskio_dma_template.c

See ENABLE_SD_DMA_CACHE_MAINTENANCE code sections

The DTCMRAM is a finite resource, I'm suggesting it as a diagnostic test here to see if it addresses your symptoms, as it's simpler to understand compared to the clean/invalidate methods.

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