add TTC driver
This commit is contained in:
parent
198e17c134
commit
90423f6fee
@ -23,6 +23,7 @@ pub mod slcr;
|
|||||||
pub mod spi;
|
pub mod spi;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod uart;
|
pub mod uart;
|
||||||
|
pub mod ttc;
|
||||||
|
|
||||||
/// This enumeration encodes the various boot sources.
|
/// This enumeration encodes the various boot sources.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
45
zynq7000-hal/src/ttc.rs
Normal file
45
zynq7000-hal/src/ttc.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
//! Triple-timer counter (TTC) high-level driver.
|
||||||
|
|
||||||
|
use arbitrary_int::u3;
|
||||||
|
|
||||||
|
use crate::gpio::{IoPeriph, Mio30, Mio31, MioPin, MuxConf, PinMode};
|
||||||
|
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||||
|
use crate::gpio::{Mio18, Mio19, Mio42, Mio43};
|
||||||
|
|
||||||
|
/// Each TTC consists of three independent timers/counters.
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub enum TtcId {
|
||||||
|
Ttc0 = 0,
|
||||||
|
Ttc1 = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const TTC_MUX_CONF: MuxConf = MuxConf::new_with_l3(u3::new(0b110));
|
||||||
|
|
||||||
|
pub trait ClockInPin {
|
||||||
|
const ID: TtcId;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait WaveOutPin {
|
||||||
|
const ID: TtcId;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! into_ttc {
|
||||||
|
($($Mio:ident),+) => {
|
||||||
|
$(
|
||||||
|
impl <M: PinMode> MioPin<$Mio, M> {
|
||||||
|
/// Convert the pin into a TTC pin by configuring the pin routing via the
|
||||||
|
/// MIO multiplexer bits.
|
||||||
|
pub fn into_ttck(self) -> MioPin<$Mio, IoPeriph> {
|
||||||
|
// Enable pull-ups for the I2C pins.
|
||||||
|
self.into_io_periph(TTC_MUX_CONF, None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)+
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||||
|
into_ttc!(Mio18, Mio19, Mio42, Mio43);
|
||||||
|
into_ttc!(Mio30, Mio31);
|
||||||
|
|
||||||
|
pub struct Pwm {}
|
@ -1,3 +1,4 @@
|
|||||||
|
//! SPI register module.
|
||||||
use arbitrary_int::{u2, u6, u10};
|
use arbitrary_int::{u2, u6, u10};
|
||||||
|
|
||||||
pub const I2C_0_BASE_ADDR: usize = 0xE000_4000;
|
pub const I2C_0_BASE_ADDR: usize = 0xE000_4000;
|
||||||
|
@ -23,6 +23,7 @@ pub mod mpcore;
|
|||||||
pub mod slcr;
|
pub mod slcr;
|
||||||
pub mod spi;
|
pub mod spi;
|
||||||
pub mod uart;
|
pub mod uart;
|
||||||
|
pub mod ttc;
|
||||||
|
|
||||||
static PERIPHERALS_TAKEN: AtomicBool = AtomicBool::new(false);
|
static PERIPHERALS_TAKEN: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
//! SPI register module.
|
||||||
use arbitrary_int::u4;
|
use arbitrary_int::u4;
|
||||||
|
|
||||||
pub const SPI_0_BASE_ADDR: usize = 0xE000_6000;
|
pub const SPI_0_BASE_ADDR: usize = 0xE000_6000;
|
||||||
|
153
zynq7000/src/ttc.rs
Normal file
153
zynq7000/src/ttc.rs
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
//! Triple-timer counter (TTC) register module.
|
||||||
|
use arbitrary_int::u4;
|
||||||
|
|
||||||
|
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||||
|
pub enum ClockSource {
|
||||||
|
Pclk = 0b0,
|
||||||
|
Extewrnal = 0b1,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
pub struct ClockControl {
|
||||||
|
/// When this bit is set and the external clock is selected, the counter clocks on the
|
||||||
|
/// negative edge of the external clock input.
|
||||||
|
#[bit(6, rw)]
|
||||||
|
ext_clk_edge: bool,
|
||||||
|
#[bit(5, rw)]
|
||||||
|
clk_src: ClockSource,
|
||||||
|
#[bits(1..=4, rw)]
|
||||||
|
prescaler: u4,
|
||||||
|
#[bit(0, rw)]
|
||||||
|
prescale_enable: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||||
|
pub enum Mode {
|
||||||
|
Overflow = 0b0,
|
||||||
|
Interval = 0b1,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||||
|
pub enum WavePolarity {
|
||||||
|
/// The waveform output goes from high to low on a match 0 interrupt and returns high on
|
||||||
|
/// overflow or interval interrupt.
|
||||||
|
HighToLowOnMatch1 = 0b0,
|
||||||
|
/// The waveform output goes from low to high on a match 0 interrupt and returns low on
|
||||||
|
/// overflow or interval interrupt.
|
||||||
|
LowToHighOnMatch1 = 0b1,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||||
|
pub enum WaveEnable {
|
||||||
|
Enable = 0b0,
|
||||||
|
Disable = 0b1,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
pub struct CountControl {
|
||||||
|
#[bit(6, rw)]
|
||||||
|
wave_polarity: WavePolarity,
|
||||||
|
/// Output waveform enable, active low. Reset value 1.
|
||||||
|
#[bit(5, rw)]
|
||||||
|
wave_enable_n: WaveEnable,
|
||||||
|
/// Resets the counter and restarts counting. Automatically cleared on restart.
|
||||||
|
#[bit(4, rw)]
|
||||||
|
reset: bool,
|
||||||
|
/// When this bit is set, an interrupt is generated when the count value matches one of the
|
||||||
|
/// three match registers and the corresponding bit is set in the IER register.
|
||||||
|
#[bit(3, rw)]
|
||||||
|
match_enable: bool,
|
||||||
|
/// When this bit is high, the timer counts down.
|
||||||
|
#[bit(2, rw)]
|
||||||
|
decrementing: bool,
|
||||||
|
#[bit(1, rw)]
|
||||||
|
mode: Mode,
|
||||||
|
#[bit(0, rw)]
|
||||||
|
disable: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
pub struct Counter {
|
||||||
|
#[bits(0..=15, r)]
|
||||||
|
count: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
pub struct RwValue {
|
||||||
|
#[bits(0..=15, rw)]
|
||||||
|
value: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
pub struct InterruptStatus {
|
||||||
|
/// Even timer overflow interrupt.
|
||||||
|
#[bit(5, r)]
|
||||||
|
event: bool,
|
||||||
|
#[bit(4, r)]
|
||||||
|
counter_overflow: bool,
|
||||||
|
#[bit(3, r)]
|
||||||
|
match_2: bool,
|
||||||
|
#[bit(2, r)]
|
||||||
|
match_1: bool,
|
||||||
|
#[bit(1, r)]
|
||||||
|
match_0: bool,
|
||||||
|
#[bit(0, r)]
|
||||||
|
interval: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
pub struct InterruptControl {
|
||||||
|
/// Even timer overflow interrupt.
|
||||||
|
#[bit(5, rw)]
|
||||||
|
event: bool,
|
||||||
|
#[bit(4, rw)]
|
||||||
|
counter_overflow: bool,
|
||||||
|
#[bit(3, rw)]
|
||||||
|
match_2: bool,
|
||||||
|
#[bit(2, rw)]
|
||||||
|
match_1: bool,
|
||||||
|
#[bit(1, rw)]
|
||||||
|
match_0: bool,
|
||||||
|
#[bit(0, rw)]
|
||||||
|
interval: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
pub struct EventControl {
|
||||||
|
/// E_Ov bit. When set to 0, the event timer is disabled and set to 0 when an event timer
|
||||||
|
/// register overflow occurs. Otherwise, continue counting on overflow.
|
||||||
|
#[bit(2, rw)]
|
||||||
|
continuous_mode: bool,
|
||||||
|
/// E_Lo bit. When set to 1, counts PCLK cycles during low level duration of the external
|
||||||
|
/// clock. Otherwise, counts it during high level duration.
|
||||||
|
#[bit(1, rw)]
|
||||||
|
count_low_level_of_ext_clk: bool,
|
||||||
|
#[bit(0, rw)]
|
||||||
|
enable: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
pub struct EventCount {
|
||||||
|
#[bits(0..=15, r)]
|
||||||
|
count: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Triple-timer counter
|
||||||
|
#[derive(derive_mmio::Mmio)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Ttc {
|
||||||
|
clk_cntr: [ClockControl; 3],
|
||||||
|
cnt_ctrl: [CountControl; 3],
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
current_counter: [Counter; 3],
|
||||||
|
interval_value: [RwValue; 3],
|
||||||
|
match_value_0: [RwValue; 3],
|
||||||
|
match_value_1: [RwValue; 3],
|
||||||
|
match_value_2: [RwValue; 3],
|
||||||
|
#[mmio(Read)]
|
||||||
|
isr: [InterruptStatus; 3],
|
||||||
|
ier: [InterruptControl; 3],
|
||||||
|
event_cntrl: [EventControl; 3],
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
event_reg: [EventCount; 3],
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
//! UART register module.
|
//! PS UART register module.
|
||||||
use arbitrary_int::u6;
|
use arbitrary_int::u6;
|
||||||
|
|
||||||
pub const UART_0_BASE: usize = 0xE000_0000;
|
pub const UART_0_BASE: usize = 0xE000_0000;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user