@@ -17,12 +17,15 @@ use core::fmt::{self, Write};
17
17
18
18
// ANCHOR: Flags
19
19
use 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 ) ;
20
26
21
27
bitflags ! {
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 {
26
29
/// Clear to send.
27
30
const CTS = 1 << 0 ;
28
31
/// Data set ready.
@@ -45,11 +48,13 @@ bitflags! {
45
48
}
46
49
// ANCHOR_END: Flags
47
50
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
+
48
56
bitflags ! {
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 {
53
58
/// Framing error.
54
59
const FE = 1 << 0 ;
55
60
/// Parity error.
@@ -62,106 +67,92 @@ bitflags! {
62
67
}
63
68
64
69
// ANCHOR: Registers
70
+ use safe_mmio:: fields:: { ReadPure , ReadPureWrite , ReadWrite , WriteOnly } ;
71
+
65
72
#[ repr( C , align( 4 ) ) ]
66
- struct Registers {
67
- dr : u16 ,
73
+ pub struct Registers {
74
+ dr : ReadWrite < u16 > ,
68
75
_reserved0 : [ u8 ; 2 ] ,
69
- rsr : ReceiveStatus ,
76
+ rsr : ReadPure < ReceiveStatus > ,
70
77
_reserved1 : [ u8 ; 19 ] ,
71
- fr : Flags ,
78
+ fr : ReadPure < Flags > ,
72
79
_reserved2 : [ u8 ; 6 ] ,
73
- ilpr : u8 ,
80
+ ilpr : ReadPureWrite < u8 > ,
74
81
_reserved3 : [ u8 ; 3 ] ,
75
- ibrd : u16 ,
82
+ ibrd : ReadPureWrite < u16 > ,
76
83
_reserved4 : [ u8 ; 2 ] ,
77
- fbrd : u8 ,
84
+ fbrd : ReadPureWrite < u8 > ,
78
85
_reserved5 : [ u8 ; 3 ] ,
79
- lcr_h : u8 ,
86
+ lcr_h : ReadPureWrite < u8 > ,
80
87
_reserved6 : [ u8 ; 3 ] ,
81
- cr : u16 ,
88
+ cr : ReadPureWrite < u16 > ,
82
89
_reserved7 : [ u8 ; 3 ] ,
83
- ifls : u8 ,
90
+ ifls : ReadPureWrite < u8 > ,
84
91
_reserved8 : [ u8 ; 3 ] ,
85
- imsc : u16 ,
92
+ imsc : ReadPureWrite < u16 > ,
86
93
_reserved9 : [ u8 ; 2 ] ,
87
- ris : u16 ,
94
+ ris : ReadPure < u16 > ,
88
95
_reserved10 : [ u8 ; 2 ] ,
89
- mis : u16 ,
96
+ mis : ReadPure < u16 > ,
90
97
_reserved11 : [ u8 ; 2 ] ,
91
- icr : u16 ,
98
+ icr : WriteOnly < u16 > ,
92
99
_reserved12 : [ u8 ; 2 ] ,
93
- dmacr : u8 ,
100
+ dmacr : ReadPureWrite < u8 > ,
94
101
_reserved13 : [ u8 ; 3 ] ,
95
102
}
96
103
// ANCHOR_END: Registers
97
104
98
105
// ANCHOR: Uart
106
+ use safe_mmio:: { UniqueMmioPointer , field, field_shared} ;
107
+
99
108
/// Driver for a PL011 UART.
100
109
#[ derive( Debug ) ]
101
- pub struct Uart {
102
- registers : * mut Registers ,
110
+ pub struct Uart < ' a > {
111
+ registers : UniqueMmioPointer < ' a , Registers > ,
103
112
}
104
113
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 }
116
119
}
117
120
118
121
/// Writes a single byte to the UART.
119
- pub fn write_byte ( & self , byte : u8 ) {
122
+ pub fn write_byte ( & mut self , byte : u8 ) {
120
123
// Wait until there is room in the TX buffer.
121
124
while self . read_flag_register ( ) . contains ( Flags :: TXFF ) { }
122
125
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 ( ) ) ;
129
128
130
129
// Wait until the UART is no longer busy.
131
130
while self . read_flag_register ( ) . contains ( Flags :: BUSY ) { }
132
131
}
133
132
134
133
/// Reads and returns a pending byte, or `None` if nothing has been
135
134
/// received.
136
- pub fn read_byte ( & self ) -> Option < u8 > {
135
+ pub fn read_byte ( & mut self ) -> Option < u8 > {
137
136
if self . read_flag_register ( ) . contains ( Flags :: RXFE ) {
138
137
None
139
138
} 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 ( ) ;
143
140
// TODO: Check for error conditions in bits 8-11.
144
141
Some ( data as u8 )
145
142
}
146
143
}
147
144
148
145
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 ( )
152
147
}
153
148
}
154
149
// ANCHOR_END: Uart
155
150
156
- impl Write for Uart {
151
+ impl Write for Uart < ' _ > {
157
152
fn write_str ( & mut self , s : & str ) -> fmt:: Result {
158
153
for c in s. as_bytes ( ) {
159
154
self . write_byte ( * c) ;
160
155
}
161
156
Ok ( ( ) )
162
157
}
163
158
}
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