Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Unexpected .in_waiting and .written values #13

@anecdata

Description

@anecdata

code.py:

import time ; time.sleep(3)  # wait for serial after reset
import board
import adafruit_pio_uart

def write(size, ch):
    print(f'writing {size} bytes of {ch}...', end=" ")
    written = u1.write(f'{size * ch}')
    time.sleep(1)
    print(f'{written=} {} {u2.in_waiting=}')


# two PIO UARTs, connected to each other
# PIO uart rx buffer 8-9 bytes
# u1 will write, u2 will check in_waiting

print("\nWITHOUT hardware flow control\n")
u1 = adafruit_pio_uart.UART(tx=board.GP0, rx=board.GP1)
u2 = adafruit_pio_uart.UART(tx=board.GP4, rx=board.GP5)

# write a chunk of bytes all at once
for size in (4, 5, 6, 7, 8, 9, 10):
    # clear the read buffer for each new test
    u2.reset_input_buffer()
    print(f'busio initial {u2.in_waiting=}')
    write(size, "Z")
print(f"{u2.read(16)=}")

print()
# write bytes one at a time
# clear the read buffer for each new test
u2.reset_input_buffer()
print(f'busio initial {u2.in_waiting=}')
write(4, "Y")
write(1, "X")
write(1, "W")
write(1, "V")
write(1, "U")
write(1, "T")  # 9th byte
write(1, "S")  # 10th byte
write(1, "R")  # 11th byte
write(1, "Q")  # 12th byte
print(f"{u2.read(16)=}")

u1.deinit()
u2.deinit()

print("\nWITH hardware flow control\n")
u1 = adafruit_pio_uart.UART(tx=board.GP0, rx=board.GP1, cts=board.GP2, rts=board.GP3)
u2 = adafruit_pio_uart.UART(tx=board.GP4, rx=board.GP5, cts=board.GP6, rts=board.GP7)

# write a chunk of bytes all at once
for size in (4, 5, 6, 7, 8):  # 9 bytes would block
    # clear the read buffer for each new test
    u2.reset_input_buffer()
    print(f'busio initial {u2.in_waiting=}')
    write(size, "A")
print(f"{u2.read(16)=}")

print()
# write bytes one at a time
# clear the read buffer for each new test
u2.reset_input_buffer()
print(f'busio initial {u2.in_waiting=}')
write(4, "B")
write(1, "C")
write(1, "D")
write(1, "E")
write(1, "F")
# write(1, "G")  # 9th byte would block
print(f"{u2.read(16)=}")

code.py output:

WITHOUT hardware flow control

busio initial u2.in_waiting=0
writing 4 bytes of Z... written=None () u2.in_waiting=4
busio initial u2.in_waiting=0
writing 5 bytes of Z... written=None () u2.in_waiting=5
busio initial u2.in_waiting=0
writing 6 bytes of Z... written=None () u2.in_waiting=6
busio initial u2.in_waiting=0
writing 7 bytes of Z... written=None () u2.in_waiting=7
busio initial u2.in_waiting=0
writing 8 bytes of Z... written=None () u2.in_waiting=8
busio initial u2.in_waiting=0
writing 9 bytes of Z... written=None () u2.in_waiting=8
busio initial u2.in_waiting=1
writing 10 bytes of Z... written=None () u2.in_waiting=8
u2.read(16)=bytearray(b'ZZZZZZZZZ')

busio initial u2.in_waiting=0
writing 4 bytes of Y... written=None () u2.in_waiting=4
writing 1 bytes of X... written=None () u2.in_waiting=5
writing 1 bytes of W... written=None () u2.in_waiting=6
writing 1 bytes of V... written=None () u2.in_waiting=7
writing 1 bytes of U... written=None () u2.in_waiting=8
writing 1 bytes of T... written=None () u2.in_waiting=8
writing 1 bytes of S... written=None () u2.in_waiting=8
writing 1 bytes of R... written=None () u2.in_waiting=8
writing 1 bytes of Q... written=None () u2.in_waiting=8
u2.read(16)=bytearray(b'YYYYXWVUT')

WITH hardware flow control

busio initial u2.in_waiting=0
writing 4 bytes of A... written=None () u2.in_waiting=4
busio initial u2.in_waiting=0
writing 5 bytes of A... written=None () u2.in_waiting=5
busio initial u2.in_waiting=0
writing 6 bytes of A... written=None () u2.in_waiting=6
busio initial u2.in_waiting=0
writing 7 bytes of A... written=None () u2.in_waiting=7
busio initial u2.in_waiting=0
writing 8 bytes of A... written=None () u2.in_waiting=7
u2.read(16)=bytearray(b'AAAAAAAA')

busio initial u2.in_waiting=0
writing 4 bytes of B... written=None () u2.in_waiting=4
writing 1 bytes of C... written=None () u2.in_waiting=5
writing 1 bytes of D... written=None () u2.in_waiting=6
writing 1 bytes of E... written=None () u2.in_waiting=7
writing 1 bytes of F... written=None () u2.in_waiting=7
u2.read(16)=bytearray(b'BBBBCDEF')

Observations:

  1. Without flow control, 9 bytes can be written then read, even though in_waiting never goes above 8. Anything written after 9 bytes is lost.
  2. With flow control, only 8 bytes can be written then read before write blocks, even though in_waiting never goes above 7. Any attempt to write after 8 bytes is blocked.
  3. Other ports also have perhaps unexpected in_waiting behavior, but those behave consistently and are probably attributable to SDK or hardware buffers.
  4. .written always returns None instead of the number of bytes written.
  5. Unlike raspberrypi and espressif busio.UART, PIO UART with flow control does not hang the serial console when write is blocked. Control-c will interrupt the code.
  6. Unlike some other ports' busio.UART, PIO UART read will drop extra bytes written when the buffer is full, rather than FIFO-ing the bytes in and dropping older bytes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions