Absolutelly in DMA when it is available.
You have one big (good solution is cyclic) buffer and you just write data from one side. If DMA does not already work, you start the DMA with your buffer.
If DMA works, you just write your data to buffer and you wait DMA transfer complete interrupt.
Later in this interrupt you increase read pointer of buffer (as you sent some data already) and check if any data available to send over DMA. Set memory address to DMA and number of bytes in buffer to send.
Again, when DMA TC IRQ happens, do process again.
There is no support for FRAME, but only in plain bytes. It means you have to "invent" your own frame protocol and use it in app.
Later, when you want to send that FRAME over UART, you have to:
- Write start byte to buffer
- Write other header bytes
- Write actual data
- Write stop bytes/CRC/whatever
- Check if DMA does not work, if it does not, start it.
Normally, I use this frame concept:
[START, ADDRESS, CMD, LEN, DATA, CRC, STOP]
- START: Start byte indicating start of frame
- ADDRESS: Address of device when multiple devices are in use on bus
- CMD: Command ID
- LEN: 2 bytes for data length
- DATA: Actual data in bytes of variable length
- CRC: 2 bytes for CRC including: address, cmd, len, data
- STOP: Stop byte indicating end of frame
This is how I do it in every project where necessary. This does not use CPU to send data, just sets DMA and starts transmission.
From app perspective, you just have to create send_send(data, len)
function which will create frame and put it to buffer for transmission.
Buffer size must be big enough to fit your requirements:
- How much data at particular time (is it continues or a lot of data at small time)
- UART baudrate
For specific question, ask and maybe I can provide some code examples from my libraries as reference.