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 flash;
|
||||
pub mod dmac;
|
||||
pub mod time;
|
||||
pub mod timer;
|
||||
|
|
|
@ -18,6 +18,34 @@ pub struct RegisterBlock {
|
|||
reserved1: [u32; 2],
|
||||
pub scu_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)
|
||||
}
|
||||
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