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<PeripheralSpec>"]
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:
- Custom-peripheral walkthrough — step-by-step guide.
- Demo DMA device — the reference example (DMA + IRQ + XOR
mask), annotated, in both spec and
add_peripheralform.
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::AlignmentErrorviaperipherals::is_word_access(src/peripherals/include/tero/peripherals/mmio_access.hpp). The APBUART, IRQMP, IRQAMP, GPTIMER, MEMCTRL, and GRGPIO all enforce this; usest/ld(word) instructions, neverstb/sth. PeripheralContextinjection atattach()— 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).