STM32L4x5 USART receives one byte per sec over TCP socket
Host environment
- Operating system: Fedora 44
- OS/kernel version: 7.1.9
- Architecture: x86_64
- QEMU flavor: qemu-system-arm
- QEMU version: commit d2e570cc
- QEMU command line:
qemu-system-arm -M b-l475e-iot01a -cpu cortex-m4 -kernel image.elf -nographic -serial tcp:127.0.0.1:1234,server=on,wait=off -nographic -icount -pidfile qemu.pid
Emulated/Virtualized environment
- Operating system: bare metal
- OS/kernel version: bare metal
- Architecture: ARMv7-M
Description of problem
On bare metal, in a busy-wait loop without interrupts enabled (such as in a hard fault trap handler) the emulated USART input is limited to one byte per second. The path lacks calls to qemu_chr_fe_accept_input() on the event, so only ever drains the socket, one byte at a time, at the ppoll() timeout. This was observed using strace on Linux.
Steps to reproduce
- Run code that busy waits on a USART mapped to a socket in qemu-system-arm with the QEMU command line above
- Run something that connects to it, sends a bunch of bytes, and waits for a response.
- Observe a 1 byte/sec throughput, for example using strace (will recv() exactly one byte on each ppoll timeout)
Additional information
Observed fix below. I'm not totally familiar with QEMU, so this may be the wrong place or way to fix it, but I can observe it behaving like I'd expect with this change.
diff --git a/hw/char/stm32l4x5_usart.c b/hw/char/stm32l4x5_usart.c
index dd1b099195..0b02dde1f8 100644
--- a/hw/char/stm32l4x5_usart.c
+++ b/hw/char/stm32l4x5_usart.c
@@ -441,6 +441,7 @@ static uint64_t stm32l4x5_usart_base_read(void *opaque, hwaddr addr,
/* Reset RXNE flag */
s->isr &= ~R_ISR_RXNE_MASK;
stm32l4x5_update_irq(s);
+ qemu_chr_fe_accept_input(&s->chr);
break;
case A_TDR:
retvalue = FIELD_EX32(s->tdr, TDR, TDR);Basically, the function stm32l4x5_usart_base_read() doesn't actually read.
The commit is the HEAD of the github mirror as of a hour or two ago. I didn't realize the codebase actually lives on gitlab until later... But I quickly checked the file here on gitlab, and it also lacks the actual read.