Skip to content

bcm2835_aux (raspi3) fails when the receive FIFO fills up

Host environment

  • Operating system: Linux
  • OS/kernel version: Linux 5.4.0-77-generic x86_64 GNU/Linux
  • Architecture: x86_64
  • QEMU flavor: qemu-system-aarch64
  • QEMU version: QEMU emulator version 4.2.1 (Debian 1:4.2-3ubuntu6.16)
  • QEMU command line:
    echo abcdefgh | qemu-system-aarch64 -M raspi3 -kernel kernel8.elf -serial null -serial stdio

Emulated/Virtualized environment

  • Operating system: bare-metal see below
  • Architecture: aarch64

Description of problem

When a bare-metal application on the raspi3 board reads the AUX_MU_STAT_REG MMIO register while the device's buffer is at full receive FIFO capacity (i.e. s->read_count == BCM2835_AUX_RX_FIFO_LEN) the assertion assert(s->read_count < BCM2835_AUX_RX_FIFO_LEN) fails.

The assertion in question is currently in line 141 of hw/char/bcm2835_aux.c: https://gitlab.com/qemu-project/qemu/-/blob/9c2647f75004c4f7d64c9c0ec55f8c6f0739a8b1/hw/char/bcm2835_aux.c#L141 but in my current QEMU version, it seems that it was in line 140, but I don't think that has any implication on this error. If the below steps to reproduce are followed, the full output of a normal QEMU (no debugging output or anything) is simply:

$ echo abcdefgh | qemu-system-aarch64 -M raspi3 -kernel kernel8.elf -serial null -serial stdio
qemu-system-aarch64: /build/qemu-71DV4m/qemu-4.2/hw/char/bcm2835_aux.c:140: bcm2835_aux_read: Assertion `s->read_count < BCM2835_AUX_RX_FIFO_LEN' failed.
Aborted (core dumped)

Notice, that there is nothing really wrong with the implementation, if for instance an application that uses the AUX_MU_LSR_REG instead to check whether input is available, everything works as expected. It really seems that just this assertion is wrong. Also notice that the BCM2835 manual (page 18) explicitly allows values inclusive 8.

Steps to reproduce

  1. write a minimal bare-metal application for aarch64 using below main file
  2. compile it with a decent aarch64 compiler, linker script and entry assembly as kernel8.elf
  3. echo abcdefgh | qemu-system-aarch64 -M raspi3 -kernel kernel8.elf -serial null -serial stdio
  4. QEMU crashes with the above state assertion error

Additional information

Minimal bare-metal application (main.c):

#define MMIO_BASE       0x3F000000
#define AUX_MU_STAT     ((volatile unsigned int*)(MMIO_BASE+0x00215064))

void main() {
    while (1) {
        // Just read STAT register to trigger the assertion error
        *AUX_MU_STAT;
    }
}

Also see kernel8.elf.zip for a precompiled version of the above application.

Edited by Cryptjar
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information