firmware: oops, misoc #[cfg]s were missing from libboard_artiq.

This commit is contained in:
whitequark 2017-12-28 07:34:17 +00:00
parent ca419aa3c2
commit d3066e5044
6 changed files with 136 additions and 140 deletions

View File

@ -38,6 +38,8 @@ dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"board 0.0.0", "board 0.0.0",
"build_artiq 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]] [[package]]

View File

@ -9,10 +9,12 @@ name = "board_artiq"
path = "lib.rs" path = "lib.rs"
[build-dependencies] [build-dependencies]
build_misoc = { path = "../libbuild_misoc" }
build_artiq = { path = "../libbuild_artiq" } build_artiq = { path = "../libbuild_artiq" }
[dependencies] [dependencies]
bitflags = "1.0" bitflags = "1.0"
log = { version = "0.3", default-features = false }
board = { path = "../libboard" } board = { path = "../libboard" }
[features] [features]

View File

@ -1,3 +1,4 @@
extern crate build_misoc;
extern crate build_artiq; extern crate build_artiq;
use std::env; use std::env;
@ -24,5 +25,6 @@ fn gen_hmc7043_writes() {
} }
fn main() { fn main() {
build_misoc::cfg();
gen_hmc7043_writes(); gen_hmc7043_writes();
} }

View File

@ -1,22 +1,18 @@
#[cfg(has_i2c)] #[cfg(has_i2c)]
use csr; mod imp {
use board::{csr, clock};
#[cfg(has_i2c)] fn half_period() { clock::spin_us(100) }
mod io {
use csr;
use clock;
pub fn half_period() { clock::spin_us(100) }
fn sda_bit(busno: u8) -> u8 { 1 << (2 * busno + 1) } fn sda_bit(busno: u8) -> u8 { 1 << (2 * busno + 1) }
fn scl_bit(busno: u8) -> u8 { 1 << (2 * busno) } fn scl_bit(busno: u8) -> u8 { 1 << (2 * busno) }
pub fn sda_i(busno: u8) -> bool { fn sda_i(busno: u8) -> bool {
unsafe { unsafe {
csr::i2c::in_read() & sda_bit(busno) != 0 csr::i2c::in_read() & sda_bit(busno) != 0
} }
} }
pub fn sda_oe(busno: u8, oe: bool) { fn sda_oe(busno: u8, oe: bool) {
unsafe { unsafe {
let reg = csr::i2c::oe_read(); let reg = csr::i2c::oe_read();
let reg = if oe { reg | sda_bit(busno) } else { reg & !sda_bit(busno) }; 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 { unsafe {
let reg = csr::i2c::out_read(); let reg = csr::i2c::out_read();
let reg = if o { reg | sda_bit(busno) } else { reg & !sda_bit(busno) }; 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 { unsafe {
let reg = csr::i2c::oe_read(); let reg = csr::i2c::oe_read();
let reg = if oe { reg | scl_bit(busno) } else { reg & !scl_bit(busno) }; 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 { unsafe {
let reg = csr::i2c::out_read(); let reg = csr::i2c::out_read();
let reg = if o { reg | scl_bit(busno) } else { reg & !scl_bit(busno) }; let reg = if o { reg | scl_bit(busno) } else { reg & !scl_bit(busno) };
csr::i2c::out_write(reg) csr::i2c::out_write(reg)
} }
} }
}
#[cfg(has_i2c)] pub fn init() {
pub fn init() { for busno in 0..csr::CONFIG_I2C_BUS_COUNT {
for busno in 0..csr::CONFIG_I2C_BUS_COUNT { let busno = busno as u8;
let busno = busno as u8; // Set SCL as output, and high level
// Set SCL as output, and high level scl_o(busno, true);
io::scl_o(busno, true); scl_oe(busno, true);
io::scl_oe(busno, true); // Prepare a zero level on SDA so that sda_oe pulls it down
// Prepare a zero level on SDA so that sda_oe pulls it down sda_o(busno, false);
io::sda_o(busno, false); // Release SDA
// Release SDA sda_oe(busno, false);
io::sda_oe(busno, false);
// Check the I2C bus is ready // Check the I2C bus is ready
io::half_period(); half_period();
io::half_period(); half_period();
if !io::sda_i(busno) { if !sda_i(busno) {
error!("SDA is stuck low on bus #{}", busno) error!("SDA is stuck low on bus #{}", busno)
}
} }
} }
}
#[cfg(has_i2c)] pub fn start(busno: u8) -> Result<(), ()> {
pub fn start(busno: u8) -> Result<(), ()> { if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT {
if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT { return Err(())
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<(), ()> {
pub fn restart(busno: u8) -> Result<(), ()> { if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT {
if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT { return Err(())
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<(), ()> {
pub fn stop(busno: u8) -> Result<(), ()> { if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT {
if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT { return Err(())
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<bool, ()> {
pub fn write(busno: u8, data: u8) -> Result<bool, ()> { if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT {
if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT { return Err(())
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() { pub fn read(busno: u8, ack: bool) -> Result<u8, ()> {
// Set SCL low and set our bit on SDA if busno as u32 >= csr::CONFIG_I2C_BUS_COUNT {
io::scl_o(busno, false); return Err(())
io::sda_oe(busno, data & (1 << bit) == 0); }
io::half_period(); // Set SCL low first, otherwise setting SDA as input may cause a transition
// Set SCL high ; data is shifted on the rising edge of SCL // on SDA with SCL high which will be interpreted as START/STOP condition.
io::scl_o(busno, true); scl_o(busno, false);
io::half_period(); 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<u8, ()> {
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))] #[cfg(not(has_i2c))]
pub fn init() {} mod imp {
#[cfg(not(has_i2c))] pub fn init() {}
pub fn start(_busno: u8) -> Result<(), ()> { Err(()) } pub fn start(_busno: u8) -> Result<(), ()> { Err(()) }
#[cfg(not(has_i2c))] pub fn restart(_busno: u8) -> Result<(), ()> { Err(()) }
pub fn restart(_busno: u8) -> Result<(), ()> { Err(()) } pub fn stop(_busno: u8) -> Result<(), ()> { Err(()) }
#[cfg(not(has_i2c))] pub fn write(_busno: u8, _data: u8) -> Result<bool, ()> { Err(()) }
pub fn stop(_busno: u8) -> Result<(), ()> { Err(()) } pub fn read(_busno: u8, _ack: bool) -> Result<u8, ()> { Err(()) }
#[cfg(not(has_i2c))] }
pub fn write(_busno: u8, _data: u8) -> Result<bool, ()> { Err(()) }
#[cfg(not(has_i2c))] pub use self::imp::*;
pub fn read(_busno: u8, _ack: bool) -> Result<u8, ()> { Err(()) }

View File

@ -3,6 +3,8 @@
#[macro_use] #[macro_use]
extern crate bitflags; extern crate bitflags;
#[macro_use]
extern crate log;
extern crate board; extern crate board;
pub mod pcr; pub mod pcr;

View File

@ -1,7 +1,6 @@
use core::result; use core::result;
use board::{csr, clock};
use i2c; use i2c;
use clock;
use csr;
type Result<T> = result::Result<T, &'static str>; type Result<T> = result::Result<T, &'static str>;
@ -200,8 +199,8 @@ pub fn setup(settings: &FrequencySettings) -> Result<()> {
if !has_clkin2()? { if !has_clkin2()? {
return Err("Si5324 misses CLKIN2 signal"); return Err("Si5324 misses CLKIN2 signal");
} }
monitor_lock()?;
monitor_lock()?;
Ok(()) Ok(())
} }