cancel
Showing results for 
Search instead for 
Did you mean: 

Sending UART data at maximum speed without interrupts

Helder Sales
Associate II

Hi,

There something odd with the USART3 (the Virtual COM one). I can send characters, but there's some speed limit that I can't surpass.

I'm trying to loop a string as fast as possible, but I can't get the optimum speed, I'm having to use a delay (or a timer) to make the UART work.

From what I understood reading the datasheet, the procedure (without the use of interrupts), would be:

Set the TE bit, wait for TEACK to be set, put some data in the TDR, wait for TXE to be set, put another data in the TDR, repeat the last two steps n times, wait for the TC bit to be set, reset the TE bit.

Doing this I'm stuck in the TC polling. Removing this I'm getting AKUeoz in the terminal. These TXE and TC flags are not to be used to control the speed in which data is sent through the U(S)ART registers?

Also, while trapped forever in the TC loop, the memory view shows nothing in the TDR memory location...

MCU is STM32F767ZI

   AREA STRINGS, DATA, READONLY
String DCB "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxz",0
 
   (...)
 
   LDR R5,=String
 
   (...)
 
 
   LDR R0,=USART3_CR1 	;Enable USART3 transmission (sends idle frame)
   LDR R1,[R0]
   ORR R1,#USART3_TE
   STR R1,[R0]
				
TEACK			;Wait for idle minimum time
   LDR R0,=USART_ISR 
   LDR R1,[R0]
   AND R1,#USART3_TEACK
   BEQ TEACK
				
   MOV R9,#10
				
LOOP_STRING		;Transmit char and update address
   LDR R0,=USART_TDR 					
   LDR R1,[R5],#1
   STR R1,[R0]
 
TXE			;Wait for TX buffer being empty	
   LDR R0,=USART_ISR 	
   LDR R1,[R0]
   AND R1,#USART3_TXE
   BEQ TXE
						
   SUBS R9,R9,#1
   BNE LOOP_STRING
 
TC			;Wait for transmission to complete			
   LDR R0,=USART_ISR 
   LDR R1,[R0]
   AND R1,#USART3_TC
   BEQ TC
				
   LDR R0,=USART3_CR1 	;Disable USART3 transmission
   LDR R1,[R0]
   AND R1,#~USART3_TE
   STR R1,[R0]

5 REPLIES 5
AvaTar
Lead

> There something odd with the USART3 (the Virtual COM one).

The "virtual COM one" is a F103 implementing the ST-Link, and translating your output to USB CDC.

Have you considered that this element might have speed limits ?

I'm using 115200 baud rate,1 stop bit, 8 bits per transfer. I haven't considered that to be honest, but this speed shouldn't be a problem I think.

Update: tested with an external CH340 USB-TTL converter and still the same results...

AvaTar
Lead

I thought you was speaking about >Mbps rates. But 115200 isn't really maximum speed, USB-to-serial devices can usually handle this.

But if I interpret you assembler code right, you mistake UART TXE for "transmission completed".

TXE means the TDR value is copied to the HW send register, the actual transmission might not have even started yet.

For sending strings, you could use DMA. That would unload the core, and avoid busy looping on flags.

Viewing the USART peripheral via a memory view is not recommended. I'm not sure you can peer inside write only registers. Use the TXE bit to determine if the USART is ready for another character. Use the VCP at 115200 baud without issue here, and with tighter code.​

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

I wasn't planning to use DMA soon, as I have not enough experience (only once with a TM4C, in ping-pong mode for ADC).

Anyway, I'm trying to use the TXE bit in this part of the code before filling TDR again

TXE  LDR R0,=USART_ISR  ;Wait for TX buffer being empty
     LDR R1,[R0]
     AND R1,#USART3_TXE ;(1 << 7)
     BEQ TXE

Even if I wait for the transmission complete flag (TC), the behavior is the same. That's what doesn't make sense.

Edit: I'm not sure you can peer inside write only registers.

Actually, it says rw registers in the reference manual.