libboard_artiqzynq -> libboard_artiq; moved si5324
This commit is contained in:
parent
d309409a84
commit
f170104304
@ -1,10 +1,10 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libboard_artiqzynq"
|
name = "libboard_artiq"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
authors = ["M-Labs"]
|
authors = ["M-Labs"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "libboard_artiqzynq"
|
name = "libboard_artiq"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4"
|
log = "0.4"
|
@ -3,8 +3,8 @@ use crc;
|
|||||||
|
|
||||||
use io::{ProtoRead, ProtoWrite, Cursor, Error as IoError};
|
use io::{ProtoRead, ProtoWrite, Cursor, Error as IoError};
|
||||||
use board_misoc::{csr::DRTIOAUX, mem::DRTIOAUX_MEM}; // <- port
|
use board_misoc::{csr::DRTIOAUX, mem::DRTIOAUX_MEM}; // <- port
|
||||||
use clock;
|
|
||||||
use proto_artiq::drtioaux_proto::Error as ProtocolError;
|
use proto_artiq::drtioaux_proto::Error as ProtocolError;
|
||||||
|
use libboard_zynq::{timer::GlobalTimer, time::Milliseconds};
|
||||||
|
|
||||||
pub use proto_artiq::drtioaux_proto::Packet;
|
pub use proto_artiq::drtioaux_proto::Packet;
|
||||||
|
|
||||||
@ -105,11 +105,12 @@ pub fn recv(linkno: u8) -> Result<Option<Packet>, Error<!>> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv_timeout(linkno: u8, timeout_ms: Option<u64>) -> Result<Packet, Error<!>> {
|
pub fn recv_timeout(linkno: u8, timeout_ms: Option<u64>,
|
||||||
let timeout_ms = timeout_ms.unwrap_or(10);
|
timer: GlobalTimer) -> Result<Packet, Error<!>>
|
||||||
// only place with clock
|
{
|
||||||
let limit = clock::get_ms() + timeout_ms;
|
let timeout_ms = Milliseconds(timeout_ms.unwrap_or(10));
|
||||||
while clock::get_ms() < limit {
|
let limit = timer.get_time() + timeout_ms;
|
||||||
|
while timer.get_time() < limit {
|
||||||
match recv(linkno)? {
|
match recv(linkno)? {
|
||||||
None => (),
|
None => (),
|
||||||
Some(packet) => return Ok(packet),
|
Some(packet) => return Ok(packet),
|
@ -1,5 +1,3 @@
|
|||||||
pub mod clock;
|
|
||||||
|
|
||||||
// has csr; taken from runtime main
|
// has csr; taken from runtime main
|
||||||
#[path = "../../../build/pl.rs"]
|
#[path = "../../../build/pl.rs"]
|
||||||
pub mod pl;
|
pub mod pl;
|
@ -37,3 +37,4 @@ dyld = { path = "../libdyld" }
|
|||||||
dwarf = { path = "../libdwarf" }
|
dwarf = { path = "../libdwarf" }
|
||||||
unwind = { path = "../libunwind" }
|
unwind = { path = "../libunwind" }
|
||||||
libc = { path = "../libc" }
|
libc = { path = "../libc" }
|
||||||
|
libboard_artiq = { path = "../libboard_artiq" }
|
@ -23,6 +23,8 @@ use embedded_hal::blocking::delay::DelayMs;
|
|||||||
use libconfig::Config;
|
use libconfig::Config;
|
||||||
use libregister::RegisterW;
|
use libregister::RegisterW;
|
||||||
use libcortex_a9::l2c::enable_l2_cache;
|
use libcortex_a9::l2c::enable_l2_cache;
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
use libboard_artiq::si5324;
|
||||||
|
|
||||||
mod proto_core_io;
|
mod proto_core_io;
|
||||||
mod proto_async;
|
mod proto_async;
|
||||||
@ -45,8 +47,7 @@ mod mgmt;
|
|||||||
mod analyzer;
|
mod analyzer;
|
||||||
mod irq;
|
mod irq;
|
||||||
mod i2c;
|
mod i2c;
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
|
||||||
mod si5324;
|
|
||||||
|
|
||||||
fn init_gateware() {
|
fn init_gateware() {
|
||||||
// Set up PS->PL clocks
|
// Set up PS->PL clocks
|
||||||
|
@ -1,258 +0,0 @@
|
|||||||
use core::result;
|
|
||||||
use log::info;
|
|
||||||
use libboard_zynq::i2c::I2c;
|
|
||||||
|
|
||||||
type Result<T> = result::Result<T, &'static str>;
|
|
||||||
|
|
||||||
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<FrequencySettings> {
|
|
||||||
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<u8> {
|
|
||||||
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<F>(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<u16> {
|
|
||||||
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<bool> {
|
|
||||||
Ok((read(i2c, 129)? & 0x01) == 0) // LOSX_INT=0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn has_ckin(i2c: &mut I2c, input: Input) -> Result<bool> {
|
|
||||||
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<bool> {
|
|
||||||
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(())
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user