Register Definitions
Relevant source files
This document details the PL011 UART register definitions implemented in the arm_pl011
crate, including the memory-mapped register structure, individual register specifications, and the type-safe abstractions provided by the tock-registers
library. This covers the hardware abstraction layer that maps PL011 UART controller registers to Rust data structures.
For information about how these registers are used in UART operations, see UART Operations. For the complete API methods that interact with these registers, see Pl011Uart Methods.
Register Structure Overview
The PL011 UART registers are defined using the register_structs!
macro from the tock-registers
crate, which provides compile-time memory layout verification and type-safe register access. The Pl011UartRegs
structure maps the complete PL011 register set to their hardware-defined memory offsets.
Register Memory Layout
flowchart TD subgraph subGraph0["Pl011UartRegs Structure"] DR["dr: ReadWrite0x00 - Data Register"] RES0["_reserved00x04-0x17"] FR["fr: ReadOnly0x18 - Flag Register"] RES1["_reserved10x1C-0x2F"] CR["cr: ReadWrite0x30 - Control Register"] IFLS["ifls: ReadWrite0x34 - Interrupt FIFO Level"] IMSC["imsc: ReadWrite0x38 - Interrupt Mask Set Clear"] RIS["ris: ReadOnly0x3C - Raw Interrupt Status"] MIS["mis: ReadOnly0x40 - Masked Interrupt Status"] ICR["icr: WriteOnly0x44 - Interrupt Clear"] END["@END0x48"] end CR --> IFLS DR --> RES0 FR --> RES1 ICR --> END IFLS --> IMSC IMSC --> RIS MIS --> ICR RES0 --> FR RES1 --> CR RIS --> MIS
Sources: src/pl011.rs(L9 - L32)
Individual Register Definitions
The register structure defines eight functional registers with specific access patterns and purposes:
Register | Offset | Type | Description |
---|---|---|---|
dr | 0x00 | ReadWrite | Data Register - transmit/receive data |
fr | 0x18 | ReadOnly | Flag Register - UART status flags |
cr | 0x30 | ReadWrite | Control Register - UART configuration |
ifls | 0x34 | ReadWrite | Interrupt FIFO Level Select Register |
imsc | 0x38 | ReadWrite | Interrupt Mask Set Clear Register |
ris | 0x3C | ReadOnly | Raw Interrupt Status Register |
mis | 0x40 | ReadOnly | Masked Interrupt Status Register |
icr | 0x44 | WriteOnly | Interrupt Clear Register |
Data Register (dr)
The Data Register at offset 0x00
provides bidirectional data access for character transmission and reception. It supports both read and write operations for handling UART data flow.
Flag Register (fr)
The Flag Register at offset 0x18
provides read-only status information about the UART state, including transmit/receive FIFO status and busy indicators.
Control Register (cr)
The Control Register at offset 0x30
configures UART operational parameters including enable/disable states for transmission, reception, and the overall UART controller.
Sources: src/pl011.rs(L9 - L32)
Type Safety and Memory Mapping
The register definitions leverage the tock-registers
library to provide compile-time guarantees about register access patterns and memory safety:
Register Access Type Safety
flowchart TD subgraph subGraph2["Compile-time Safety"] TYPE_CHECK["Type Checking"] ACCESS_CONTROL["Access Control"] MEMORY_LAYOUT["Memory Layout Verification"] end subgraph subGraph1["Tock-Registers Traits"] READABLE["Readable Interface"] WRITEABLE["Writeable Interface"] end subgraph subGraph0["Access Patterns"] RO["ReadOnlyfr, ris, mis"] RW["ReadWritedr, cr, ifls, imsc"] WO["WriteOnlyicr"] end ACCESS_CONTROL --> MEMORY_LAYOUT READABLE --> TYPE_CHECK RO --> READABLE RW --> READABLE RW --> WRITEABLE TYPE_CHECK --> MEMORY_LAYOUT WO --> WRITEABLE WRITEABLE --> ACCESS_CONTROL
The register_structs!
macro ensures that:
- Register offsets match PL011 hardware specifications
- Reserved memory regions are properly handled
- Access patterns prevent invalid operations (e.g., reading write-only registers)
- Memory layout is validated at compile time
Sources: src/pl011.rs(L3 - L7) src/pl011.rs(L9 - L32)
Register Access Implementation
The Pl011Uart
structure contains a NonNull<Pl011UartRegs>
pointer that provides safe access to the memory-mapped registers. The regs()
method returns a reference to the register structure for performing hardware operations.
Register Access Flow
flowchart TD subgraph subGraph2["Hardware Interface"] MMIO["Memory-Mapped I/O"] PL011_HW["PL011 Hardware"] end subgraph subGraph1["Register Operations"] READ["Register Read Operations"] WRITE["Register Write Operations"] SET["Register Set Operations"] GET["Register Get Operations"] end subgraph subGraph0["Pl011Uart Structure"] BASE["base: NonNull"] REGS_METHOD["regs() -> &Pl011UartRegs"] end BASE --> REGS_METHOD GET --> MMIO MMIO --> PL011_HW READ --> SET REGS_METHOD --> READ REGS_METHOD --> WRITE SET --> MMIO WRITE --> GET
The implementation ensures memory safety through:
- Const construction via
NonNull::new().unwrap().cast()
- Unsafe register access contained within safe method boundaries
- Type-safe register operations through tock-registers interfaces
Sources: src/pl011.rs(L42 - L59)