@@ -17,12 +17,15 @@ use core::fmt::{self, Write};
1717
1818// ANCHOR: Flags
1919use bitflags:: bitflags;
20+ use zerocopy:: { FromBytes , IntoBytes } ;
21+
22+ /// Flags from the UART flag register.
23+ #[ repr( transparent) ]
24+ #[ derive( Copy , Clone , Debug , Eq , FromBytes , IntoBytes , PartialEq ) ]
25+ struct Flags ( u16 ) ;
2026
2127bitflags ! {
22- /// Flags from the UART flag register.
23- #[ repr( transparent) ]
24- #[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
25- struct Flags : u16 {
28+ impl Flags : u16 {
2629 /// Clear to send.
2730 const CTS = 1 << 0 ;
2831 /// Data set ready.
@@ -45,11 +48,13 @@ bitflags! {
4548}
4649// ANCHOR_END: Flags
4750
51+ /// Flags from the UART Receive Status Register / Error Clear Register.
52+ #[ repr( transparent) ]
53+ #[ derive( Copy , Clone , Debug , Eq , FromBytes , IntoBytes , PartialEq ) ]
54+ struct ReceiveStatus ( u16 ) ;
55+
4856bitflags ! {
49- /// Flags from the UART Receive Status Register / Error Clear Register.
50- #[ repr( transparent) ]
51- #[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
52- struct ReceiveStatus : u16 {
57+ impl ReceiveStatus : u16 {
5358 /// Framing error.
5459 const FE = 1 << 0 ;
5560 /// Parity error.
@@ -62,106 +67,92 @@ bitflags! {
6267}
6368
6469// ANCHOR: Registers
70+ use safe_mmio:: fields:: { ReadPure , ReadPureWrite , ReadWrite , WriteOnly } ;
71+
6572#[ repr( C , align( 4 ) ) ]
66- struct Registers {
67- dr : u16 ,
73+ pub struct Registers {
74+ dr : ReadWrite < u16 > ,
6875 _reserved0 : [ u8 ; 2 ] ,
69- rsr : ReceiveStatus ,
76+ rsr : ReadPure < ReceiveStatus > ,
7077 _reserved1 : [ u8 ; 19 ] ,
71- fr : Flags ,
78+ fr : ReadPure < Flags > ,
7279 _reserved2 : [ u8 ; 6 ] ,
73- ilpr : u8 ,
80+ ilpr : ReadPureWrite < u8 > ,
7481 _reserved3 : [ u8 ; 3 ] ,
75- ibrd : u16 ,
82+ ibrd : ReadPureWrite < u16 > ,
7683 _reserved4 : [ u8 ; 2 ] ,
77- fbrd : u8 ,
84+ fbrd : ReadPureWrite < u8 > ,
7885 _reserved5 : [ u8 ; 3 ] ,
79- lcr_h : u8 ,
86+ lcr_h : ReadPureWrite < u8 > ,
8087 _reserved6 : [ u8 ; 3 ] ,
81- cr : u16 ,
88+ cr : ReadPureWrite < u16 > ,
8289 _reserved7 : [ u8 ; 3 ] ,
83- ifls : u8 ,
90+ ifls : ReadPureWrite < u8 > ,
8491 _reserved8 : [ u8 ; 3 ] ,
85- imsc : u16 ,
92+ imsc : ReadPureWrite < u16 > ,
8693 _reserved9 : [ u8 ; 2 ] ,
87- ris : u16 ,
94+ ris : ReadPure < u16 > ,
8895 _reserved10 : [ u8 ; 2 ] ,
89- mis : u16 ,
96+ mis : ReadPure < u16 > ,
9097 _reserved11 : [ u8 ; 2 ] ,
91- icr : u16 ,
98+ icr : WriteOnly < u16 > ,
9299 _reserved12 : [ u8 ; 2 ] ,
93- dmacr : u8 ,
100+ dmacr : ReadPureWrite < u8 > ,
94101 _reserved13 : [ u8 ; 3 ] ,
95102}
96103// ANCHOR_END: Registers
97104
98105// ANCHOR: Uart
106+ use safe_mmio:: { UniqueMmioPointer , field, field_shared} ;
107+
99108/// Driver for a PL011 UART.
100109#[ derive( Debug ) ]
101- pub struct Uart {
102- registers : * mut Registers ,
110+ pub struct Uart < ' a > {
111+ registers : UniqueMmioPointer < ' a , Registers > ,
103112}
104113
105- impl Uart {
106- /// Constructs a new instance of the UART driver for a PL011 device at the
107- /// given base address.
108- ///
109- /// # Safety
110- ///
111- /// The given base address must point to the 8 MMIO control registers of a
112- /// PL011 device, which must be mapped into the address space of the process
113- /// as device memory and not have any other aliases.
114- pub unsafe fn new ( base_address : * mut u32 ) -> Self {
115- Self { registers : base_address as * mut Registers }
114+ impl < ' a > Uart < ' a > {
115+ /// Constructs a new instance of the UART driver for a PL011 device with the
116+ /// given set of registers.
117+ pub fn new ( registers : UniqueMmioPointer < ' a , Registers > ) -> Self {
118+ Self { registers }
116119 }
117120
118121 /// Writes a single byte to the UART.
119- pub fn write_byte ( & self , byte : u8 ) {
122+ pub fn write_byte ( & mut self , byte : u8 ) {
120123 // Wait until there is room in the TX buffer.
121124 while self . read_flag_register ( ) . contains ( Flags :: TXFF ) { }
122125
123- // SAFETY: We know that self.registers points to the control registers
124- // of a PL011 device which is appropriately mapped.
125- unsafe {
126- // Write to the TX buffer.
127- ( & raw mut ( * self . registers ) . dr ) . write_volatile ( byte. into ( ) ) ;
128- }
126+ // Write to the TX buffer.
127+ field ! ( self . registers, dr) . write ( byte. into ( ) ) ;
129128
130129 // Wait until the UART is no longer busy.
131130 while self . read_flag_register ( ) . contains ( Flags :: BUSY ) { }
132131 }
133132
134133 /// Reads and returns a pending byte, or `None` if nothing has been
135134 /// received.
136- pub fn read_byte ( & self ) -> Option < u8 > {
135+ pub fn read_byte ( & mut self ) -> Option < u8 > {
137136 if self . read_flag_register ( ) . contains ( Flags :: RXFE ) {
138137 None
139138 } else {
140- // SAFETY: We know that self.registers points to the control
141- // registers of a PL011 device which is appropriately mapped.
142- let data = unsafe { ( & raw const ( * self . registers ) . dr ) . read_volatile ( ) } ;
139+ let data = field ! ( self . registers, dr) . read ( ) ;
143140 // TODO: Check for error conditions in bits 8-11.
144141 Some ( data as u8 )
145142 }
146143 }
147144
148145 fn read_flag_register ( & self ) -> Flags {
149- // SAFETY: We know that self.registers points to the control registers
150- // of a PL011 device which is appropriately mapped.
151- unsafe { ( & raw const ( * self . registers ) . fr ) . read_volatile ( ) }
146+ field_shared ! ( self . registers, fr) . read ( )
152147 }
153148}
154149// ANCHOR_END: Uart
155150
156- impl Write for Uart {
151+ impl Write for Uart < ' _ > {
157152 fn write_str ( & mut self , s : & str ) -> fmt:: Result {
158153 for c in s. as_bytes ( ) {
159154 self . write_byte ( * c) ;
160155 }
161156 Ok ( ( ) )
162157 }
163158}
164-
165- // Safe because it just contains a pointer to device memory, which can be
166- // accessed from any context.
167- unsafe impl Send for Uart { }
0 commit comments