2024-05-30 06:34 AM
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?
Solved! Go to Solution.
2024-06-07 09:56 AM
There is an example of using USART with DMA:
2024-05-30 07:16 AM
Use two buffers, ping-pong style. Small 300 bytes, or if memory is available than two big
2024-05-30 07:29 AM
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.
2024-06-07 04:33 AM - edited 2024-06-07 05:29 AM
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?
2024-06-07 06:02 AM
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
2024-06-07 09:56 AM
There is an example of using USART with DMA:
2024-06-17 06:42 AM
I appreciate all of your comments. Thank you.