cancel
Showing results for 
Search instead for 
Did you mean: 

Using DMA for USART Rx to get an interrupt whenever a byte of data is received

SJant.1
Associate III

Hi,

I have an application that is running many tasks with different priorities. So whenever the user enters data, the task containing uart_read function might not have executed. So currently I am using RXFNE interrupt which gives me an interrupt on the reception of each byte of data, and in the callback function I continuously check for the presence of data

((huart->Instance->ISR & UART_FLAG_RXFNE)  != 0)

So until the data is available I get the data as well as I check for data and copy it in a circular buffer whenever the data is available. With this the data read is completely working fine.

Now I want to use the DMA for the data transfer. In the call back function if I use HAL_DMA_START_INIT and give the destination and source address as the circular buffer and huart->Instance->RDR respectively, and set the DMAR bit, I donot see the data actually being copied to the buffer though I can see it in the RDR register.

Any idea how can I implement this?

In a gist what I want to do is I want to receive an interrupt whenever the data is received and then I want to transfer the data from RDR register to a circular buffer using DMA.

Any suggestions would be very helpful. Thanks

7 REPLIES 7

So, let's see if I get this. You're using interrupts, but polling the interrupt flag?

Now you want to use DMA, but want to see the data being moved?

DMA works by grabbing free time on the bus while your code is off doing other things. So you can't watch the data being moved. The DMA happens when you're not looking.

Interrupts mean never having to poll.

I must be missing something very basic in your question. I wrote some posts about this.

https://embedded.fm/blog/2017/2/20/an-introduction-to-dma

https://embedded.fm/blog/2017/2/27/dma-examples

The bigger problem that you will run into is that 1 character DMA will have as much overhead as interrupts. You'll be rate limited. If you bring in more than one character, you will be in the typical situation of not getting an interrupt until you get all N characters, one too few and you won't get your interrupt, so you end up using timeouts.

SJant.1
Associate III

Hi Andrei,

Thanks for your response.

I think I have already made the question quite complicated, but let me try to put it this way,

My requirement is I read the data only when it is available and the data transfer from UART to a circular buffer should be through DMA.

Currently without DMA, I am using a callback function for receive FIFO not empty register and whenever there is data available this interrupt triggers and callback function is called. In the callback function I check if the data is really present by checking ISR register with RXFNE flag (this check might make no sense as the callback function is called only on data reception). Now this system is perfectly working. So whenever the data is entered, it is copied to a circular buffer in the callback function.

But here I am using regular read operation to pop the data from the RDR register to the circular buffer.

This transaction of data I want to do it using DMA. So how can I actually do this?

Remember I should not wait for the data to be present, the application will be running different tasks. So whenever there is data then only I should read.

Hoping this is a better explanation than the previous post!!

Here just make a circular buffer, commensurate with baud rate, and swept on the 1KHz task

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

Hi Tesla,

Can you please elaborate this?

The question is how do I get to know when the data is available if I am using DMA?

How to setup DMA so it gives me a transfer complete interrupt when data is received?

Piranha
Chief II

The UART RX have an IDLE line interrupt, you can enable this interrupt and know when the transfer on the UART is likely to be complete. DMA also has that TransferComplete / half TransferComplete interrupt for a fixed TX buffer size.

SJant.1
Associate III

Hi everyone,

Thanks for your response. I need to know if there is a way to configure UART-Rx in DMA mode and wait for the data to be available?

I mean in case of Rx FIFO not empty interrupt, we wait for that interrupt and then read the RDR register. But I want this to happen with the DMA. How to get the data to the RDR register using DMA?