LabWired uses declarative YAML specifications to define the register interface of peripherals. This system decouples the hardware description from the implementation logic, ensuring consistent behavior across all simulated devices.
The schema defines the register map, access permissions, and side-effects.
peripheral: "SPI"
version: "1.0"
registers:
- id: "CR1"
address_offset: 0x00
size: 16
access: "R/W"
reset_value: 0x0000
fields:
- name: "SPE"
bit_range: [6, 6]
description: "SPI Enable"
access: "R/W"
- id: "DR"
address_offset: 0x0C
size: 16
access: "R/W"
side_effects:
on_read: "clear_rxne"
on_write: "start_tx"- id: Unique identifier for the register.
- address_offset: Byte offset from the peripheral base address.
- access: Access permissions (
R,W,R/W). Violations trigger a BusFault. - side_effects: Hooks that invoke custom Rust logic when the register is accessed.
The declarative system consists of three phases:
- Parsing: The
labwired-configcrate deserializes the YAML into aPeripheralDescriptorintermediate representation (IR). - Runtime: The
GenericPeripheralimplementation inlabwired-coreuses this descriptor to serveread()andwrite()requests. It handles bounds checking, access permissions, and bit masking automatically. - Hooks: The
GenericPeripheraldelegates to aHookHandlertrait when a side-effect (e.g.,on_write: "start_tx") is triggered.
- Generation: Use
svd-to-yamlto generate the initial descriptor from vendor SVD files. - Refinement: Manually add
side_effectsto registers that require custom logic (e.g., triggering a state machine transition). - Implementation: Implement the corresponding hook functions in Rust.