add TTC driver

This commit is contained in:
Robin Müller 2025-04-01 10:59:23 +02:00
parent 198e17c134
commit 90423f6fee
Signed by: muellerr
GPG Key ID: A649FB78196E3849
7 changed files with 203 additions and 1 deletions

View File

@ -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
View 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 {}

View File

@ -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;

View File

@ -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);

View File

@ -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
View 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],
}

View File

@ -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;