mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-05-25 19:56:09 +02:00
Add newtype for interrupt ID.
This commit is contained in:
parent
cddf766491
commit
8cdb93cc74
@ -53,14 +53,58 @@ macro_rules! write_sysreg {
|
|||||||
/// The offset in bytes from `RD_base` to `SGI_base`.
|
/// The offset in bytes from `RD_base` to `SGI_base`.
|
||||||
const SGI_OFFSET: usize = 0x10000;
|
const SGI_OFFSET: usize = 0x10000;
|
||||||
|
|
||||||
/// The ID of the first Software Generated Interrupt.
|
/// An interrupt ID.
|
||||||
pub const SGI_START: u32 = 0;
|
#[derive(Copy, Clone, Debug, Eq, Ord, PartialOrd, PartialEq)]
|
||||||
|
pub struct IntId(u32);
|
||||||
|
|
||||||
/// The ID of the first Private Peripheral Interrupt.
|
impl IntId {
|
||||||
pub const PPI_START: u32 = 16;
|
/// The ID of the first Software Generated Interrupt.
|
||||||
|
const SGI_START: u32 = 0;
|
||||||
|
|
||||||
/// The ID of the first Shared Peripheral Interrupt.
|
/// The ID of the first Private Peripheral Interrupt.
|
||||||
pub const SPI_START: u32 = 32;
|
const PPI_START: u32 = 16;
|
||||||
|
|
||||||
|
/// The ID of the first Shared Peripheral Interrupt.
|
||||||
|
const SPI_START: u32 = 32;
|
||||||
|
|
||||||
|
/// The first special interrupt ID.
|
||||||
|
const SPECIAL_START: u32 = 1020;
|
||||||
|
|
||||||
|
/// Returns the interrupt ID for the given Software Generated Interrupt.
|
||||||
|
pub const fn sgi(sgi: u32) -> Self {
|
||||||
|
assert!(sgi < Self::PPI_START);
|
||||||
|
Self(Self::SGI_START + sgi)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the interrupt ID for the given Private Peripheral Interrupt.
|
||||||
|
pub const fn ppi(ppi: u32) -> Self {
|
||||||
|
assert!(ppi < Self::SPI_START - Self::PPI_START);
|
||||||
|
Self(Self::PPI_START + ppi)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the interrupt ID for the given Shared Peripheral Interrupt.
|
||||||
|
pub const fn spi(spi: u32) -> Self {
|
||||||
|
assert!(spi < Self::SPECIAL_START);
|
||||||
|
Self(Self::SPI_START + spi)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether this interrupt ID is for a Software Generated Interrupt.
|
||||||
|
fn is_sgi(self) -> bool {
|
||||||
|
self.0 < Self::PPI_START
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether this interrupt ID is private to a core, i.e. it is an
|
||||||
|
/// SGI or PPI.
|
||||||
|
fn is_private(self) -> bool {
|
||||||
|
self.0 < Self::SPI_START
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<IntId> for u32 {
|
||||||
|
fn from(intid: IntId) -> Self {
|
||||||
|
intid.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
@ -408,9 +452,9 @@ impl GicV3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Enables or disables the interrupt with the given ID.
|
/// Enables or disables the interrupt with the given ID.
|
||||||
pub fn enable_interrupt(&mut self, intid: u32, enable: bool) {
|
pub fn enable_interrupt(&mut self, intid: IntId, enable: bool) {
|
||||||
let index = (intid / 32) as usize;
|
let index = (intid.0 / 32) as usize;
|
||||||
let bit = 1 << (intid % 32);
|
let bit = 1 << (intid.0 % 32);
|
||||||
|
|
||||||
// Safe because we know that `self.gicd` is a valid and unique pointer
|
// Safe because we know that `self.gicd` is a valid and unique pointer
|
||||||
// to the registers of a GIC distributor interface, and `self.sgi` to
|
// to the registers of a GIC distributor interface, and `self.sgi` to
|
||||||
@ -418,12 +462,12 @@ impl GicV3 {
|
|||||||
unsafe {
|
unsafe {
|
||||||
if enable {
|
if enable {
|
||||||
addr_of_mut!((*self.gicd).isenabler[index]).write_volatile(bit);
|
addr_of_mut!((*self.gicd).isenabler[index]).write_volatile(bit);
|
||||||
if intid < SPI_START {
|
if intid.is_private() {
|
||||||
addr_of_mut!((*self.sgi).isenabler0).write_volatile(bit);
|
addr_of_mut!((*self.sgi).isenabler0).write_volatile(bit);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
addr_of_mut!((*self.gicd).icenabler[index]).write_volatile(bit);
|
addr_of_mut!((*self.gicd).icenabler[index]).write_volatile(bit);
|
||||||
if intid < SPI_START {
|
if intid.is_private() {
|
||||||
addr_of_mut!((*self.sgi).icenabler0).write_volatile(bit);
|
addr_of_mut!((*self.sgi).icenabler0).write_volatile(bit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -470,33 +514,33 @@ impl GicV3 {
|
|||||||
///
|
///
|
||||||
/// Note that lower numbers correspond to higher priorities; i.e. 0 is the
|
/// Note that lower numbers correspond to higher priorities; i.e. 0 is the
|
||||||
/// highest priority, and 255 is the lowest.
|
/// highest priority, and 255 is the lowest.
|
||||||
pub fn set_interrupt_priority(&mut self, intid: u32, priority: u8) {
|
pub fn set_interrupt_priority(&mut self, intid: IntId, priority: u8) {
|
||||||
// Safe because we know that `self.gicd` is a valid and unique pointer
|
// Safe because we know that `self.gicd` is a valid and unique pointer
|
||||||
// to the registers of a GIC distributor interface, and `self.sgi` to
|
// to the registers of a GIC distributor interface, and `self.sgi` to
|
||||||
// the SGI and PPI registers of a GIC redistributor interface.
|
// the SGI and PPI registers of a GIC redistributor interface.
|
||||||
unsafe {
|
unsafe {
|
||||||
// Affinity routing is enabled, so use the GICR for SGIs and PPIs.
|
// Affinity routing is enabled, so use the GICR for SGIs and PPIs.
|
||||||
if intid < SPI_START {
|
if intid.is_private() {
|
||||||
addr_of_mut!((*self.sgi).ipriorityr[intid as usize])
|
addr_of_mut!((*self.sgi).ipriorityr[intid.0 as usize])
|
||||||
.write_volatile(priority);
|
.write_volatile(priority);
|
||||||
} else {
|
} else {
|
||||||
addr_of_mut!((*self.gicd).ipriorityr[intid as usize])
|
addr_of_mut!((*self.gicd).ipriorityr[intid.0 as usize])
|
||||||
.write_volatile(priority);
|
.write_volatile(priority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configures the trigger type for the interrupt with the given ID.
|
/// Configures the trigger type for the interrupt with the given ID.
|
||||||
pub fn set_trigger(&mut self, intid: u32, trigger: Trigger) {
|
pub fn set_trigger(&mut self, intid: IntId, trigger: Trigger) {
|
||||||
let index = (intid / 16) as usize;
|
let index = (intid.0 / 16) as usize;
|
||||||
let bit = 1 << (((intid % 16) * 2) + 1);
|
let bit = 1 << (((intid.0 % 16) * 2) + 1);
|
||||||
|
|
||||||
// Safe because we know that `self.gicd` is a valid and unique pointer
|
// Safe because we know that `self.gicd` is a valid and unique pointer
|
||||||
// to the registers of a GIC distributor interface, and `self.sgi` to
|
// to the registers of a GIC distributor interface, and `self.sgi` to
|
||||||
// the SGI and PPI registers of a GIC redistributor interface.
|
// the SGI and PPI registers of a GIC redistributor interface.
|
||||||
unsafe {
|
unsafe {
|
||||||
// Affinity routing is enabled, so use the GICR for SGIs and PPIs.
|
// Affinity routing is enabled, so use the GICR for SGIs and PPIs.
|
||||||
let register = if intid < SPI_START {
|
let register = if intid.is_private() {
|
||||||
addr_of_mut!((*self.sgi).icfgr[index])
|
addr_of_mut!((*self.sgi).icfgr[index])
|
||||||
} else {
|
} else {
|
||||||
addr_of_mut!((*self.gicd).icfgr[index])
|
addr_of_mut!((*self.gicd).icfgr[index])
|
||||||
@ -511,19 +555,26 @@ impl GicV3 {
|
|||||||
|
|
||||||
/// Gets the ID of the highest priority signalled interrupt, and
|
/// Gets the ID of the highest priority signalled interrupt, and
|
||||||
/// acknowledges it.
|
/// acknowledges it.
|
||||||
pub fn get_and_acknowledge_interrupt() -> u32 {
|
///
|
||||||
|
/// Returns `None` if there is no pending interrupt of sufficient priority.
|
||||||
|
pub fn get_and_acknowledge_interrupt() -> Option<IntId> {
|
||||||
// Safe because reading this system register doesn't access memory in
|
// Safe because reading this system register doesn't access memory in
|
||||||
// any way.
|
// any way.
|
||||||
(unsafe { read_sysreg!(icc_iar1_el1) }) as u32
|
let intid = unsafe { read_sysreg!(icc_iar1_el1) } as u32;
|
||||||
|
if intid == IntId::SPECIAL_START {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(IntId(intid))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Informs the interrupt controller that the CPU has completed processing
|
/// Informs the interrupt controller that the CPU has completed processing
|
||||||
/// the given interrupt. This drops the interrupt priority and deactivates
|
/// the given interrupt. This drops the interrupt priority and deactivates
|
||||||
/// the interrupt.
|
/// the interrupt.
|
||||||
pub fn end_interrupt(intid: u32) {
|
pub fn end_interrupt(intid: IntId) {
|
||||||
// Safe because writing to this system register doesn't access memory in
|
// Safe because writing to this system register doesn't access memory in
|
||||||
// any way.
|
// any way.
|
||||||
unsafe { write_sysreg!(icc_eoir1_el1, intid.into()) }
|
unsafe { write_sysreg!(icc_eoir1_el1, intid.0.into()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ mod pl011;
|
|||||||
// ANCHOR_END: top
|
// ANCHOR_END: top
|
||||||
mod pl031;
|
mod pl031;
|
||||||
|
|
||||||
use crate::gicv3::{irq_enable, wfi, GicV3, Trigger, SPI_START};
|
use crate::gicv3::{irq_enable, wfi, GicV3, IntId, Trigger};
|
||||||
use crate::pl031::Rtc;
|
use crate::pl031::Rtc;
|
||||||
use chrono::{TimeZone, Utc};
|
use chrono::{TimeZone, Utc};
|
||||||
use core::hint::spin_loop;
|
use core::hint::spin_loop;
|
||||||
@ -43,8 +43,8 @@ const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;
|
|||||||
|
|
||||||
/// Base address of the PL031 RTC.
|
/// Base address of the PL031 RTC.
|
||||||
const PL031_BASE_ADDRESS: *mut u32 = 0x901_0000 as _;
|
const PL031_BASE_ADDRESS: *mut u32 = 0x901_0000 as _;
|
||||||
/// The IRQ used by the PL031 RTC: SPI 2.
|
/// The IRQ used by the PL031 RTC.
|
||||||
const PL031_IRQ: u32 = SPI_START + 2;
|
const PL031_IRQ: IntId = IntId::spi(2);
|
||||||
|
|
||||||
// ANCHOR: main
|
// ANCHOR: main
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user