cancel
Showing results for 
Search instead for 
Did you mean: 

How DMA works in UART

Xenon02
Senior

Hello ! 

I've been wondering how DMA works in UART. 
I've checked some codes for example HAL_UART_Transmit_DMA(). I know it is set to sned 8 bit to peripheral. But I wondered when DMA knows that UART sent 8 bit when it is TX DMA or recevied 8 bit when it is in RX DMA. In this case it is TX. 

I've checked what HAL_UART_Transmit_DMA() does : 

Xenon02_1-1700343951013.png

 

And there was this HAL_DMA_Start_IT(). So it works that DMA sends it's data from memory to UART TX registers. Ok. So tmp is the memory we have the data, and the Instance-> DR is the register the data must be sent. 

So where exactly there is info about turning on the UART to transmit data, and when does the DMA know that UART sent 8 bit and is ready to send another 8 bits ? 

I've also noticed this : 

Xenon02_2-1700343959811.png

 

But I don't understand what it does ? It turn on the UART transmit ? 


Sorry for being to picky I was quite a bit confused due to the fact that in HAL_UART_Transmit there is a while which has a counter that sends 1 byte 

Xenon02_0-1700343925953.png


Although I don't know if it has any info back whether it has sent the data or not. It's so confusing ... There is no waiting time or anything. 

1 ACCEPTED SOLUTION

Accepted Solutions

> RM ?

Reference Manual. You did not tell us which STM32 are you using; if it's STM32L0x3, then it's RM0367.

The proper way to learn is to read the RM and write simple experiments based on what you read there, starting with simple things like transmitting a couple of bytes (which requires to read also the RCC and GPIO chapters to be able to set up the respective Tx pin properly), experimenting with peripherals' registers in debugger (with understanding the caveats), and then add things like DMA which is basically again reading the RM and experimenting with it. Unfortunately, ST refuses to support this path by providing clean and simple register-based examples.

Clicking in CubeMX and using Cube/HAL is a shortcut where you arrive quickly at working point without really understanding what's going on in the hardware. It may work for you if you ever stick to what can be clicked CubeMX; otherwise it may get into your way more than help.

> HAL_UART_Transmit  ... while doesn't check if the data was sent it just goes on, like it sends data to TX without a break

It does wait, in UART_WaitOnFlagUntilTimeout()

> UART_CR3.DMAT says that DMA transmit data to TX register when UART sends TXE

Basically, yes.

As long as TX buffer is empty and UART transmitter is enabled, TXE is set. TXE is a signal from UART's logic (a wire), and UART_CR3.DMAT is a flip-flop which retains the value you've written to it. Output of that flip-flop and TXE are fed to an AND gate (i.e. any one of those two signals is 0, the AND's output is 0) and the output of AND is fed to DMA's input which triggers the DMA transfer.

JW

View solution in original post

13 REPLIES 13

When UART transmiter is enabled, if the transmit buffer is empty, TXE flag is set. This flag, gated by UART_CR3.DMAT, is the request signal ("trigger") to the DMA channel. So, if DMA channel is enabled and UART_CR3.DMAT is set and TXE is set, DMA starts one transfer from memory to UART's data register. This clears TXE, so there is no more DMA transfer, until given bye in UART is transmitted when TXE is set again and the whole process repeats until DMA's count runs to 0.

Instead of Cube/HAL sources, better read the DMA and relevant portions of UART chapters in RM.

JW

STTwo-32
ST Employee

Hello @Xenon02 

>where exactly there is info about turning on the UART to transmit data?

in the initialisation of the uart instant, we can choice to turn on or off both TX and RX. If TX is on, WE Can Do a transfert whenever TXE is set.

 

>when does the DMA know that UART sent 8 bit and is ready to send another 8 bits?

The DMA know that when TXE is set.

 

>But I don't understand what it does ?

This command enable the DMA mode for transmission.

PS: to understand more about how HAL functions work, you can use any exemple then debug the HAL function you want step by step and check the registers states every Time (refer to the product reference manual also).

Best Regards.

STTwo-32 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

So as I understand the : UART_CR3.DMAT is a setting in the hardware of DMA ? Like UART_CR3.DMAT says that DMA transmit data to TX register when UART sends TXE ?  Because I didn't understand what UART_CR3.DMAT exactly do. 
Also about counting is there any counter in the code ? And where it says the UART is enabled to transmit ? 

In the normal UART transmission 
HAL_UART_Transmit , there is some counter TxXferCounter but there is no info when to send another 8 bits or rather info that the UART finished sending 8 bits as well. There is a code that pdatabits8 is incremented but the while doesn't check if the data was sent it just goes on, like it sends data to TX without a break. 

"Instead of Cube/HAL sources, better read the DMA and relevant portions of UART chapters in RM." 

RM ? 
I've tried to understand the code as well but I got lost a bit. I don't know if the begginer is a good thing to add here as well. 

Hello @STTwo-32 

>in the initialisation of the uart instant, we can choice to turn on or off both TX and RX. If TX is on, WE Can Do a transfert whenever TXE is set.

Ok so in initialisation the TX is on, and the data from memory is sent to UART TX register it somehow know if the data is fully transfered to the register ? 

>The DMA know that when TXE is set. 

Is it somewhere in the code such. Like a while loop that checks this TXE or is it a hardware thing ? 

>This command enable the DMA mode for transmission. 

I still don't understand, DMA into transmition ? but it says about UART bit and not DMA bit. It's confusing. 

>PS: to understand more about how HAL functions work, you can use any exemple then debug the HAL function you want step by step and check the registers states every Time (refer to the product reference manual also).

I'll try although I don't yet know how to start with it, I am a begginer :>

> RM ?

Reference Manual. You did not tell us which STM32 are you using; if it's STM32L0x3, then it's RM0367.

The proper way to learn is to read the RM and write simple experiments based on what you read there, starting with simple things like transmitting a couple of bytes (which requires to read also the RCC and GPIO chapters to be able to set up the respective Tx pin properly), experimenting with peripherals' registers in debugger (with understanding the caveats), and then add things like DMA which is basically again reading the RM and experimenting with it. Unfortunately, ST refuses to support this path by providing clean and simple register-based examples.

Clicking in CubeMX and using Cube/HAL is a shortcut where you arrive quickly at working point without really understanding what's going on in the hardware. It may work for you if you ever stick to what can be clicked CubeMX; otherwise it may get into your way more than help.

> HAL_UART_Transmit  ... while doesn't check if the data was sent it just goes on, like it sends data to TX without a break

It does wait, in UART_WaitOnFlagUntilTimeout()

> UART_CR3.DMAT says that DMA transmit data to TX register when UART sends TXE

Basically, yes.

As long as TX buffer is empty and UART transmitter is enabled, TXE is set. TXE is a signal from UART's logic (a wire), and UART_CR3.DMAT is a flip-flop which retains the value you've written to it. Output of that flip-flop and TXE are fed to an AND gate (i.e. any one of those two signals is 0, the AND's output is 0) and the output of AND is fed to DMA's input which triggers the DMA transfer.

JW

Hello Waclaw.jan ! 

>Reference Manual. You did not tell us which STM32 are you using; if it's STM32L0x3, then it's RM0367.

Aha this is what you meant :>, I understand now, I have STM32L073RZ, so I found out which manual it is. 

It does wait, in UART_WaitOnFlagUntilTimeout()

Oh I can see it right now :> I missed this part and inside of UART_WaitOnFlagUntilTimeout() there is a while loop that checks untill there is a timeout or not.

> As long as TX buffer is empty and UART transmitter is enabled, TXE is set. TXE is a signal from UART's logic (a wire), and UART_CR3.DMAT is a flip-flop which retains the value you've written to it. Output of that flip-flop and TXE are fed to an AND gate (i.e. any one of those two signals is 0, the AND's output is 0) and the output of AND is fed to DMA's input which triggers the DMA transfer.


I have found a really good picture about it. 
I wanted to ask 4 more questions if it's not a problem ? I understood a lot from these replies ! 

- How does the register or something know that UART is empty to send this TX flag ? 
- I've heard something like that : "DMA is performed by hardware. There is no code." But the DMA must be somehow configured right ? So there must be a code to configure it. Although there is no code about which TX flag etc. Something like which flag he has to wait for. So I got a bit confused when there is something about DMA codding and about UART codding because UART_Transmit_DMA is mostly about UART settings, and CR3 for uart is also a UART setting and not a DMA setting (it allows to transmit the TX flag to it's DMA).
- What is the Huart and Hdma_usart handlers ? I've read both of them and Huart has things the Hdma_usart has as well, Huart is just the Hdma_usart but with more arguments. More over, in the Hdma_usart like here : 

Xenon02_0-1700394516029.png

the hdma has configured the flags but not the direction and in HAL_DMA_Start_IT it asks for direction :D It's weird why it is not here configured but somewhere in a different file. It is mixing. 

- does DMA has to always wait for a flag to transmit a data like it sent 32 bits now it wait for a flag ? Same with receiving it also has to wait for a flag Like from device to the memory so the memory has to send a flag? Let's say from memory to memory, how does he know for which flag he has to wait ? Or is it predefined to only a specific devices ? 


Sorry for asking so many questions, have a nice day :> 

> How does the register or something know that UART is empty to send this TX flag ?

The UART Tx hardware is basically a shift register and a counter (which counts, how many bits remain to be transmitted, i.e. at the beginning it's at 0). TXE is a flip-flop, which after enabling transmitter is set to 1. When you write a byte into the data register, TXE gets cleared. Then UART checks, if the counter is zero, and if it is, the byte gets transferred from the data register into the shift register, together with a startbit and a stopbit, and at the same time the counter is set to 2+8 (or whatever the data length is). Data register is now empty so TXE gets set to 1. If you now write another byte in to the data register, TXE gets cleared and it does not get set to 1 again until the byte is transmitted from the shift register and counter is zero. The baudrate generator clocks out the bits from the shift register and at the same time decrements the counter; as soon as counter gets to zero, baudrate generator thus transmission stops. If there is already a byte in the data register, it gets transferred to the shift register, TXE gets set, and the whole process starts again.

 

> But the DMA must be somehow configured right ? So there must be a code to configure it.

You will find all the details you need in the DMA chapter in RM. Start with reading it as I've recommended above.

 

> does DMA has to always wait for a flag to transmit a data

Yes.

 

> like it sent 32 bits now it wait for a flag ?

DMA transfers 8, 16 or 32 bit data in one transaction, depending on setting in given DMA channel's control register. Read the DMA chapter in RM.

From peripheral point of view, such transfer is the same as if you'd write from processor. Most peripherals require data of certain width, e.g. UART when set to 7 or 8 bit data requires 8-bit wide data; when set to 9 bit it requires 16-bit wide data. If UART is set to 8-bit data and you write 16 or 32 bit wide data to it, the uppermost bits simple get lost.

 

> What is the Huart and Hdma_usart handlers ?

I don't use Cube/HAL and I am not interested in it.

JW

The UART Tx hardware is basically a shift register and a counter (which counts, how many bits remain to be transmitted, i.e. at the beginning it's at 0). TXE is a flip-flop, which after enabling transmitter is set to 1. When you write a byte into the data register, TXE gets cleared. Then UART checks, if the counter is zero, and if it is, the byte gets transferred from the data register into the shift register, together with a startbit and a stopbit, and at the same time the counter is set to 2+8 (or whatever the data length is). Data register is now empty so TXE gets set to 1. If you now write another byte in to the data register, TXE gets cleared and it does not get set to 1 again until the byte is transmitted from the shift register and counter is zero. The baudrate generator clocks out the bits from the shift register and at the same time decrements the counter; as soon as counter gets to zero, baudrate generator thus transmission stops. If there is already a byte in the data register, it gets transferred to the shift register, TXE gets set, and the whole process starts again.

Something like this ? 

Xenon02_2-1700416658139.png

But this picture is not enough. Because there must be something a logic gate to stop UART from transmiting and stops the clock ? To make sure the data is set in the shift register. Or rather I don't know if I am right but the clock must be disabled in shift register to not send data I think ? 

The TX flag is from different register I guess ? And it acts as input or as output, I wonder how. 

Don't get me wrong here, I understand the concept you have told me and as I understand UART doesn't check the counter until the TX flag is cleared. When it is cleared it checks the counter and when it's 0, it loads the data from register to shift register and I think it, and then the counter is not 0, I don't know if 8/10 number can be treated as "1" or "0" in the shift/write register. But I think that's how it would work. 

Sorry for me being very stubborn, I believe I haven't angered you, because I don't know why I have a feeling I want to understand it and it makes me a bit anxious that I don't understand it a bit when it comes to hardware in more specific way. Because usually the UART devices pictures shows only data bus and TX RX like here : 

Xenon02_5-1700417599892.png


Maybe it is in RM as you've said but I wanted to also try to ask here because in RM it is not that specific as I've checked. 

Sorry again :> 

>You will find all the details you need in the DMA chapter in RM. Start with reading it as I've recommended above.

If I don't find what I am looking for there or won't understand it should I ask it here or in new post ?
I don't want to be a problem in this forum. 

I don't use Cube/HAL and I am not interested in it.

I am sorry if my question annoyed you. 
thanks for the help :> 

Thank you a lot JW. 

I've started reading the DMA in RM, and it is a bit confusing like this part : 

Xenon02_0-1700419415558.png

Like bits 1 and 0 of PA[31:0] are ignored ? The whole data of PA[31:0] can be 0001010011111... and it contains 0 and 1 so they are ignored :D Like whole data loaded in it is ignored. 

I can see that DMA must be first configured by CPU to even work. After configuration it will work. Like register memory configuration and peripheral configuration, channel configuration etc. So I think CPU must configure the device first so it will work from that point. CPU sends an enable I think to start the DMA after configuration. 

The picture how DMA works doesn't tell a lot : 

Xenon02_1-1700419582261.png

Like how it works exactly AHB Slave I believe is for configuration like which channel or which devices uses this DMA, and the DMA output bus I guess is to make this transfer, I wonder how it works like it know the address so it goes to that address and takes somehow the value and stores it in a register not shown in the RM ? I guess. How he searches the devices/memory like there is some logic gates for scanning already built in ? 


Sorry for many questions, if it's bothering.