QUERY · ISSUE
uasyncio StreamWriter concurrency failure
enhancementport-stm32
The following script produces unexpected behaviour on a Pyboard 1.1
import uasyncio as asyncio
from machine import UART
import monitor
from pyb import LED
led = LED(1)
uarts = [] # Pins x9, x3, y9, y1
for n in (1, 2, 3, 6):
uarts.append((UART(n, 9600, timeout=0), n))
async def sender(u, n):
s = f"Hello from UART {n} "# * 55 # 990 chars
swriter = asyncio.StreamWriter(u, {})
while True:
swriter.write(s)
await swriter.drain()
await asyncio.sleep(0)
async def heartbeat():
while True:
await asyncio.sleep_ms(100)
led.toggle()
async def main():
for v in uarts:
asyncio.create_task(sender(*v))
await heartbeat()
asyncio.run(main())
Each instance of swriter.drain appears to block: here is no concurrency.

With 990 character strings (see code comment), the heartbeat LED changes state only once per second, implying that the scheduler is locked for the duration of each write. The LA trace is similar to above, but each burst is ~1s long.
CANDIDATE · ISSUE
uasyncio stream reader/writer: unexpected behaviour with UART
Testing done on Pyboard V1.1. The sender coroutine iterates every 2 seconds but no output appears on pin X1:
import uasyncio as asyncio
from pyb import UART
uart = UART(4, 9600)
async def sender():
swriter = asyncio.StreamWriter(uart, {})
while True:
swriter.awrite('Hello uart\n')
await asyncio.sleep(2)
print('wrote')
loop = asyncio.get_event_loop()
loop.create_task(sender())
loop.run_forever()
The next script produces output on X1 as expected until a loopback is applied (link X1 and X2). At this point the UART sends data continuously. The data is read correctly, but the call to
await asyncio.sleep(2) no longer behaves as expected.
import uasyncio as asyncio
from pyb import UART
uart = UART(4, 9600)
async def sender():
while True:
uart.write('Hello uart\n')
await asyncio.sleep(2)
print('Wrote')
async def receiver():
sreader = asyncio.StreamReader(uart)
while True:
res = await sreader.readline()
print('Recieved', res)
loop = asyncio.get_event_loop()
loop.create_task(sender())
loop.create_task(receiver())
loop.run_forever()