← index #4389Issue #6999
Off-topic · high · value 0.684
QUERY · ISSUE

esp8266: Necessity for UART flush

openby cemoxopened 2019-01-01updated 2019-07-06
port-esp8266

This is rather recommendation than issue. The code below sends a string message from UART1 and is supposed to pull the output pin LOW :

mypin.on()
uart1.write("a long sentence")
mypin.off()

when I checked the signal (part tx and output) with logic analyzer, I saw that pin is pulled low long before the uart transmission has been completed. A function like uart.flash() which checks the relevant uart status bits for completion of the transmission would be very handy.

CANDIDATE · ISSUE

rp2: uart performance problem with higher baudrates or when doing additional operations

closedby kevinkk525opened 2021-03-05updated 2021-06-18

The rp2 suffers from a performance problem reading from the UART, most likely getting received bytes out of the FIFO and into the RAM in time.
The problem becomes more obvious the higher the baudrate is.

Most obvious test case at baudrate 460800:

# on the rp2:
uart = machine.UART(1, rx=machine.Pin(5), tx=machine.Pin(4), baudrate=460800)
def read(l):
    # function just to print the length of the received message and flush the uart before waiting for new bytes.
    while uart.any():
        uart.read(1)
    r=uart.read(l)
    print(r,len(r))
read(60)
b'012345678901234567890123456789012345678901234567890167890123' 60

On the esp32 (done manually on the repl):

>>> a=b'0123456789'
>>> uart = machine.UART(1, tx=17, rx=16, baudrate=460800)
>>> uart.write(a*6) # send 60 Bytes
>>> uart.write(a*6)

On the esp32 I had to send 60 Bytes twice (!) because the rp2 didn't receive all 60 Bytes during the first transmission. It seems to have dropped Bytes after 51 bytes because that's where the sequence starts again every time, so it's a consitent error.

Running the same test at baudrate 115200 was fine even up to 4000 Bytes. Therefore my assumption that this is a performance problem because if it was just getting out of sync, it wouldn't be fine with 4000 Bytes at baudrate 115200 but only less than 60 Bytes at 460800.

To further show the performance problem when doing some small operations while receiving data like reading in smaller chunks and merging the received strings:

Testcase (note: usually I'd use uart.read() but that doesn't work on the rp2 at the moment, so we're reading in chunks of 20):

def test2(t,t2):
...     while True:
...         gc.collect()
...         recv=b''
...         read=[]
...         st=time.ticks_us()
...         while time.ticks_diff(time.ticks_us(),st)<t:
...             if uart.any():
...                 rr=uart.read(20)
...                 recv+=rr
...                 read.append(len(rr))
...             else:
...                 time.sleep_us(t2)
...         if len(recv)>0:
...             print(recv,len(recv),read)
...
...
...
>>> test2(10000,0)

The output of always sending 60 Bytes manually after reading the last output results in an output of something like this on the rp2:

b'012345678901234567890123456789012345678901234567890123456789' 60 [20, 20, 20]
b'012345678901234567890123456789012345678901234567890123456789' 60 [20, 20, 20]
b'01234567890123456789' 20 [20]
b'0123456789012345678901234567890101234567' 40 [20, 20]
b'8901234567890123456789012345678901234567' 40 [20, 20]
b'8901234567890123456789012345678901234567' 40 [20, 20]
b'89012345678901234567' 20 [20]

As you can see, at first receiving 60 Bytes in chunks of 20 Bytes was working but only after a few more transmissions it screwed up and lost some bytes.
And that's at baudrate 115200!

Repeating this test at baudrate 460800 already screws up when sending 40 Bytes at once! The output is then (after having to send 40 Bytes twice since it didn't even read 40 Bytes during the first read):

b'0123456789012345678901234567890101234567' 40 [20, 20]

So suddenly even the previously stable uart.read(4000) at baudrate 115200 is now unreliable when trying to read 60 Bytes in 20 Bytes chunks!

(I also did the test at baudrate 9600 and at that baudrate you can actually transmit 4kB in 20 Byte chunks just fine.)

I'll spare you the comparison between two esp32s. The short version is: It's a lot better, I can send 800Bytes at baudrate 460800 without any issues.

So in the current uart implementation there seems to be a serious performance issue resulting in the uart dropping bytes, making it rather impossible to use as the smallest amount of operations already impacts its performance severly even at baudrate 115200.
I understand the buffer is only 32 Bytes but to fill that buffer the uart at baudrate 115200 needs ~2.5ms, which should be more than enough (after removing 20 Bytes from the buffer when reading the next chunk) to perform the operations in test2() since that's just a small merge of 2 byte objects with less than 40 Bytes lenght in total.

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied