diff --git a/artiq/firmware/Cargo.lock b/artiq/firmware/Cargo.lock index 3b6ed3581..2144f7367 100644 --- a/artiq/firmware/Cargo.lock +++ b/artiq/firmware/Cargo.lock @@ -38,6 +38,8 @@ dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "board 0.0.0", "build_artiq 0.0.0", + "build_misoc 0.0.0", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/artiq/firmware/libboard_artiq/Cargo.toml b/artiq/firmware/libboard_artiq/Cargo.toml index 8ac55b6a2..2c92b6050 100644 --- a/artiq/firmware/libboard_artiq/Cargo.toml +++ b/artiq/firmware/libboard_artiq/Cargo.toml @@ -9,10 +9,12 @@ name = "board_artiq" path = "lib.rs" [build-dependencies] +build_misoc = { path = "../libbuild_misoc" } build_artiq = { path = "../libbuild_artiq" } [dependencies] bitflags = "1.0" +log = { version = "0.3", default-features = false } board = { path = "../libboard" } [features] diff --git a/artiq/firmware/libboard_artiq/build.rs b/artiq/firmware/libboard_artiq/build.rs index b787e5007..225cf707a 100644 --- a/artiq/firmware/libboard_artiq/build.rs +++ b/artiq/firmware/libboard_artiq/build.rs @@ -1,3 +1,4 @@ +extern crate build_misoc; extern crate build_artiq; use std::env; @@ -24,5 +25,6 @@ fn gen_hmc7043_writes() { } fn main() { + build_misoc::cfg(); gen_hmc7043_writes(); } diff --git a/artiq/firmware/libboard_artiq/i2c.rs b/artiq/firmware/libboard_artiq/i2c.rs index 6f3880645..819c21c1b 100644 --- a/artiq/firmware/libboard_artiq/i2c.rs +++ b/artiq/firmware/libboard_artiq/i2c.rs @@ -1,22 +1,18 @@ #[cfg(has_i2c)] -use csr; +mod imp { + use board::{csr, clock}; -#[cfg(has_i2c)] -mod io { - use csr; - use clock; - - pub fn half_period() { clock::spin_us(100) } + fn half_period() { clock::spin_us(100) } fn sda_bit(busno: u8) -> u8 { 1 << (2 * busno + 1) } fn scl_bit(busno: u8) -> u8 { 1 << (2 * busno) } - pub fn sda_i(busno: u8) -> bool { + fn sda_i(busno: u8) -> bool { unsafe { csr::i2c::in_read() & sda_bit(busno) != 0 } } - pub fn sda_oe(busno: u8, oe: bool) { + fn sda_oe(busno: u8, oe: bool) { unsafe { let reg = csr::i2c::oe_read(); let reg = if oe { reg | sda_bit(busno) } else { reg & !sda_bit(busno) }; @@ -24,7 +20,7 @@ mod io { } } - pub fn sda_o(busno: u8, o: bool) { + fn sda_o(busno: u8, o: bool) { unsafe { let reg = csr::i2c::out_read(); let reg = if o { reg | sda_bit(busno) } else { reg & !sda_bit(busno) }; @@ -32,7 +28,7 @@ mod io { } } - pub fn scl_oe(busno: u8, oe: bool) { + fn scl_oe(busno: u8, oe: bool) { unsafe { let reg = csr::i2c::oe_read(); let reg = if oe { reg | scl_bit(busno) } else { reg & !scl_bit(busno) }; @@ -40,151 +36,144 @@ mod io { } } - pub fn scl_o(busno: u8, o: bool) { + fn scl_o(busno: u8, o: bool) { unsafe { let reg = csr::i2c::out_read(); let reg = if o { reg | scl_bit(busno) } else { reg & !scl_bit(busno) }; csr::i2c::out_write(reg) } } -} -#[cfg(has_i2c)] -pub fn init() { - for busno in 0..csr::CONFIG_I2C_BUS_COUNT { - let busno = busno as u8; - // Set SCL as output, and high level - io::scl_o(busno, true); - io::scl_oe(busno, true); - // Prepare a zero level on SDA so that sda_oe pulls it down - io::sda_o(busno, false); - // Release SDA - io::sda_oe(busno, false); + pub fn init() { + for busno in 0..csr::CONFIG_I2C_BUS_COUNT { + let busno = busno as u8; + // Set SCL as output, and high level + scl_o(busno, true); + scl_oe(busno, true); + // Prepare a zero level on SDA so that sda_oe pulls it down + sda_o(busno, false); + // Release SDA + sda_oe(busno, false); - // Check the I2C bus is ready - io::half_period(); - io::half_period(); - if !io::sda_i(busno) { - error!("SDA is stuck low on bus #{}", busno) + // Check the I2C bus is ready + half_period(); + half_period(); + if !sda_i(busno) { + error!("SDA is stuck low on bus #{}", busno) + } } } -} -#[cfg(has_i2c)] -pub fn start(busno: u8) -> Result<(), ()> { - if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT { - return Err(()) + pub fn start(busno: u8) -> Result<(), ()> { + if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT { + return Err(()) + } + // Set SCL high then SDA low + scl_o(busno, true); + half_period(); + sda_oe(busno, true); + half_period(); + Ok(()) } - // Set SCL high then SDA low - io::scl_o(busno, true); - io::half_period(); - io::sda_oe(busno, true); - io::half_period(); - Ok(()) -} -#[cfg(has_i2c)] -pub fn restart(busno: u8) -> Result<(), ()> { - if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT { - return Err(()) + pub fn restart(busno: u8) -> Result<(), ()> { + if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT { + return Err(()) + } + // Set SCL low then SDA high */ + scl_o(busno, false); + half_period(); + sda_oe(busno, false); + half_period(); + // Do a regular start + start(busno)?; + Ok(()) } - // Set SCL low then SDA high */ - io::scl_o(busno, false); - io::half_period(); - io::sda_oe(busno, false); - io::half_period(); - // Do a regular start - start(busno)?; - Ok(()) -} -#[cfg(has_i2c)] -pub fn stop(busno: u8) -> Result<(), ()> { - if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT { - return Err(()) + pub fn stop(busno: u8) -> Result<(), ()> { + if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT { + return Err(()) + } + // First, make sure SCL is low, so that the target releases the SDA line + scl_o(busno, false); + half_period(); + // Set SCL high then SDA high + sda_oe(busno, true); + scl_o(busno, true); + half_period(); + sda_oe(busno, false); + half_period(); + Ok(()) } - // First, make sure SCL is low, so that the target releases the SDA line - io::scl_o(busno, false); - io::half_period(); - // Set SCL high then SDA high - io::sda_oe(busno, true); - io::scl_o(busno, true); - io::half_period(); - io::sda_oe(busno, false); - io::half_period(); - Ok(()) -} -#[cfg(has_i2c)] -pub fn write(busno: u8, data: u8) -> Result { - if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT { - return Err(()) + pub fn write(busno: u8, data: u8) -> Result { + if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT { + return Err(()) + } + // MSB first + for bit in (0..8).rev() { + // Set SCL low and set our bit on SDA + scl_o(busno, false); + sda_oe(busno, data & (1 << bit) == 0); + half_period(); + // Set SCL high ; data is shifted on the rising edge of SCL + scl_o(busno, true); + half_period(); + } + // Check ack + // Set SCL low, then release SDA so that the I2C target can respond + scl_o(busno, false); + half_period(); + sda_oe(busno, false); + // Set SCL high and check for ack + scl_o(busno, true); + half_period(); + // returns true if acked (I2C target pulled SDA low) + Ok(!sda_i(busno)) } - // MSB first - for bit in (0..8).rev() { - // Set SCL low and set our bit on SDA - io::scl_o(busno, false); - io::sda_oe(busno, data & (1 << bit) == 0); - io::half_period(); - // Set SCL high ; data is shifted on the rising edge of SCL - io::scl_o(busno, true); - io::half_period(); + + pub fn read(busno: u8, ack: bool) -> Result { + if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT { + return Err(()) + } + // Set SCL low first, otherwise setting SDA as input may cause a transition + // on SDA with SCL high which will be interpreted as START/STOP condition. + scl_o(busno, false); + half_period(); // make sure SCL has settled low + sda_oe(busno, false); + + let mut data: u8 = 0; + + // MSB first + for bit in (0..8).rev() { + scl_o(busno, false); + half_period(); + // Set SCL high and shift data + scl_o(busno, true); + half_period(); + if sda_i(busno) { data |= 1 << bit } + } + // Send ack + // Set SCL low and pull SDA low when acking + scl_o(busno, false); + if ack { sda_oe(busno, true) } + half_period(); + // then set SCL high + scl_o(busno, true); + half_period(); + + Ok(data) } - // Check ack - // Set SCL low, then release SDA so that the I2C target can respond - io::scl_o(busno, false); - io::half_period(); - io::sda_oe(busno, false); - // Set SCL high and check for ack - io::scl_o(busno, true); - io::half_period(); - // returns true if acked (I2C target pulled SDA low) - Ok(!io::sda_i(busno)) -} - -#[cfg(has_i2c)] -pub fn read(busno: u8, ack: bool) -> Result { - if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT { - return Err(()) - } - // Set SCL low first, otherwise setting SDA as input may cause a transition - // on SDA with SCL high which will be interpreted as START/STOP condition. - io::scl_o(busno, false); - io::half_period(); // make sure SCL has settled low - io::sda_oe(busno, false); - - let mut data: u8 = 0; - - // MSB first - for bit in (0..8).rev() { - io::scl_o(busno, false); - io::half_period(); - // Set SCL high and shift data - io::scl_o(busno, true); - io::half_period(); - if io::sda_i(busno) { data |= 1 << bit } - } - // Send ack - // Set SCL low and pull SDA low when acking - io::scl_o(busno, false); - if ack { io::sda_oe(busno, true) } - io::half_period(); - // then set SCL high - io::scl_o(busno, true); - io::half_period(); - - Ok(data) } #[cfg(not(has_i2c))] -pub fn init() {} -#[cfg(not(has_i2c))] -pub fn start(_busno: u8) -> Result<(), ()> { Err(()) } -#[cfg(not(has_i2c))] -pub fn restart(_busno: u8) -> Result<(), ()> { Err(()) } -#[cfg(not(has_i2c))] -pub fn stop(_busno: u8) -> Result<(), ()> { Err(()) } -#[cfg(not(has_i2c))] -pub fn write(_busno: u8, _data: u8) -> Result { Err(()) } -#[cfg(not(has_i2c))] -pub fn read(_busno: u8, _ack: bool) -> Result { Err(()) } +mod imp { + pub fn init() {} + pub fn start(_busno: u8) -> Result<(), ()> { Err(()) } + pub fn restart(_busno: u8) -> Result<(), ()> { Err(()) } + pub fn stop(_busno: u8) -> Result<(), ()> { Err(()) } + pub fn write(_busno: u8, _data: u8) -> Result { Err(()) } + pub fn read(_busno: u8, _ack: bool) -> Result { Err(()) } +} + +pub use self::imp::*; diff --git a/artiq/firmware/libboard_artiq/lib.rs b/artiq/firmware/libboard_artiq/lib.rs index 894866980..c40f899c3 100644 --- a/artiq/firmware/libboard_artiq/lib.rs +++ b/artiq/firmware/libboard_artiq/lib.rs @@ -3,6 +3,8 @@ #[macro_use] extern crate bitflags; +#[macro_use] +extern crate log; extern crate board; pub mod pcr; diff --git a/artiq/firmware/libboard_artiq/si5324.rs b/artiq/firmware/libboard_artiq/si5324.rs index 5cea4f814..574e1ba53 100644 --- a/artiq/firmware/libboard_artiq/si5324.rs +++ b/artiq/firmware/libboard_artiq/si5324.rs @@ -1,7 +1,6 @@ use core::result; +use board::{csr, clock}; use i2c; -use clock; -use csr; type Result = result::Result; @@ -200,8 +199,8 @@ pub fn setup(settings: &FrequencySettings) -> Result<()> { if !has_clkin2()? { return Err("Si5324 misses CLKIN2 signal"); } - monitor_lock()?; + monitor_lock()?; Ok(()) }