diff --git a/src/libboard_artiqzynq/Cargo.toml b/src/libboard_artiq/Cargo.toml similarity index 86% rename from src/libboard_artiqzynq/Cargo.toml rename to src/libboard_artiq/Cargo.toml index a0157f2..ac70ee1 100644 --- a/src/libboard_artiqzynq/Cargo.toml +++ b/src/libboard_artiq/Cargo.toml @@ -1,10 +1,10 @@ [package] -name = "libboard_artiqzynq" +name = "libboard_artiq" version = "0.0.0" authors = ["M-Labs"] [lib] -name = "libboard_artiqzynq" +name = "libboard_artiq" [dependencies] log = "0.4" diff --git a/src/libboard_artiqzynq/drtio_routing.rs b/src/libboard_artiq/drtio_routing.rs similarity index 100% rename from src/libboard_artiqzynq/drtio_routing.rs rename to src/libboard_artiq/drtio_routing.rs diff --git a/src/libboard_artiqzynq/drtioaux.rs b/src/libboard_artiq/drtioaux.rs similarity index 93% rename from src/libboard_artiqzynq/drtioaux.rs rename to src/libboard_artiq/drtioaux.rs index 69a2f80..c0abd4c 100644 --- a/src/libboard_artiqzynq/drtioaux.rs +++ b/src/libboard_artiq/drtioaux.rs @@ -3,8 +3,8 @@ use crc; use io::{ProtoRead, ProtoWrite, Cursor, Error as IoError}; use board_misoc::{csr::DRTIOAUX, mem::DRTIOAUX_MEM}; // <- port -use clock; use proto_artiq::drtioaux_proto::Error as ProtocolError; +use libboard_zynq::{timer::GlobalTimer, time::Milliseconds}; pub use proto_artiq::drtioaux_proto::Packet; @@ -105,11 +105,12 @@ pub fn recv(linkno: u8) -> Result, Error> { }) } -pub fn recv_timeout(linkno: u8, timeout_ms: Option) -> Result> { - let timeout_ms = timeout_ms.unwrap_or(10); - // only place with clock - let limit = clock::get_ms() + timeout_ms; - while clock::get_ms() < limit { +pub fn recv_timeout(linkno: u8, timeout_ms: Option, + timer: GlobalTimer) -> Result> +{ + let timeout_ms = Milliseconds(timeout_ms.unwrap_or(10)); + let limit = timer.get_time() + timeout_ms; + while timer.get_time() < limit { match recv(linkno)? { None => (), Some(packet) => return Ok(packet), diff --git a/src/libboard_artiqzynq/lib.rs b/src/libboard_artiq/lib.rs similarity index 91% rename from src/libboard_artiqzynq/lib.rs rename to src/libboard_artiq/lib.rs index b1b1943..79d0243 100644 --- a/src/libboard_artiqzynq/lib.rs +++ b/src/libboard_artiq/lib.rs @@ -1,5 +1,3 @@ -pub mod clock; - // has csr; taken from runtime main #[path = "../../../build/pl.rs"] pub mod pl; diff --git a/src/libboard_artiqzynq/logger.rs b/src/libboard_artiq/logger.rs similarity index 100% rename from src/libboard_artiqzynq/logger.rs rename to src/libboard_artiq/logger.rs diff --git a/src/libboard_artiqzynq/si5324.rs b/src/libboard_artiq/si5324.rs similarity index 100% rename from src/libboard_artiqzynq/si5324.rs rename to src/libboard_artiq/si5324.rs diff --git a/src/runtime/Cargo.toml b/src/runtime/Cargo.toml index c813611..e87897e 100644 --- a/src/runtime/Cargo.toml +++ b/src/runtime/Cargo.toml @@ -37,3 +37,4 @@ dyld = { path = "../libdyld" } dwarf = { path = "../libdwarf" } unwind = { path = "../libunwind" } libc = { path = "../libc" } +libboard_artiq = { path = "../libboard_artiq" } \ No newline at end of file diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index f4b41a1..dbc21fd 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -23,6 +23,8 @@ use embedded_hal::blocking::delay::DelayMs; use libconfig::Config; use libregister::RegisterW; use libcortex_a9::l2c::enable_l2_cache; +#[cfg(feature = "target_kasli_soc")] +use libboard_artiq::si5324; mod proto_core_io; mod proto_async; @@ -45,8 +47,7 @@ mod mgmt; mod analyzer; mod irq; mod i2c; -#[cfg(feature = "target_kasli_soc")] -mod si5324; + fn init_gateware() { // Set up PS->PL clocks diff --git a/src/runtime/src/si5324.rs b/src/runtime/src/si5324.rs deleted file mode 100644 index 8327fc0..0000000 --- a/src/runtime/src/si5324.rs +++ /dev/null @@ -1,258 +0,0 @@ -use core::result; -use log::info; -use libboard_zynq::i2c::I2c; - -type Result = result::Result; - -const ADDRESS: u8 = 0x68; - -// NOTE: the logical parameters DO NOT MAP to physical values written -// into registers. They have to be mapped; see the datasheet. -// DSPLLsim reports the logical parameters in the design summary, not -// the physical register values. -pub struct FrequencySettings { - pub n1_hs: u8, - pub nc1_ls: u32, - pub n2_hs: u8, - pub n2_ls: u32, - pub n31: u32, - pub n32: u32, - pub bwsel: u8, - pub crystal_ref: bool -} - -pub enum Input { - Ckin1, - Ckin2, -} - -fn map_frequency_settings(settings: &FrequencySettings) -> Result { - if settings.nc1_ls != 0 && (settings.nc1_ls % 2) == 1 { - return Err("NC1_LS must be 0 or even") - } - if settings.nc1_ls > (1 << 20) { - return Err("NC1_LS is too high") - } - if (settings.n2_ls % 2) == 1 { - return Err("N2_LS must be even") - } - if settings.n2_ls > (1 << 20) { - return Err("N2_LS is too high") - } - if settings.n31 > (1 << 19) { - return Err("N31 is too high") - } - if settings.n32 > (1 << 19) { - return Err("N32 is too high") - } - let r = FrequencySettings { - n1_hs: match settings.n1_hs { - 4 => 0b000, - 5 => 0b001, - 6 => 0b010, - 7 => 0b011, - 8 => 0b100, - 9 => 0b101, - 10 => 0b110, - 11 => 0b111, - _ => return Err("N1_HS has an invalid value") - }, - nc1_ls: settings.nc1_ls - 1, - n2_hs: match settings.n2_hs { - 4 => 0b000, - 5 => 0b001, - 6 => 0b010, - 7 => 0b011, - 8 => 0b100, - 9 => 0b101, - 10 => 0b110, - 11 => 0b111, - _ => return Err("N2_HS has an invalid value") - }, - n2_ls: settings.n2_ls - 1, - n31: settings.n31 - 1, - n32: settings.n32 - 1, - bwsel: settings.bwsel, - crystal_ref: settings.crystal_ref - }; - Ok(r) -} - -fn write(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> { - i2c.start().unwrap(); - if !i2c.write(ADDRESS << 1).unwrap() { - return Err("Si5324 failed to ack write address") - } - if !i2c.write(reg).unwrap() { - return Err("Si5324 failed to ack register") - } - if !i2c.write(val).unwrap() { - return Err("Si5324 failed to ack value") - } - i2c.stop().unwrap(); - Ok(()) -} - -fn write_no_ack_value(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> { - i2c.start().unwrap(); - if !i2c.write(ADDRESS << 1).unwrap() { - return Err("Si5324 failed to ack write address") - } - if !i2c.write(reg).unwrap() { - return Err("Si5324 failed to ack register") - } - i2c.write(val).unwrap(); - i2c.stop().unwrap(); - Ok(()) -} - -fn read(i2c: &mut I2c, reg: u8) -> Result { - i2c.start().unwrap(); - if !i2c.write(ADDRESS << 1).unwrap() { - return Err("Si5324 failed to ack write address") - } - if !i2c.write(reg).unwrap() { - return Err("Si5324 failed to ack register") - } - i2c.restart().unwrap(); - if !i2c.write((ADDRESS << 1) | 1).unwrap() { - return Err("Si5324 failed to ack read address") - } - let val = i2c.read(false).unwrap(); - i2c.stop().unwrap(); - Ok(val) -} - -fn rmw(i2c: &mut I2c, reg: u8, f: F) -> Result<()> where - F: Fn(u8) -> u8 { - let value = read(i2c, reg)?; - write(i2c, reg, f(value))?; - Ok(()) -} - -fn ident(i2c: &mut I2c) -> Result { - Ok(((read(i2c, 134)? as u16) << 8) | (read(i2c, 135)? as u16)) -} - -fn soft_reset(i2c: &mut I2c) -> Result<()> { - //TODO write_no_ack_value(i2c, 136, read(136)? | 0x80)?; - //TODO clock::spin_us(10_000); - Ok(()) -} - -fn has_xtal(i2c: &mut I2c) -> Result { - Ok((read(i2c, 129)? & 0x01) == 0) // LOSX_INT=0 -} - -fn has_ckin(i2c: &mut I2c, input: Input) -> Result { - match input { - Input::Ckin1 => Ok((read(i2c, 129)? & 0x02) == 0), // LOS1_INT=0 - Input::Ckin2 => Ok((read(i2c, 129)? & 0x04) == 0), // LOS2_INT=0 - } -} - -fn locked(i2c: &mut I2c) -> Result { - Ok((read(i2c, 130)? & 0x01) == 0) // LOL_INT=0 -} - -fn monitor_lock(i2c: &mut I2c) -> Result<()> { - info!("waiting for Si5324 lock..."); - // TODO let t = clock::get_ms(); - while !locked(i2c)? { - // Yes, lock can be really slow. - /*if clock::get_ms() > t + 20000 { - return Err("Si5324 lock timeout"); - }*/ - } - info!(" ...locked"); - Ok(()) -} - -fn init(i2c: &mut I2c) -> Result<()> { - info!("init test"); - #[cfg(feature = "target_kasli_soc")] - { - i2c.pca9548_select(0x70, 0)?; - i2c.pca9548_select(0x71, 1 << 3)?; - } - - if ident(i2c)? != 0x0182 { - return Err("Si5324 does not have expected product number"); - } - - soft_reset(i2c)?; - Ok(()) -} - -pub fn bypass(i2c: &mut I2c, input: Input) -> Result<()> { - let cksel_reg = match input { - Input::Ckin1 => 0b00, - Input::Ckin2 => 0b01, - }; - init(i2c)?; - rmw(i2c, 21, |v| v & 0xfe)?; // CKSEL_PIN=0 - rmw(i2c, 3, |v| (v & 0x3f) | (cksel_reg << 6))?; // CKSEL_REG - rmw(i2c, 4, |v| (v & 0x3f) | (0b00 << 6))?; // AUTOSEL_REG=b00 - rmw(i2c, 6, |v| (v & 0xc0) | 0b111111)?; // SFOUT2_REG=b111 SFOUT1_REG=b111 - rmw(i2c, 0, |v| (v & 0xfd) | 0x02)?; // BYPASS_REG=1 - Ok(()) -} - -pub fn setup(i2c: &mut I2c, settings: &FrequencySettings, input: Input) -> Result<()> { - let s = map_frequency_settings(settings)?; - let cksel_reg = match input { - Input::Ckin1 => 0b00, - Input::Ckin2 => 0b01, - }; - - init(i2c)?; - if settings.crystal_ref { - rmw(i2c, 0, |v| v | 0x40)?; // FREE_RUN=1 - } - rmw(i2c, 2, |v| (v & 0x0f) | (s.bwsel << 4))?; - rmw(i2c, 21, |v| v & 0xfe)?; // CKSEL_PIN=0 - rmw(i2c, 3, |v| (v & 0x2f) | (cksel_reg << 6) | 0x10)?; // CKSEL_REG, SQ_ICAL=1 - rmw(i2c, 4, |v| (v & 0x3f) | (0b00 << 6))?; // AUTOSEL_REG=b00 - rmw(i2c, 6, |v| (v & 0xc0) | 0b111111)?; // SFOUT2_REG=b111 SFOUT1_REG=b111 - write(i2c, 25, (s.n1_hs << 5 ) as u8)?; - write(i2c, 31, (s.nc1_ls >> 16) as u8)?; - write(i2c, 32, (s.nc1_ls >> 8 ) as u8)?; - write(i2c, 33, (s.nc1_ls) as u8)?; - write(i2c, 34, (s.nc1_ls >> 16) as u8)?; // write to NC2_LS as well - write(i2c, 35, (s.nc1_ls >> 8 ) as u8)?; - write(i2c, 36, (s.nc1_ls) as u8)?; - write(i2c, 40, (s.n2_hs << 5 ) as u8 | (s.n2_ls >> 16) as u8)?; - write(i2c, 41, (s.n2_ls >> 8 ) as u8)?; - write(i2c, 42, (s.n2_ls) as u8)?; - write(i2c, 43, (s.n31 >> 16) as u8)?; - write(i2c, 44, (s.n31 >> 8) as u8)?; - write(i2c, 45, (s.n31) as u8)?; - write(i2c, 46, (s.n32 >> 16) as u8)?; - write(i2c, 47, (s.n32 >> 8) as u8)?; - write(i2c, 48, (s.n32) as u8)?; - rmw(i2c, 137, |v| v | 0x01)?; // FASTLOCK=1 - rmw(i2c, 136, |v| v | 0x40)?; // ICAL=1 - - if !has_xtal(i2c)? { - return Err("Si5324 misses XA/XB signal"); - } - if !has_ckin(i2c, input)? { - return Err("Si5324 misses clock input signal"); - } - - monitor_lock(i2c)?; - Ok(()) -} - -pub fn select_input(i2c: &mut I2c, input: Input) -> Result<()> { - let cksel_reg = match input { - Input::Ckin1 => 0b00, - Input::Ckin2 => 0b01, - }; - rmw(i2c, 3, |v| (v & 0x3f) | (cksel_reg << 6))?; - if !has_ckin(i2c, input)? { - return Err("Si5324 misses clock input signal"); - } - monitor_lock(i2c)?; - Ok(()) -}