UART Operations
Relevant source files
This document covers the core UART operations provided by the Pl011Uart implementation, including initialization, character transmission and reception, status monitoring, and interrupt handling. These operations form the fundamental interface for communicating with PL011 UART hardware controllers.
For details about the underlying register structure and memory layout, see Register Definitions. For complete API documentation and method signatures, see Pl011Uart Methods.
Operation Categories
The Pl011Uart struct provides five main categories of operations implemented through distinct methods that directly manipulate hardware registers:
| Operation Category | Methods | Purpose |
|---|---|---|
| Initialization | init() | Configure UART for operation |
| Character Output | putchar() | Transmit single characters |
| Character Input | getchar() | Receive single characters |
| Interrupt Detection | is_receive_interrupt() | Check for receive interrupts |
| Interrupt Handling | ack_interrupts() | Clear pending interrupts |
Initialization Process
init() Method Operation Flow
flowchart TD
subgraph subGraph0["Register Operations"]
ICR["icr: Interrupt Clear Register"]
IFLS["ifls: FIFO Level Select"]
IMSC["imsc: Interrupt Mask"]
CR["cr: Control Register"]
end
Start["init() called"]
ClearIRQ["Clear all interruptsicr.set(0x7ff)"]
SetFIFO["Set FIFO trigger levelsifls.set(0)"]
EnableRxInt["Enable RX interruptimsc.set(1 << 4)"]
EnableUART["Enable UART componentscr.set(tx|rx|uart enable)"]
Complete["UART ready for operation"]
ClearIRQ --> SetFIFO
EnableRxInt --> EnableUART
EnableUART --> Complete
SetFIFO --> EnableRxInt
Start --> ClearIRQ
The init() method src/pl011.rs(L64 - L76) performs a four-step hardware configuration sequence:
- Interrupt Clearing: Sets
icrregister to0x7ffto clear all pending interrupts - FIFO Configuration: Sets
iflsregister to0for 1/8 RX FIFO and 1/8 TX FIFO trigger levels - Interrupt Enabling: Sets
imscregister bit 4 to enable receive interrupts (rxim) - UART Activation: Sets
crregister bits 0, 8, and 9 to enable transmission, reception, and overall UART operation
Sources: src/pl011.rs(L61 - L76)
Character Transmission
putchar() Operation Flow
flowchart TD
subgraph subGraph0["Register Access"]
FR["fr: Flag Register (Read-Only)"]
DR["dr: Data Register (Read-Write)"]
end
PutChar["putchar(c: u8) called"]
CheckTXFull["Poll fr registerCheck bit 5 (TXFF)"]
IsTXFull["TX FIFO Full?"]
Wait["Wait - continue polling"]
WriteDR["Write character to dr registerdr.set(c as u32)"]
Complete["Character transmitted"]
CheckTXFull --> IsTXFull
IsTXFull --> Wait
IsTXFull --> WriteDR
PutChar --> CheckTXFull
Wait --> CheckTXFull
WriteDR --> Complete
The putchar() method src/pl011.rs(L79 - L82) implements blocking character transmission:
- Status Polling: Continuously reads the
fr(Flag Register) and checks bit 5 (TXFF- Transmit FIFO Full) - Busy Waiting: If bit 5 is set, the transmit FIFO is full and the method continues polling
- Character Writing: When bit 5 is clear, writes the character to the
dr(Data Register) as a 32-bit value
Sources: src/pl011.rs(L78 - L82)
Character Reception
getchar() Operation Flow
flowchart TD
subgraph subGraph0["Register Access"]
FR["fr: Flag Register (Read-Only)"]
DR["dr: Data Register (Read-Write)"]
end
GetChar["getchar() called"]
CheckRXEmpty["Read fr registerCheck bit 4 (RXFE)"]
IsRXEmpty["RX FIFO Empty?"]
ReturnNone["Return None"]
ReadDR["Read character from dr registerdr.get() as u8"]
ReturnSome["Return Some(character)"]
CheckRXEmpty --> IsRXEmpty
GetChar --> CheckRXEmpty
IsRXEmpty --> ReadDR
IsRXEmpty --> ReturnNone
ReadDR --> ReturnSome
The getchar() method src/pl011.rs(L85 - L91) provides non-blocking character reception:
- Status Check: Reads the
fr(Flag Register) and examines bit 4 (RXFE- Receive FIFO Empty) - Conditional Read: If bit 4 is clear (FIFO not empty), reads from the
dr(Data Register) - Return Logic: Returns
Some(u8)if data is available,Noneif FIFO is empty
Sources: src/pl011.rs(L84 - L91)
Interrupt Handling
Interrupt Detection and Acknowledgment
flowchart TD
subgraph subGraph2["Register Types"]
MIS["mis: Masked Interrupt Status (Read-Only)"]
ICR["icr: Interrupt Clear Register (Write-Only)"]
AckInt["ack_interrupts() called"]
CheckInt["is_receive_interrupt() called"]
end
subgraph subGraph0["Interrupt Detection"]
ReturnBool["Return boolean result"]
subgraph subGraph1["Interrupt Acknowledgment"]
MIS["mis: Masked Interrupt Status (Read-Only)"]
AckInt["ack_interrupts() called"]
ClearICR["Write 0x7ff to icr register(clears all interrupt types)"]
IntCleared["All interrupts cleared"]
CheckInt["is_receive_interrupt() called"]
ReadMIS["Read mis register(Masked Interrupt Status)"]
CheckBit4["Check bit 4 (receive interrupt)"]
end
end
AckInt --> ClearICR
CheckBit4 --> ReturnBool
CheckInt --> ReadMIS
ClearICR --> IntCleared
ReadMIS --> CheckBit4
The interrupt handling operations src/pl011.rs(L94 - L102) provide status checking and clearing functionality:
Interrupt Detection (is_receive_interrupt()):
- Reads the
mis(Masked Interrupt Status) register - Checks bit 4 to determine if a receive interrupt is pending
- Returns boolean indicating interrupt status
Interrupt Acknowledgment (ack_interrupts()):
- Writes
0x7ffto theicr(Interrupt Clear Register) - Clears all interrupt types simultaneously
- Used after handling interrupts to reset hardware state
Sources: src/pl011.rs(L93 - L102)
FIFO Management
The PL011 UART controller includes internal FIFOs for both transmission and reception. The implementation configures and interacts with these FIFOs through specific register operations:
| FIFO Aspect | Register | Configuration | Purpose |
|---|---|---|---|
| Trigger Levels | ifls | Set to0 | 1/8 depth triggers for both TX/RX |
| TX Status | frbit 5 | Read-only | Indicates TX FIFO full condition |
| RX Status | frbit 4 | Read-only | Indicates RX FIFO empty condition |
| Data Transfer | dr | Read/Write | Single entry point for FIFO access |
The FIFO configuration ensures efficient interrupt-driven operation while preventing data loss during high-throughput scenarios.
Sources: src/pl011.rs(L68 - L69) src/pl011.rs(L80) src/pl011.rs(L86)
Register Access Patterns
All UART operations follow consistent patterns for hardware register access through the regs() method src/pl011.rs(L57 - L59) :
flowchart TD
subgraph subGraph0["Access Types"]
ReadOnly["ReadOnly (fr, ris, mis)"]
WriteOnly["WriteOnly (icr)"]
ReadWrite["ReadWrite (dr, cr, ifls, imsc)"]
end
Method["UART Method"]
RegsCall["self.regs()"]
UnsafeDeref["unsafe { self.base.as_ref() }"]
RegisterStruct["&Pl011UartRegs"]
SpecificReg["Specific Register Access"]
Method --> RegsCall
RegisterStruct --> SpecificReg
RegsCall --> UnsafeDeref
UnsafeDeref --> RegisterStruct
The regs() method provides type-safe access to memory-mapped registers through the tock-registers crate, ensuring that register access constraints are enforced at compile time.