cancel
Showing results for 
Search instead for 
Did you mean: 

High Speed Memory array copy

VolterPhase
Associate

Hello,

 

I have implemented a high-speed USART @921600 baud rate with STM32f10x @72Mhz. I want to send 3000 Bytes to a slave MCU.

In slave MCU, I used USART DMA to read MSG[300]byte data collect the data, and copy them into a larger array(Data[3000]).

My problem is that when the first 300 bytes come from the USART and a DMA interrupt occurs, I don't have enough time to copy MSG[300] bytes to my larger array Data[3000] and if I use a memory-to-memory DMA, I am worried about the variable changing when the incoming the second-300byte packet changes the previous values of MSG variable.

 

what is you idea?

5 REPLIES 5
MasterT
Senior III

Use two buffers, ping-pong style. Small 300 bytes, or if memory is available than two big

Peter BENSCH
ST Employee

Or use Half Transfers via XferHalfCpltCallback, which is similar to the proposal of @MasterT:

In addition to the DMA interrupt for a filled buffer, there is also one for a half-filled buffer. Your main process can then store the first half of the buffer in your data array, while the second half is simultaneously filled by the DMA - and later do the same again with the second half of the buffer.

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
VolterPhase
Associate

Hi all,

I am appreciative of your responses.

I followed your advice and implemented the suggested procedure. After each transfer-completed-interrupt, I switch the DMA buffers. However, I am experiencing data loss during the next transmission because the sender transmits all 3000 bytes continuously, and during the 300 bytes interrupts I miss some of them. This version is more polished and clear.

 

void DMA1_Channel3_IRQHandler(void){
			

			if(TCP_Buffer_Selection==1)
			{
				TCP_Buffer_Selection=2;
				DMA_Cmd(DMA1_Channel3, DISABLE);	
				DMA_DeInit(DMA1_Channel3);
			        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Buffer2;
				DMA_Init(DMA1_Channel3, &DMA_InitStructure);
				DMA_ClearITPendingBit(DMA1_IT_TC3| DMA1_IT_TE3);
				DMA_Cmd(DMA1_Channel3, ENABLE);
			}
			else
			{
				TCP_Buffer_Selection=1;
				DMA_Cmd(DMA1_Channel3, DISABLE);	
				DMA_DeInit(DMA1_Channel3);
				DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Buffer1;
				DMA_Init(DMA1_Channel3, &DMA_InitStructure);
				New_DMA_Packet=2;
				DMA_ClearITPendingBit(DMA1_IT_TC3| DMA1_IT_TE3);
				DMA_Cmd(DMA1_Channel3, ENABLE);
			}

}

 

As I know, each time that I want to change the buffer I should configure the DMA and enable it again.

Did I make a mistake?

 

The fastest way is not to do it...

It will likely be cheaper to implement as a scatter-gather list for the DMA to process, and leave the data in-situ

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