Skip to content

Peripherals

Tero models the GR712RC (LEON3FT) and GR740 (LEON4FT) peripherals required to boot RTEMS, plus a fully wired example of a custom DMA peripheral. Every device implements the same IPeripheral interface (src/interfaces/include/tero/iperipheral.hpp), so adding your own is mechanically the same as anything in the reference set.

How to read these pages

Each device page has a Using it part (how to drive the device from a guest or host, register-level behaviour) for users, and an Internals / how it's modelled part for developers. For the framework itself (lifecycle, MMIO dispatch, IRQ/DMA wiring, the port system, validation) see Peripheral system.

Built-in peripherals

Peripheral Class GR712RC base / IRQ GR740 base / IRQ Page
IRQMP — GR712RC multi-processor interrupt controller peripherals::IrqMP 0x80000200 / — IRQMP
IRQAMP — GR740 interrupt controller (sibling IP core) peripherals::IrqAMP 0xFF904000 / — IRQMP
GPTIMER — prescaler + 4 sub-timers peripherals::GPTimer 0x80000300 / 8 0xFF908000 / 1 GPTimer
APBUART — serial port (RX FIFO + IRQ) peripherals::ApbUart 0x80000100 / 2 (console)
0x801001xx / 17..21
0xFF900000 / 29 (console)
0xFF901000 / 30
APBUART
MEMCTRL (FTMCTRL) — memory-controller stub peripherals::MemCtrl 0x80000000 / — 0xFFE00000 / — MemCtrl
GRGPIO — 32-pin general-purpose I/O port peripherals::GrGpio 0x80000900 & 0x80000A00 / 1..15 header: tero/peripherals/grgpio.hpp
RAM — generic memory entity (primary RAM, on-chip blocks) peripherals::Ram from cfg.ram_base / — 0x00000000 / — Memory
ROM — immutable memory entity (boot PROM, mkprom2 images) peripherals::Rom from cfg.prom_base / — (none by default) Memory
FTAHBRAM — on-chip-RAM-with-EDAC config register peripherals::FtAhbRam 0x80100000 / — (n/a) Memory

The base addresses and IRQ lines above are exactly what the SoC recipes (gr712rc_config() / gr740_config() in src/runtime/src/emulator_config.cpp) put into EmulatorConfig::peripherals. They are plain PeripheralSpec data — inspect, mutate, drop, or replace any entry before Emulator::create. The MMIO bases are not a hidden table; they are constructor arguments inside the recipe factories (src/runtime/include/tero/runtime/soc_family.hpp holds the address constants).

IRQMP vs IRQAMP

GR712RC ships an IRQMP; GR740 ships an IRQAMP — distinct interrupt controllers from GRLIB (Gaisler's open-source LEON¾ IP-core library). IRQAMP adds a timestamp-counter block and shares the classic register subset. Tero models them as separate peripherals (peripherals::IrqMP / peripherals::IrqAMP) so GR740-only behaviour never perturbs the GR712RC implementation. The recipe picks the right one per SocFamily.

How peripherals are assembled

flowchart LR
    R["gr712rc_config()<br/>or gr740_config()"] -->|"populates"| V["cfg.peripherals<br/>vector&lt;PeripheralSpec&gt;"]
    V -->|"Emulator::create"| Val["validate_emulator_config"]
    Val -->|"Emulator::initialize"| I["for each spec:<br/>factory → attach → map on bus"]
    I --> Bus["SystemBus dispatches<br/>CPU/DMA accesses by address"]

Each spec carries an instance_name, a factory, optional irqs, an optional chardev_index, and optional port connections. The runtime walks the vector, instantiates each peripheral, wires its IRQ bridges and chardev, resolves port edges, and maps its MMIO window. See Peripheral system for the full lifecycle.

Custom peripherals

Adding your own is one C++ class plus one PeripheralSpec (or one add_peripheral() call). No CMake changes, no rebuild of tero_runtime, no global registry:

What is shared across all peripherals

Every peripheral conforms to the same contract:

  • reset() returns internal state to its documented reset value.
  • tick(now) advances timed state once per scheduling round (empty for passive devices).
  • Word-only MMIO for the built-in GRLIB devices: byte/half-word accesses return ErrorCode::AlignmentError via peripherals::is_word_access (src/peripherals/include/tero/peripherals/mmio_access.hpp). The APBUART, IRQMP, IRQAMP, GPTIMER, MEMCTRL, and GRGPIO all enforce this; use st/ld (word) instructions, never stb/sth.
  • PeripheralContext injection at attach() — services in, no globals out.

The dedicated device pages below go deeper than this overview: each register, each bit, each side effect, and the GRLIB / GR712RC / GR740 manual section that anchors the behaviour (see references/INDEX.md).