Technically, rx_buff and rx_out should be volatile too, but it is
unlikely for it to be a problem (your compiler would have to be inlining
multiple copies of the uart_getchar function - possible with link-time
optimisation - and do some legal but unlikely re-ordering).
And have rx_size as a variable is going to be inefficient compared to
using a compile-time constant and making ROLLOVER a mask.
>
> Now I'm starting using new microcontrollers that embed a DMA engine, for
> example SAM C21 Cortex-M0+ from Atmel (I think many Cortex-M0+ micros
> out there integrate a DMA engine).
>
> So I'm asking if it is possible to avoid completely the ISR and use the
> DMA to move received character in the FIFO buffer.
>
> I read the datasheet, but I couldn't found a solution to my problem.
>
> First of all, the destination memory address could be fixed or
> auto-incrementing, but there isn't a mechanism to wrap-around (FIFO
> buffer is a *circular* array, so after pushing N bytes, the address
> should start again from the beginning).
My experience is only with Freescale's DMA engine (on Kinetis ARMs and
MPC's), which have support for circular buffers for precisely this
reason. It seems a strange omission from Atmel to have no similar support.
> Maybe I have to configure the DMA for a transaction with a byte count
> equals to the size of the FIFO buffer. When the last byte is received,
> the transaction ends and an interrupt could be raises (if correctly
> configured). In the relevant ISR, a new DMA transaction could be
> started (with the destination memory address equals to the beginning of
> the FIFO buffer).
That sounds about right.
Depending on the type of communication you are expecting, and the
resources you have, it might be possible to simply have a large enough
buffer to support all legal incoming packets.
>
> Another issue is how the application (background) could know how many
> bytes are present in the FIFO buffer so it can pop and process them as
> it wants.
Again, I don't know Atmel's DMA engine, but usually there are values you
can read (byte count, current destination pointer, etc.) that will help
here.
And you also want to check if you really /need/ the DMA here. If the
processor is not overloaded, an ISR can be simpler and easier - and
often it does not matter if that "wastes" a few percent of your cpu
capacity. DMA on transmit is often very simple, but for receive the
complications of timings and timeouts can make the DMA less of a win.