UART with DMA but without using interrupts?

Showing results for 
Search instead for 
Did you mean: 

UART with DMA but without using interrupts?

Contributor II

Is it possible to automate the receiving and transmitting of data with a UART peripheral using DMAs without using interrupts? I'm using MKL27Z128. It seems like you need the interrupt to do a few things like clear the "done" flag and reload BCR with a value for the next block. In my application, I would really like to avoid interrupts all together!

To be clear, I would like the RX DMA to simply transfer a byte to a circular buffer every time the uart data buffer is full. I would also like the TX DMA to transfer bytes one by one from a circular buffer in memory to the uart data buffer (transfer would be initiated by software via the "START" bit).

Is this just impossible with this microcontroller family?


0 Kudos
3 Replies

Specialist V

Hello Felix

The DMA controller in the KL27 is not as flexible as the eDMA in other parts but what you want to do is possible.

You need to use modulo mode of DMA operation (aligning your buffers on 16, 32, 64, 128... boundaries and using the same size) and then you can use free-running DMA operation. The free-running operation is in fact limited to 64k transfers (due to the max. counter value) but as long as this counter is reset to its max. value periodically (before it counts down to 0) it then is effectively infinite.

The uTasker project supports these mode for its UART and LPUART drivers (on all UARTs up to the DMA channel limit in the HW), including allowing the application to work with free-running DMA rx operation (also allowing FreeRTOS to benefit from the mode for interrupt and data loss free high speed UART reception up to several MBaud).

The operation is included in the open source uTasker version on GitHub for almost all Kinetis parts (including KL27) and allows the operation to be accurately simulated in Visual Studio for developing/debugging/understanding the underlying operation. Or in its supported commercial version with many more features and compatibility with i.MX RT parts.

Eg. Interrupt driver mode:

tInterfaceParameters.Channel = 0; // UART 0, 1, 2
tInterfaceParameters.ucDMAConfig = 0;

fnOpen(TYPE_TTY, FOR_I_O, ptrInterfaceParameters);

DMA transmission mode

tInterfaceParameters.ucDMAConfig = UART_TX_DMA;
fnOpen(TYPE_TTY, FOR_I_O, ptrInterfaceParameters);

DMA transmission and reception mode

tInterfaceParameters.ucDMAConfig = (UART_RX_DMA | UART_RX_MODULO | UART_TX_DMA);
fnOpen(TYPE_TTY, FOR_I_O, ptrInterfaceParameters);

whereby UART_RX_MODULO is needed only by parts without eDMA and the driver then does all the dirty work of aligning buffers accordingly. The user just needs to set the driver flags according to behavioral requirements.

DMA channel allocation is by project defines (with potential limitations due to DMA channels available in the actual device used - up to 4 can be actually used in the KL27!):

    #define DMA_UART0_TX_CHANNEL   2                                     // use this DMA channel when using UART 0 for transmission driven by DMA
    #define DMA_UART1_TX_CHANNEL   1                                     // use this DMA channel when using UART 1 for transmission driven by DMA
    #define DMA_UART2_TX_CHANNEL   0                                     // use this DMA channel when using UART 2 for transmission driven by DMA

    #define DMA_UART0_RX_CHANNEL   3                                     // use this DMA channel when using UART 0 for transmission driven by DMA
    #define DMA_UART1_RX_CHANNEL   4                                     // use this DMA channel when using UART 1 for transmission driven by DMA
    #define DMA_UART2_RX_CHANNEL   5                                     // use this DMA channel when using UART 2 for transmission driven by DMA


[uTasker project developer for Kinetis and i.MX RT]

Contributor II

Thanks Mark for pointing me in the right direction. The piece I was missing was periodically setting BCR to a high number (to make sure it never hits zero) and setting the Cycle Steal bit to only do one transfer per trigger. Now it works beautifully!

0 Kudos

NXP TechSupport
NXP TechSupport


You can disable the interrupt in DMA_DCRn. Then when you initiate a transfer, you have to continuously check the bit DONE in DSR_BCRn to confirm if the transfer has completed. 

Have a great day,

- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 days after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.

0 Kudos