1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-05-24 03:10:28 +02:00

Add methods to mask and clear interrupts.

This commit is contained in:
Andrew Walbran 2023-03-31 14:42:28 +01:00
parent d143528e07
commit ce752db15a
2 changed files with 64 additions and 1 deletions

View File

@ -28,7 +28,7 @@ use core::hint::spin_loop;
// ANCHOR: imports
use crate::pl011::Uart;
use core::panic::PanicInfo;
use log::{error, info, LevelFilter};
use log::{error, info, trace, LevelFilter};
use psci::system_off;
/// Base address of the primary PL011 UART.
@ -63,9 +63,43 @@ extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {
"Waiting for {}",
Utc.timestamp_opt(target.into(), 0).unwrap()
);
trace!(
"matched={}, interrupt_pending={}",
rtc.matched(),
rtc.interrupt_pending()
);
while !rtc.matched() {
spin_loop();
}
trace!(
"matched={}, interrupt_pending={}",
rtc.matched(),
rtc.interrupt_pending()
);
info!("Finished waiting");
// Wait another 3 seconds for an interrupt.
let target = timestamp + 6;
info!(
"Waiting for {}",
Utc.timestamp_opt(target.into(), 0).unwrap()
);
rtc.set_match(target);
rtc.clear_interrupt();
rtc.enable_interrupt(true);
trace!(
"matched={}, interrupt_pending={}",
rtc.matched(),
rtc.interrupt_pending()
);
while !rtc.interrupt_pending() {
spin_loop();
}
trace!(
"matched={}, interrupt_pending={}",
rtc.matched(),
rtc.interrupt_pending()
);
info!("Finished waiting");
// ANCHOR: main_end

View File

@ -83,6 +83,35 @@ impl Rtc {
let ris = unsafe { addr_of!((*self.registers).ris).read_volatile() };
(ris & 0x01) != 0
}
/// Returns whether there is currently an interrupt pending.
///
/// This should be true iff `matched` returns true and the interrupt is
/// masked.
pub fn interrupt_pending(&self) -> bool {
// Safe because we know that self.registers points to the control
// registers of a PL031 device which is appropriately mapped.
let ris = unsafe { addr_of!((*self.registers).mis).read_volatile() };
(ris & 0x01) != 0
}
/// Sets or clears the interrupt mask.
///
/// When the mask is true the interrupt is enabled; when it is false the
/// interrupt is disabled.
pub fn enable_interrupt(&mut self, mask: bool) {
let imsc = if mask { 0x01 } else { 0x00 };
// Safe because we know that self.registers points to the control
// registers of a PL031 device which is appropriately mapped.
unsafe { addr_of_mut!((*self.registers).imsc).write_volatile(imsc) }
}
/// Clears a pending interrupt, if any.
pub fn clear_interrupt(&mut self) {
// Safe because we know that self.registers points to the control
// registers of a PL031 device which is appropriately mapped.
unsafe { addr_of_mut!((*self.registers).icr).write_volatile(0x01) }
}
}
// Safe because it just contains a pointer to device memory, which can be