Hi
A simple method to receive random message lengths via DMA is to use free-running DMA. That is, simple receive to a circular buffer with effectively infinite reception length. A task then polls the amount of data that is in the buffer and handles it.
As long as the polling task checks at a rate that ensures that the circular buffer doesn't overwrite data that hasn't yet been read there is no data loss. Typically a low priority polling or timer event driven task is adequate.
The polling rate can be selected as compromise between the checking overhead and the reaction time to a completed message and the circular buffer length is also defined to be adequately large to avoid overflow after a worst case polling interval delay. Since the polling rate is not related to the necessary reaction time to ensure no Rx data loss at the UART itself MByte data rates are possible without data loss (the advantage of the DMA).
This technique is used in the uTasker project on various platforms including Kinetis and i.MX RT and the interface and behavior is equivalent. The i.MX RT has a better DMA controller than in some Kinetis parts (like the KL range) and can easily do this. Some KL parts can only do modulo reception lengths up to a certain number of DMA transactions but, with the RX memory set up accordingly, can be used in the same way by simply re-initialising the Rx DMA count to its max. value at each polling interval. Therefore such projects can be made fully portable across various families.
Regards
Mark
Below is, by way of example, the code used in the uTasker project's ESP32 AT mode WIFI interface (to configure the interface) that has been used on various families. It uses DMA on UART TX and RX (when the define is set) and is fully compatible on various platforms - note that the user adds a flag when KL parts (with modulo DMA buffer requirement) and the UART driver does the rest.
extern int fnConfigSerialESP32(unsigned char ucSpeed, unsigned char ucDriverMode)
{
TTYTABLE tInterfaceParameters; // table for passing information to driver
tInterfaceParameters.Channel = ESP32_S2_AT_UART; // the UART connected to the ESP32
tInterfaceParameters.ucSpeed = ucSpeed; // fixed baud rate
tInterfaceParameters.Config = (CHAR_8 | NO_PARITY | ONE_STOP | CHAR_MODE); // fixed settings
tInterfaceParameters.Task_to_wake = OWN_TASK; // wake self when messages have been received
#if defined SERIAL_SUPPORT_DMA
#if (defined ESP32_AT_FREERUN_RX_DMA && defined SERIAL_SUPPORT_DMA_RX && defined SERIAL_SUPPORT_DMA_RX_FREERUN)
#if defined KINETIS_KL
tInterfaceParameters.ucDMAConfig = (UART_TX_DMA | UART_RX_DMA | UART_RX_MODULO); // activate DMA on transmission and reception
#else
tInterfaceParameters.ucDMAConfig = (UART_TX_DMA | UART_RX_DMA); // activate DMA on transmission and reception
#endif
#else
tInterfaceParameters.ucDMAConfig = (UART_TX_DMA); // activate DMA on transmission
#endif
#endif
tInterfaceParameters.Rx_tx_sizes.RxQueueSize = ESP32_UART_RX_BUFFER_SIZE; // input buffer size
tInterfaceParameters.Rx_tx_sizes.TxQueueSize = ESP32_UART_TX_BUFFER_SIZE; // output buffer size
ESP32_S2_PortID = fnSetNewSerialMode(&tInterfaceParameters, ucDriverMode); // open serial port for I/O, or modify its baud rate
return (ESP32_S2_PortID == NO_ID_ALLOCATED);
}