Skip to main content
Graduate II
May 30, 2024
Solved

High Speed Memory array copy

  • May 30, 2024
  • 4 replies
  • 2123 views

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?

    This topic has been closed for replies.

    4 replies

    Explorer
    May 30, 2024

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

    Technical Moderator
    May 30, 2024

    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.

    Graduate II
    June 7, 2024

    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?

     

    MasterTAnswer
    Explorer
    June 7, 2024
    Graduate II
    June 17, 2024

    I appreciate all of your comments. Thank you.

    Graduate II
    June 7, 2024

    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