start adding GIC and GTP driver
This commit is contained in:
parent
7279c96f03
commit
ae6e78e93b
@ -3,6 +3,7 @@
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
use cortex_ar::asm::nop;
|
||||
use zynq7000::{hal::gic::Gic, pac::gic::{Gicc, Gicd}};
|
||||
use zynq7000_rt as _;
|
||||
|
||||
/// One user LED is MIO7
|
||||
@ -19,6 +20,11 @@ pub extern "C" fn boot_core(cpu_id: u32) -> ! {
|
||||
|
||||
#[unsafe(export_name = "main")]
|
||||
pub fn main() -> ! {
|
||||
let mut gic = Gic::new(unsafe { Gicc::new_mmio() }, unsafe { Gicd::new_mmio() });
|
||||
gic.enable_all_interrupts();
|
||||
gic.set_all_spi_interrupt_targets_cpu0();
|
||||
gic.enable();
|
||||
|
||||
let mut gpio = unsafe { zynq7000::pac::gpio::Gpio::new_mmio() };
|
||||
gpio.modify_dirm_0(|v| v | ZEDBOARD_LED_MASK);
|
||||
gpio.modify_out_en_0(|v| v | ZEDBOARD_LED_MASK);
|
||||
@ -30,6 +36,12 @@ pub fn main() -> ! {
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn _irq_handler() {
|
||||
let mut gic = Gic::new(unsafe { Gicc::new_mmio() }, unsafe { Gicd::new_mmio() });
|
||||
|
||||
}
|
||||
|
||||
/// Panic handler
|
||||
#[panic_handler]
|
||||
fn panic(_info: &PanicInfo) -> ! {
|
||||
|
@ -16,6 +16,10 @@ derive-mmio = { path = "../../derive-mmio", default-features = false }
|
||||
bitbybit = "1.3"
|
||||
arbitrary-int = "1.3"
|
||||
thiserror = { version = "2", default-features = false }
|
||||
num_enum = { version = "0.7", default-features = false }
|
||||
critical-section = "1"
|
||||
embassy-time-driver = "0.2"
|
||||
embassy-time-queue-utils = "0.1"
|
||||
# cortex-r
|
||||
# defmt = { version = "0.3", optional = true }
|
||||
# critical-section = { version = "1", optional = true }
|
||||
|
@ -1,14 +1,4 @@
|
||||
use crate::pac::gic::{MmioGicc, MmioGicd};
|
||||
|
||||
pub struct Gic {
|
||||
pub gicc: MmioGicc<'static>,
|
||||
pub gicd: MmioGicd<'static>,
|
||||
}
|
||||
|
||||
pub enum SpiSensitivity {
|
||||
Level = 0b01,
|
||||
Edge = 0b11,
|
||||
}
|
||||
use crate::pac::gic::{Dcr, Icr, MmioGicc, MmioGicd};
|
||||
|
||||
pub const ICFR_2_FIXED_VALUE: u32 = 0b01010101010111010101010001011111;
|
||||
/// This configures PL[2:0] to high-level sensitivity.
|
||||
@ -18,13 +8,159 @@ pub const ICFR_4_FIXED_VALUE: u32 = 0b01110101010101010101010101010101;
|
||||
/// This configures PL[15:8] to high-level sensitivity.
|
||||
pub const ICFR_5_FIXED_VALUE: u32 = 0b00000011010101010101010101010101;
|
||||
|
||||
pub const TARGETS_ALL_CPU_0_IPTR_VAL: u32 = 0x01010101;
|
||||
pub const TARGETS_ALL_CPU_1_IPTR_VAL: u32 = 0x02020202;
|
||||
|
||||
pub const ACTIVATE_ALL_SGIS_MASK_ISER: u32 = 0x0000_FFFF;
|
||||
pub const ACTIVATE_ALL_PPIS_MASK_ISER: u32 = 0xF800_0000;
|
||||
|
||||
pub enum SpiSensitivity {
|
||||
Level = 0b01,
|
||||
Edge = 0b11,
|
||||
}
|
||||
|
||||
pub enum TargetCpu {
|
||||
None = 0b00,
|
||||
Cpu0 = 0b01,
|
||||
Cpu1 = 0b10,
|
||||
Both = 0b11,
|
||||
}
|
||||
|
||||
/// Private Peripheral Interrupt (PPI) which are private to the CPU.
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy, num_enum::TryFromPrimitive)]
|
||||
#[repr(u8)]
|
||||
pub enum PpiInterrupt {
|
||||
GlobalTimer = 27,
|
||||
// Interrupt signal from the PL. CPU0: IRQF2P[18] and CPU1: IRQF2P[19]
|
||||
NFiq = 28,
|
||||
CpuPrivateTimer = 29,
|
||||
/// AWDT0 and AWDT1 for each CPU.
|
||||
Awdt = 30,
|
||||
// Interrupt signal from the PL. CPU0: IRQF2P[16] and CPU1: IRQF2P[17]
|
||||
NIrq = 31,
|
||||
}
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy, num_enum::TryFromPrimitive)]
|
||||
#[repr(u8)]
|
||||
pub enum SpiInterrupt {
|
||||
Cpu0 = 32,
|
||||
Cpu1 = 33,
|
||||
L2Cache = 34,
|
||||
Ocm = 35,
|
||||
_Reserved0 = 36,
|
||||
Pmu0 = 37,
|
||||
Pmu1 = 38,
|
||||
Xadc = 39,
|
||||
DevC = 40,
|
||||
Swdt = 41,
|
||||
Ttc00 = 42,
|
||||
Ttc01 = 43,
|
||||
Ttc02 = 44,
|
||||
DmacAbort = 45,
|
||||
Dmac0 = 46,
|
||||
Dmac1 = 47,
|
||||
Dmac2 = 48,
|
||||
Dmac3 = 49,
|
||||
Smc = 50,
|
||||
Qspi = 51,
|
||||
Gpio = 52,
|
||||
Usb0 = 53,
|
||||
Eth0 = 54,
|
||||
Eth0Wakeup = 55,
|
||||
Sdio0 = 56,
|
||||
I2c0 = 57,
|
||||
Spi0 = 58,
|
||||
Uart0 = 59,
|
||||
Can0 = 60,
|
||||
Pl0 = 61,
|
||||
Pl1 = 62,
|
||||
Pl2 = 63,
|
||||
Pl3 = 64,
|
||||
Pl4 = 65,
|
||||
Pl5 = 66,
|
||||
Pl6 = 67,
|
||||
Pl7 = 68,
|
||||
Ttc10 = 69,
|
||||
Ttc11 = 70,
|
||||
Ttc12 = 71,
|
||||
Dmac4 = 72,
|
||||
Dmac5 = 73,
|
||||
Dmac6 = 74,
|
||||
Dmac7 = 75,
|
||||
Usb1 = 76,
|
||||
Eth1 = 77,
|
||||
Eth1Wakeup = 78,
|
||||
Sdio1 = 79,
|
||||
I2c1 = 80,
|
||||
Spi1 = 81,
|
||||
Uart1 = 82,
|
||||
Can1 = 83,
|
||||
Pl8 = 84,
|
||||
Pl9 = 85,
|
||||
Pl10 = 86,
|
||||
Pl11 = 87,
|
||||
Pl12 = 88,
|
||||
Pl13 = 89,
|
||||
Pl14 = 90,
|
||||
Pl15 = 91,
|
||||
ScuParity = 92,
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("Invalid PL interrupt ID {0}")]
|
||||
pub struct InvalidPlInterruptId(pub u32);
|
||||
pub struct InvalidPlInterruptId(pub usize);
|
||||
|
||||
/// Invalid Shared Peripheral Interrupt (SPI) ID.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("Invalid SPI interrupt ID {0}")]
|
||||
pub struct InvalidSpiInterruptId(pub usize);
|
||||
|
||||
/// Invalid Software Generated Interrupt (SGI) ID.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("Invalid SGI interrupt ID {0}")]
|
||||
pub struct InvalidSgiInterruptId(pub usize);
|
||||
/// Higher-level GIC controller for the Zynq70000 SoC.
|
||||
///
|
||||
/// The flow of using this controller is as follows:
|
||||
///
|
||||
/// 1. Create the controller using [Self::new]. You can use the [crate::pac::gic::Gicc::new_mmio]
|
||||
/// and [crate::pac::gic::Gicd::new_mmio] functions to create the MMIO instances. The
|
||||
/// constructor configures all PL interrupts sensivities to high-level sensitivity and
|
||||
/// configures all sensitivities which are expected to have a certain value.
|
||||
/// 2. Perform the configuration of the interrupt targets and the interrupt sensitivities.
|
||||
/// The CPU targets are encoded with [TargetCpu] while the sensitivities are encoded by
|
||||
/// the [SpiSensitivity] enum. You can use the following API to configure the interrupts:
|
||||
///
|
||||
/// - [Self::set_spi_interrupt_cpu_target]
|
||||
/// - [Self::set_all_spi_interrupt_targets_cpu0]
|
||||
/// - [Self::set_pl_interrupt_sensitivity]
|
||||
///
|
||||
/// 3. Enable all required interrupts. The following API can be used for this:
|
||||
///
|
||||
/// - [Self::enable_sgi_interrupt]
|
||||
/// - [Self::enable_ppi_interrupt]
|
||||
/// - [Self::enable_spi_interrupt]
|
||||
/// - [Self::enable_all_spi_interrupts]
|
||||
/// - [Self::enable_all_ppi_interrupts]
|
||||
/// - [Self::enable_all_sgi_interrupts]
|
||||
/// - [Self::enable_all_interrupts]
|
||||
///
|
||||
/// You might also chose to enable these interrupts at run-time after the GIC was started.
|
||||
/// 4. Start the GIC by calling [Self::update_ctrl_regs] with the required settings or
|
||||
/// with [Self::enable] which assumes a certain configuration.
|
||||
pub struct Gic {
|
||||
pub gicc: MmioGicc<'static>,
|
||||
pub gicd: MmioGicd<'static>,
|
||||
}
|
||||
|
||||
impl Gic {
|
||||
/// Create a new GIC controller instance and calls [Self::initialize] to perform
|
||||
/// strongly recommended initialization routines for the GIC.
|
||||
///
|
||||
#[inline]
|
||||
pub fn new(gicc: MmioGicc<'static>, gicd: MmioGicd<'static>) -> Self {
|
||||
Gic { gicc, gicd }
|
||||
let mut gic = Gic { gicc, gicd };
|
||||
gic.initialize();
|
||||
gic
|
||||
}
|
||||
|
||||
/// Sets up the GIC by configuring the required sensitivites for the shared peripheral
|
||||
@ -35,6 +171,7 @@ impl Gic {
|
||||
/// logic. These are configured to high level sensitivity by this function.
|
||||
/// If you need a different sensitivity, you need to update the bits using the
|
||||
/// [Self::set_pl_interrupt_sensitivity] function.
|
||||
#[inline]
|
||||
pub fn initialize(&mut self) {
|
||||
self.gicd.write_icfr_2_spi(ICFR_2_FIXED_VALUE);
|
||||
self.gicd.write_icfr_3_spi(ICFR_3_FIXED_VALUE);
|
||||
@ -42,9 +179,15 @@ impl Gic {
|
||||
self.gicd.write_icfr_5_spi(ICFR_5_FIXED_VALUE);
|
||||
}
|
||||
|
||||
/// Set the sensitivity of a the Programmable Logic SPI interrupts.
|
||||
///
|
||||
/// These are the only interrupt IDs which are configurable for SPI. They are set
|
||||
/// to high-level sensitivity by default by the [Self::initialize] function. You can
|
||||
/// use this method to override certain sensitivies.
|
||||
#[inline]
|
||||
pub fn set_pl_interrupt_sensitivity(
|
||||
&mut self,
|
||||
pl_int_id: u32,
|
||||
pl_int_id: usize,
|
||||
sensitivity: SpiSensitivity,
|
||||
) -> Result<(), InvalidPlInterruptId> {
|
||||
if pl_int_id >= 16 {
|
||||
@ -73,4 +216,144 @@ impl Gic {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the CPU target for a SPI interrupt.
|
||||
///
|
||||
/// See [Self::set_all_spi_interrupt_targets_cpu0] for a utility method to handle all
|
||||
/// interrupts with one core.
|
||||
#[inline]
|
||||
pub fn set_spi_interrupt_cpu_target(&mut self, spi_int: SpiInterrupt, target: TargetCpu) {
|
||||
let spi_int_raw = spi_int as u32;
|
||||
let spi_offset_to_0 = spi_int_raw as usize - 32;
|
||||
// Unwrap okay, calculated index is always valid.
|
||||
self.gicd
|
||||
.write_iptr_spi(
|
||||
spi_offset_to_0 / 4,
|
||||
(target as u32) << ((spi_offset_to_0 % 4) * 8),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/// Utility function to set all SGI interrupt targets to CPU0.
|
||||
///
|
||||
/// This is useful if only CPU0 is active in a system, or if CPU0 handles most interrupts in
|
||||
/// the system.
|
||||
#[inline]
|
||||
pub fn set_all_spi_interrupt_targets_cpu0(&mut self) {
|
||||
self.gicd
|
||||
.write_iptr_spi(0, TARGETS_ALL_CPU_0_IPTR_VAL)
|
||||
.unwrap();
|
||||
self.gicd
|
||||
.write_iptr_spi(1, TARGETS_ALL_CPU_0_IPTR_VAL)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn enable_sgi_interrupt(&mut self, int_id: usize) -> Result<(), InvalidSpiInterruptId> {
|
||||
if int_id >= 16 {
|
||||
return Err(InvalidSpiInterruptId(int_id));
|
||||
}
|
||||
unsafe { self.gicd.write_iser_unchecked(0, 1 << int_id) };
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn enable_all_sgi_interrupts(&mut self) {
|
||||
// Unwrap okay, index is valid.
|
||||
self.gicd
|
||||
.modify_iser(0, |mut v| {
|
||||
v |= ACTIVATE_ALL_SGIS_MASK_ISER;
|
||||
v
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn enable_ppi_interrupt(&mut self, ppi_int: PpiInterrupt) {
|
||||
// Unwrap okay, index is valid.
|
||||
self.gicd
|
||||
.modify_iser(0, |mut v| {
|
||||
v |= 1 << (ppi_int as u32);
|
||||
v
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn enable_all_ppi_interrupts(&mut self) {
|
||||
unsafe {
|
||||
self.gicd.modify_iser_unchecked(0, |mut v| {
|
||||
v |= ACTIVATE_ALL_PPIS_MASK_ISER;
|
||||
v
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn enable_spi_interrupt(&mut self, spi_int: SpiInterrupt) {
|
||||
let spi_int_raw = spi_int as u32;
|
||||
match spi_int_raw {
|
||||
32..=63 => {
|
||||
let bit_pos = spi_int_raw - 32;
|
||||
// Unwrap okay, valid index.
|
||||
self.gicd.write_iser(1, 1 << bit_pos).unwrap();
|
||||
}
|
||||
64..=92 => {
|
||||
let bit_pos = spi_int_raw - 64;
|
||||
// Unwrap okay, valid index.
|
||||
self.gicd.write_iser(2, 1 << bit_pos).unwrap();
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn enable_all_spi_interrupts(&mut self) {
|
||||
self.gicd.write_iser(1, 0xFFFF_FFFF).unwrap();
|
||||
self.gicd.write_iser(2, 0xFFFF_FFFF).unwrap();
|
||||
}
|
||||
|
||||
/// Enables all interrupts by calling [Self::enable_all_sgi_interrupts],
|
||||
/// [Self::enable_all_ppi_interrupts] and [Self::enable_all_spi_interrupts].
|
||||
pub fn enable_all_interrupts(&mut self) {
|
||||
self.enable_all_sgi_interrupts();
|
||||
self.enable_all_ppi_interrupts();
|
||||
self.enable_all_spi_interrupts();
|
||||
}
|
||||
|
||||
/// Enable the GIC assuming a possibly non-secure configuration.
|
||||
///
|
||||
/// This function will NOT configure and enable the various interrupt sources. You need to
|
||||
/// set the interrupt
|
||||
/// This function configured the control registers with the following settings:
|
||||
///
|
||||
/// - CPU interface: Secure and non-secure interrupts are enabled. SBPR, FIQen and AckCtrl
|
||||
/// fields set to default value 0.
|
||||
/// - Distributor interface: Both non-secure and secure interrupt distribution enabled.
|
||||
///
|
||||
/// It calls [Self::update_ctrl_regs] to update the control registers.
|
||||
/// If you need custom settings, you can call [Self::update_ctrl_regs] with your required
|
||||
/// settings.
|
||||
pub fn enable(&mut self) {
|
||||
self.update_ctrl_regs(
|
||||
Icr::builder()
|
||||
.with_sbpr(false)
|
||||
.with_fiq_en(false)
|
||||
.with_ack_ctrl(false)
|
||||
.with_enable_non_secure(true)
|
||||
.with_enable_secure(true)
|
||||
.build(),
|
||||
Dcr::builder()
|
||||
.with_enable_non_secure(true)
|
||||
.with_enable_secure(true)
|
||||
.build(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Update the control registers which control the safety configuration and which also enable
|
||||
/// the GIC.
|
||||
pub fn update_ctrl_regs(&mut self, icr: Icr, dcr: Dcr) {
|
||||
self.gicc.write_icr(icr);
|
||||
self.gicd.write_dcr(dcr);
|
||||
}
|
||||
}
|
||||
|
34
zynq7000/src/hal/gtc.rs
Normal file
34
zynq7000/src/hal/gtc.rs
Normal file
@ -0,0 +1,34 @@
|
||||
use core::{
|
||||
cell::RefCell,
|
||||
sync::atomic::{compiler_fence, Ordering},
|
||||
};
|
||||
|
||||
use crate::pac::gtc::MmioGtc;
|
||||
|
||||
/// High level GTC driver.
|
||||
pub struct Gtc(pub RefCell<MmioGtc<'static>>);
|
||||
|
||||
impl Gtc {
|
||||
#[inline]
|
||||
pub fn new(mmio_gtc: MmioGtc<'static>) -> Self {
|
||||
Self(RefCell::new(mmio_gtc))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn steal() -> Self {
|
||||
Self::new(unsafe { crate::pac::gtc::Gtc::new_mmio() })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_timer(&self) -> u64 {
|
||||
let mut periph = self.0.borrow_mut();
|
||||
let upper = periph.read_count_upper();
|
||||
loop {
|
||||
let lower = periph.read_count_lower();
|
||||
if periph.read_count_upper() == upper {
|
||||
return ((upper as u64) << 32) | (lower as u64);
|
||||
}
|
||||
// Overflow, read upper again.
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +1,2 @@
|
||||
pub mod gic;
|
||||
pub mod gtc;
|
||||
|
@ -3,5 +3,6 @@
|
||||
|
||||
pub const MPCORE_BASE_ADDR: usize = 0xF8F0_0000;
|
||||
|
||||
pub mod pac;
|
||||
pub mod hal;
|
||||
pub mod pac;
|
||||
pub mod time_driver;
|
||||
|
@ -1,9 +1,9 @@
|
||||
pub use crate::pac::mpcore::{GICC_BASE_ADDR, GICD_BASE_ADDR};
|
||||
use arbitrary_int::{u10, u3, u5};
|
||||
use arbitrary_int::{u3, u5, u10};
|
||||
use static_assertions::const_assert_eq;
|
||||
|
||||
/// Distributor Control Register
|
||||
#[bitbybit::bitfield(u32)]
|
||||
#[bitbybit::bitfield(u32, default = 0x0)]
|
||||
pub struct Dcr {
|
||||
#[bit(1, rw)]
|
||||
enable_non_secure: bool,
|
||||
@ -75,7 +75,10 @@ pub struct Gicd {
|
||||
pub ipr: [u32; 0x18],
|
||||
_reserved_11: [u32; 0xE8],
|
||||
/// Interrupt Processor Targes Registers
|
||||
pub iptr: [u32; 0x18],
|
||||
pub iptr_sgi: [u32; 0x4],
|
||||
// TODO: Mark those read-only as soon as that works for arrays.
|
||||
pub iptr_ppi: [u32; 0x4],
|
||||
pub iptr_spi: [u32; 0x10],
|
||||
// Those are split in the ARM documentation for some reason..
|
||||
_reserved_12: [u32; 0xE8],
|
||||
/// Interrupt Configuration Registers
|
||||
@ -125,7 +128,7 @@ impl Gicd {
|
||||
}
|
||||
|
||||
/// CPU interface control register.
|
||||
#[bitbybit::bitfield(u32)]
|
||||
#[bitbybit::bitfield(u32, default = 0x0)]
|
||||
pub struct Icr {
|
||||
#[bit(4, rw)]
|
||||
sbpr: bool,
|
||||
|
@ -2,6 +2,24 @@
|
||||
|
||||
pub const GTC_BASE_ADDR: usize = crate::pac::mpcore::MPCORE_BASE_ADDR + 0x0000_0200;
|
||||
|
||||
#[bitbybit::bitfield(u32)]
|
||||
pub struct GtcCtrl {
|
||||
#[bits(8..=15, rw)]
|
||||
prescaler: u8,
|
||||
#[bit(2, rw)]
|
||||
irq_enable: bool,
|
||||
#[bit(1, rw)]
|
||||
comparator_enable: bool,
|
||||
#[bit(0, rw)]
|
||||
enable: bool,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32)]
|
||||
pub struct InterruptStatus {
|
||||
#[bit(0, rw)]
|
||||
event_flag: bool,
|
||||
}
|
||||
|
||||
/// Global timer counter.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[mmio(no_ctors)]
|
||||
@ -12,9 +30,9 @@ pub struct Gtc {
|
||||
/// Count register 1, upper 32 bits
|
||||
count_upper: u32,
|
||||
/// Control register
|
||||
ctrl: u32,
|
||||
ctrl: GtcCtrl,
|
||||
/// Interrupt status register
|
||||
isr: u32,
|
||||
isr: InterruptStatus,
|
||||
/// Comparator 0, lower 32 bits
|
||||
comparator_lower: u32,
|
||||
/// Comparator 1, upper 32 bits
|
||||
|
@ -1,6 +1,6 @@
|
||||
pub mod gpio;
|
||||
pub mod uart;
|
||||
pub mod gtc;
|
||||
pub mod slcr;
|
||||
pub mod mpcore;
|
||||
pub mod gic;
|
||||
pub mod gpio;
|
||||
pub mod gtc;
|
||||
pub mod mpcore;
|
||||
pub mod slcr;
|
||||
pub mod uart;
|
||||
|
77
zynq7000/src/time_driver.rs
Normal file
77
zynq7000/src/time_driver.rs
Normal file
@ -0,0 +1,77 @@
|
||||
use core::{
|
||||
cell::{Cell, RefCell},
|
||||
sync::atomic::AtomicU64,
|
||||
};
|
||||
|
||||
use critical_section::{CriticalSection, Mutex};
|
||||
use embassy_time_driver::Driver;
|
||||
use embassy_time_queue_utils::Queue;
|
||||
|
||||
struct AlarmState {
|
||||
timestamp: Cell<u64>,
|
||||
}
|
||||
|
||||
impl AlarmState {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
timestamp: Cell::new(u64::MAX),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for AlarmState {}
|
||||
|
||||
pub struct TimerDriver {
|
||||
periods: AtomicU64,
|
||||
/// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled.
|
||||
alarms: Mutex<AlarmState>,
|
||||
queue: Mutex<RefCell<Queue>>,
|
||||
}
|
||||
|
||||
impl TimerDriver {
|
||||
|
||||
fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
}
|
||||
impl Driver for TimerDriver {
|
||||
fn now(&self) -> u64 {
|
||||
/*
|
||||
if SCALE.get().is_none() {
|
||||
return 0;
|
||||
}
|
||||
let mut period1: u32;
|
||||
let mut period2: u32;
|
||||
let mut counter_val: u32;
|
||||
|
||||
loop {
|
||||
// Acquire ensures that we get the latest value of `periods` and
|
||||
// no instructions can be reordered before the load.
|
||||
period1 = self.periods.load(Ordering::Acquire);
|
||||
|
||||
counter_val = u32::MAX - Self::timekeeper_tim().cnt_value().read().bits();
|
||||
|
||||
// Double read to protect against race conditions when the counter is overflowing.
|
||||
period2 = self.periods.load(Ordering::Relaxed);
|
||||
if period1 == period2 {
|
||||
let now = (((period1 as u64) << 32) | counter_val as u64) / *SCALE.get().unwrap();
|
||||
return now;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
fn schedule_wake(&self, at: u64, waker: &core::task::Waker) {
|
||||
critical_section::with(|cs| {
|
||||
let mut queue = self.queue.borrow(cs).borrow_mut();
|
||||
|
||||
if queue.schedule_wake(at, waker) {
|
||||
let mut next = queue.next_expiration(self.now());
|
||||
while !self.set_alarm(cs, next) {
|
||||
next = queue.next_expiration(self.now());
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user