Reputation: 55
Which of the following is better practice (or please suggest better alternatives) when using a global buffer with DMA with UART on an STM32 embedded application (no RTOS):
Option 1: When entering the ISR after a DMA to Idle event on the UART I have a global buffer that has been filled with characters. I set a flag in the ISR and exit quickly. In main loop I check the flag and process the contents of the global array. I then reset the flag at the end of processing.
Possible Advantages
Possible Disadvantages
Option 2: When entering the ISR after a DMA to Idle event on the UART I have a global buffer that has been filled with characters. I process the characters within the ISR and then set a flag according to what output is necessary.
Possible Advantages
Possible Disadvantages
Or, does anyone have any other alternatives, e.g. setting a flag and then copying the buffer immediately in the main loop to a local variable, and then processing that local variable itself?
Grateful for any advice and comments.
Upvotes: 1
Views: 95
Reputation: 154173
I process the characters within the ISR
#2 is a weak choice. ISRs are not meant for long execution time. Get in, get out.
incoming UART characters could change the array contents as I'm processing it?
Avoid a race condition of data arriving while processing the buffer in option #1.
Option 3: use 2 buffers. Let the DMA fill the one that is not being processed. The ISR, after filling one buffer, simple swaps which buffer to use. Now the processing is done in the foreground with the proviso that it must be done before the alternate buffer is filled, else the ISR should whine with setting a buffer overflow error flag.
Could use more than 2 buffers is processing is sluggish/jerky, yet fast enough over a long period. Yet I suspect 2 will work fine for OP.
Upvotes: 3
Reputation: 67835
Global buffer is a bad idea.
I have plenty systems using DMA UART at the high speeds (up to 8M).
It is clean fast and reliable.
Upvotes: 3
Reputation: 214770
It all boils down to real-time requirements. How fast is the data coming in and how frequently. Size of the data in relation to the DMA buffer. How busy your program is doing other things. How important is the UART communication in relation to other things. What possibilities the DMA offers when it comes to early warning flags and swapping buffers. And so on - there is no general solution fitting every application.
Also, processing data directly in the DMA buffer is probably not recommended, unless you know you have plenty of time to do so. Otherwise copying to another buffer is faster than processing. Either way you have to make sure that the data stays protected from getting overwritten while sitting in the DMA buffer.
So one sensible way of implementing it could be:
There's also a law of physics here: if the background program isn't fast enough to process the data in time, then no DMA driver design or queue system will salvage that situation. You have to either live with packet losses or find a way to speed up the background program.
Upvotes: 0