libboard_zynq: add GlobalTimer implementation
This commit is contained in:
parent
04c47b9bdb
commit
f835192c0a
|
@ -15,3 +15,5 @@ pub mod ddr;
|
||||||
pub mod mpcore;
|
pub mod mpcore;
|
||||||
pub mod flash;
|
pub mod flash;
|
||||||
pub mod dmac;
|
pub mod dmac;
|
||||||
|
pub mod time;
|
||||||
|
pub mod timer;
|
||||||
|
|
|
@ -18,6 +18,34 @@ pub struct RegisterBlock {
|
||||||
reserved1: [u32; 2],
|
reserved1: [u32; 2],
|
||||||
pub scu_access_control: RW<u32>,
|
pub scu_access_control: RW<u32>,
|
||||||
pub scu_non_secure_access_control: RW<u32>,
|
pub scu_non_secure_access_control: RW<u32>,
|
||||||
|
reserved2: [u32; 42],
|
||||||
|
pub iccicr: RW<u32>,
|
||||||
|
pub iccpmw: RW<u32>,
|
||||||
|
pub iccbpr: RW<u32>,
|
||||||
|
pub icciar: RW<u32>,
|
||||||
|
pub icceoir: RW<u32>,
|
||||||
|
pub iccrpr: RW<u32>,
|
||||||
|
pub icchpir: RW<u32>,
|
||||||
|
pub iccabpr: RW<u32>,
|
||||||
|
reserved3: [u32; 55],
|
||||||
|
pub iccidr: RW<u32>,
|
||||||
|
pub global_timer_counter0: ValueRegister,
|
||||||
|
pub global_timer_counter1: ValueRegister,
|
||||||
|
pub global_timer_control: GlobalTimerControl,
|
||||||
|
pub global_timer_interrupt_status: RW<u32>,
|
||||||
|
pub comparator_value0: ValueRegister,
|
||||||
|
pub comparator_value1: ValueRegister,
|
||||||
|
pub auto_increment: ValueRegister,
|
||||||
|
reserved4: [u32; 249],
|
||||||
|
pub private_timer_load: ValueRegister,
|
||||||
|
pub private_timer_counter: ValueRegister,
|
||||||
|
pub private_timer_control: RW<u32>,
|
||||||
|
pub private_timer_interrupt_status: RW<u32>,
|
||||||
|
reserved5: [u32; 4],
|
||||||
|
pub watchdog_load: ValueRegister,
|
||||||
|
pub watchdog_counter: ValueRegister,
|
||||||
|
pub watchdog_control: RW<u32>,
|
||||||
|
pub watchdog_interrupt_status: RW<u32>,
|
||||||
// there is plenty more (unimplemented)
|
// there is plenty more (unimplemented)
|
||||||
}
|
}
|
||||||
register_at!(RegisterBlock, 0xF8F00000, new);
|
register_at!(RegisterBlock, 0xF8F00000, new);
|
||||||
|
@ -59,3 +87,13 @@ impl ScuInvalidate {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
register!(value_register, ValueRegister, RW, u32);
|
||||||
|
register_bits!(value_register, value, u32, 0, 31);
|
||||||
|
|
||||||
|
register!(global_timer_control, GlobalTimerControl, RW, u32);
|
||||||
|
register_bits!(global_timer_control, prescaler, u16, 8, 15);
|
||||||
|
register_bit!(global_timer_control, auto_increment_mode, 3);
|
||||||
|
register_bit!(global_timer_control, irq_enable, 2);
|
||||||
|
register_bit!(global_timer_control, comp_enablea, 1);
|
||||||
|
register_bit!(global_timer_control, timer_enable, 0);
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
#[derive(Debug, Clone, PartialEq, PartialOrd)]
|
||||||
|
pub struct Milliseconds(pub u64);
|
|
@ -0,0 +1,59 @@
|
||||||
|
use libregister::{RegisterR, RegisterW};
|
||||||
|
use crate::{
|
||||||
|
clocks::Clocks,
|
||||||
|
mpcore,
|
||||||
|
time::Milliseconds,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct GlobalTimer {
|
||||||
|
regs: &'static mut mpcore::RegisterBlock,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GlobalTimer {
|
||||||
|
pub fn new() -> GlobalTimer {
|
||||||
|
let regs = mpcore::RegisterBlock::new();
|
||||||
|
GlobalTimer { regs }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
// Disable
|
||||||
|
self.regs.global_timer_control.write(
|
||||||
|
mpcore::GlobalTimerControl::zeroed()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Reset counters
|
||||||
|
self.regs.global_timer_counter0.write(
|
||||||
|
mpcore::ValueRegister::zeroed()
|
||||||
|
);
|
||||||
|
self.regs.global_timer_counter1.write(
|
||||||
|
mpcore::ValueRegister::zeroed()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Start
|
||||||
|
self.regs.global_timer_control.write(
|
||||||
|
mpcore::GlobalTimerControl::zeroed()
|
||||||
|
.prescaler(255)
|
||||||
|
.auto_increment_mode(true)
|
||||||
|
.timer_enable(true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_counter(&self) -> u64 {
|
||||||
|
loop {
|
||||||
|
let c1 = self.regs.global_timer_counter1.read().value();
|
||||||
|
let c0 = self.regs.global_timer_counter0.read().value();
|
||||||
|
let c1_post = self.regs.global_timer_counter1.read().value();
|
||||||
|
|
||||||
|
if c1 == c1_post {
|
||||||
|
return ((c1 as u64) << 32) | (c0 as u64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_time(&self) -> Milliseconds {
|
||||||
|
let prescaler = self.regs.global_timer_control.read().prescaler() as u64;
|
||||||
|
let clocks = Clocks::get();
|
||||||
|
|
||||||
|
Milliseconds(self.get_counter() * (prescaler + 1) / (clocks.cpu_3x2x() as u64 / 1000))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
mod global;
|
||||||
|
pub use global::GlobalTimer;
|
Loading…
Reference in New Issue