Skip to main content
Helder Sales
Associate III
December 12, 2018
Question

Sending UART data at maximum speed without interrupts

  • December 12, 2018
  • 5 replies
  • 1431 views

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]

This topic has been closed for replies.

5 replies

AvaTar
Senior III
December 12, 2018

> 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 ?

Helder Sales
Associate III
December 12, 2018

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
Senior III
December 12, 2018

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.

Tesla DeLorean
Guru
December 12, 2018

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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
Helder Sales
Associate III
December 12, 2018

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.