1212// See the License for the specific language governing permissions and
1313// limitations under the License.
1414
15+ use safe_mmio:: fields:: { ReadPure , ReadPureWrite , WriteOnly } ;
16+ use safe_mmio:: { field, field_shared, UniqueMmioPointer } ;
17+
1518// ANCHOR: solution
1619#[ repr( C , align( 4 ) ) ]
17- struct Registers {
20+ pub struct Registers {
1821 /// Data register
19- dr : u32 ,
22+ dr : ReadPure < u32 > ,
2023 /// Match register
21- mr : u32 ,
24+ mr : ReadPureWrite < u32 > ,
2225 /// Load register
23- lr : u32 ,
26+ lr : ReadPureWrite < u32 > ,
2427 /// Control register
25- cr : u8 ,
28+ cr : ReadPureWrite < u8 > ,
2629 _reserved0 : [ u8 ; 3 ] ,
2730 /// Interrupt Mask Set or Clear register
28- imsc : u8 ,
31+ imsc : ReadPureWrite < u8 > ,
2932 _reserved1 : [ u8 ; 3 ] ,
3033 /// Raw Interrupt Status
31- ris : u8 ,
34+ ris : ReadPure < u8 > ,
3235 _reserved2 : [ u8 ; 3 ] ,
3336 /// Masked Interrupt Status
34- mis : u8 ,
37+ mis : ReadPure < u8 > ,
3538 _reserved3 : [ u8 ; 3 ] ,
3639 /// Interrupt Clear Register
37- icr : u8 ,
40+ icr : WriteOnly < u8 > ,
3841 _reserved4 : [ u8 ; 3 ] ,
3942}
4043
4144/// Driver for a PL031 real-time clock.
4245#[ derive( Debug ) ]
43- pub struct Rtc {
44- registers : * mut Registers ,
46+ pub struct Rtc < ' a > {
47+ registers : UniqueMmioPointer < ' a , Registers > ,
4548}
4649
47- impl Rtc {
50+ impl < ' a > Rtc < ' a > {
4851 /// Constructs a new instance of the RTC driver for a PL031 device at the
49- /// given base address.
50- ///
51- /// # Safety
52- ///
53- /// The given base address must point to the MMIO control registers of a
54- /// PL031 device, which must be mapped into the address space of the process
55- /// as device memory and not have any other aliases.
56- pub unsafe fn new ( base_address : * mut u32 ) -> Self {
57- Self { registers : base_address as * mut Registers }
52+ /// given set of registers.
53+ pub unsafe fn new ( registers : UniqueMmioPointer < ' a , Registers > ) -> Self {
54+ Self { registers }
5855 }
5956
6057 /// Reads the current RTC value.
6158 pub fn read ( & self ) -> u32 {
62- // SAFETY: We know that self.registers points to the control registers
63- // of a PL031 device which is appropriately mapped.
64- unsafe { ( & raw const ( * self . registers ) . dr ) . read_volatile ( ) }
59+ field_shared ! ( self . registers, dr) . read ( )
6560 }
6661
6762 /// Writes a match value. When the RTC value matches this then an interrupt
6863 /// will be generated (if it is enabled).
6964 pub fn set_match ( & mut self , value : u32 ) {
70- // SAFETY: We know that self.registers points to the control registers
71- // of a PL031 device which is appropriately mapped.
72- unsafe { ( & raw mut ( * self . registers ) . mr ) . write_volatile ( value) }
65+ field ! ( self . registers, mr) . write ( value) ;
7366 }
7467
7568 /// Returns whether the match register matches the RTC value, whether or not
7669 /// the interrupt is enabled.
7770 pub fn matched ( & self ) -> bool {
78- // SAFETY: We know that self.registers points to the control registers
79- // of a PL031 device which is appropriately mapped.
80- let ris = unsafe { ( & raw const ( * self . registers ) . ris ) . read_volatile ( ) } ;
71+ let ris = field_shared ! ( self . registers, ris) . read ( ) ;
8172 ( ris & 0x01 ) != 0
8273 }
8374
@@ -86,10 +77,8 @@ impl Rtc {
8677 /// This should be true if and only if `matched` returns true and the
8778 /// interrupt is masked.
8879 pub fn interrupt_pending ( & self ) -> bool {
89- // SAFETY: We know that self.registers points to the control registers
90- // of a PL031 device which is appropriately mapped.
91- let ris = unsafe { ( & raw const ( * self . registers ) . mis ) . read_volatile ( ) } ;
92- ( ris & 0x01 ) != 0
80+ let mis = field_shared ! ( self . registers, mis) . read ( ) ;
81+ ( mis & 0x01 ) != 0
9382 }
9483
9584 /// Sets or clears the interrupt mask.
@@ -98,19 +87,11 @@ impl Rtc {
9887 /// interrupt is disabled.
9988 pub fn enable_interrupt ( & mut self , mask : bool ) {
10089 let imsc = if mask { 0x01 } else { 0x00 } ;
101- // SAFETY: We know that self.registers points to the control registers
102- // of a PL031 device which is appropriately mapped.
103- unsafe { ( & raw mut ( * self . registers ) . imsc ) . write_volatile ( imsc) }
90+ field ! ( self . registers, imsc) . write ( imsc) ;
10491 }
10592
10693 /// Clears a pending interrupt, if any.
10794 pub fn clear_interrupt ( & mut self ) {
108- // SAFETY: We know that self.registers points to the control registers
109- // of a PL031 device which is appropriately mapped.
110- unsafe { ( & raw mut ( * self . registers ) . icr ) . write_volatile ( 0x01 ) }
95+ field ! ( self . registers, icr) . write ( 0x01 ) ;
11196 }
11297}
113-
114- // SAFETY: `Rtc` just contains a pointer to device memory, which can be
115- // accessed from any context.
116- unsafe impl Send for Rtc { }
0 commit comments