Skip to content

APBUART — Serial port

GRLIB APBUART (GR712RC §10 / GRLIB IP §28). The primary serial console; the only path between guest software and the host.

Property Value
Default MMIO base 0x80000100
MMIO window size 0x100
Default IRQ 3
RX FIFO depth 8 (Decision 18)
TX FIFO not modelled (immediate drain)
Source file src/peripherals/src/apbuart.cpp

Register map

Offset Name Access Description
0x00 DATA R/W Data register: read pops RX FIFO, write enqueues TX byte
0x04 STATUS R/(W to clear flags) Status flags
0x08 CTRL R/W Control flags (TE/RE/PE/PS/IE/RI/TI/LB/EC/FA/DB)
0x0C SCALER R/W Baud-rate scaler (no observable effect)

All registers are 32-bit. Byte and half-word accesses return AlignmentError.

Control register

Bit Name Description
0 RE Receiver enable
1 TE Transmitter enable (Decision 22 — without this bit, TX is silently dropped)
2 RI Receive interrupt enable
3 TI Transmit interrupt enable
4 PS Parity select
5 PE Parity enable
6 FL Flow control enable
7 LB Loopback enable
8 EC External clock select (no effect)
9 TF Transmit FIFO interrupt
10 RF Receive FIFO interrupt
11 DB Debug enable
31 FA FIFOs available (read-only 1)

Important: RTEMS sets TE=1 during BSP init. Raw assembly tests must do this explicitly or no output will appear (Decision 22). The canonical fixture is tests/asm/hello_uart.S.

Status register

Bit Name Description
0 DR Data ready (RX FIFO non-empty)
1 TS Transmitter shift register empty
2 TE Transmitter empty (always 1, since TX has no FIFO)
3 BR Break received
4 OV Overrun (a byte arrived while RX FIFO was full)
5 PE Parity error
6 FE Framing error
7 ER Errored
26 TF TX FIFO full (always 0)
27 RF RX FIFO full
31 FA FIFOs available (always 1)

Bits 4–7 are W0C (write 0 to clear).

RX path

  1. The runtime calls tick() every quantum.
  2. tick() calls ctx_.chardev->receive(byte) non-blockingly.
  3. If a byte is available and the FIFO has room, push it. Otherwise set STATUS.OV and drop it.
  4. If CTRL.RE && CTRL.RI && fifo non-empty, raise IRQ.

CPU reads from DATA:

  • If FIFO empty → return 0 (per GRLIB convention).
  • Otherwise pop the head, lower the IRQ if the FIFO becomes empty.

TX path

CPU writes to DATA:

  • If CTRL.TE == 0 → silently drop the byte (Decision 22).
  • Otherwise call ctx_.chardev->transmit(byte) immediately.
  • If CTRL.TI == 1, raise IRQ.

There is no TX FIFO and no per-byte timing. The byte hits the host the same simulated cycle it was written.

Reset state

  • STATUS = 0x86 (TS=1, TE=1, FA=1).
  • CTRL = 0.
  • SCALER = 0.
  • RX FIFO empty.

Tests

  • tests/unit/test_apbuart.cpp — register coverage, FIFO push/pop, overrun, IRQ raise on RI, TX dropped without TE, MMIO alignment rejection.
  • tests/integration/test_hello_uart_elf.cpp — drives the assembly fixture end-to-end.
  • The RTEMS hello-world boot test depends on this peripheral.