Add SFP fibers support for satman #217

Merged
sb10q merged 2 commits from esavkin/artiq-zynq:213-satman-sfp-fiber-support into master 2023-02-17 17:19:30 +08:00
4 changed files with 50 additions and 45 deletions

View File

@ -1,4 +1,4 @@
use crate::i2c;
use libboard_zynq::i2c;
use log::info;
// Only the bare minimum registers. Bits/IO connections equivalent between IC types.
@ -10,10 +10,9 @@ struct Registers {
gpiob: u8, // Output Port 1
}
pub struct IoExpander {
busno: i32,
port: u8,
address: i32,
pub struct IoExpander<'a> {
i2c: &'a mut i2c::I2c,
address: u8,
iodir: [u8; 2],
out_current: [u8; 2],
out_target: [u8; 2],
@ -21,14 +20,13 @@ pub struct IoExpander {
}
impl IoExpander {
pub fn new(index: u8) -> Result<Self, &'static str> {
impl<'a> IoExpander<'a> {
pub fn new(i2c: &'a mut i2c::I2c, index: u8) -> Result<Self, &'static str> {
// Both expanders on SHARED I2C bus
let mut io_expander = match index {
0 => IoExpander {
busno: 0,
port: 11,
i2c,
address: 0x40,
iodir: [0xff; 2],
out_current: [0; 2],
@ -41,8 +39,7 @@ impl IoExpander {
},
},
1 => IoExpander {
busno: 0,
port: 11,
i2c,
address: 0x42,
iodir: [0xff; 2],
out_current: [0; 2],
@ -75,32 +72,31 @@ impl IoExpander {
Ok(io_expander)
}
fn select(&self) -> Result<(), &'static str> {
let mask: u16 = 1 << self.port;
i2c::switch_select(self.busno, 0x70, mask as u8 as i32);
i2c::switch_select(self.busno, 0x71, (mask >> 8) as u8 as i32);
fn select(&mut self) -> Result<(), &'static str> {
self.i2c.pca954x_select(0x70, None)?;
self.i2c.pca954x_select(0x71, Some(3))?;
Ok(())
}
fn write(&self, addr: u8, value: u8) -> Result<(), &'static str> {
i2c::start(self.busno);
i2c::write(self.busno, self.address as i32);
i2c::write(self.busno, addr as i32);
i2c::write(self.busno, value as i32);
i2c::stop(self.busno);
fn write(&mut self, addr: u8, value: u8) -> Result<(), &'static str> {
self.i2c.start()?;
self.i2c.write(self.address)?;
self.i2c.write(addr)?;
self.i2c.write(value)?;
self.i2c.stop()?;
Ok(())
}
fn check_ack(&self) -> Result<bool, &'static str> {
fn check_ack(&mut self) -> Result<bool, &'static str> {
// Check for ack from io expander
self.select()?;
i2c::start(self.busno);
let ack = i2c::write(self.busno, self.address);
i2c::stop(self.busno);
self.i2c.start()?;
let ack = self.i2c.write(self.address)?;
self.i2c.stop()?;
Ok(ack)
}
fn update_iodir(&self) -> Result<(), &'static str> {
fn update_iodir(&mut self) -> Result<(), &'static str> {
self.write(self.registers.iodira, self.iodir[0])?;
self.write(self.registers.iodirb, self.iodir[1])?;
Ok(())

View File

@ -27,6 +27,8 @@ pub mod drtioaux_async;
#[cfg(has_drtio)]
#[path = "../../../build/mem.rs"]
pub mod mem;
#[cfg(feature = "target_kasli_soc")]
pub mod io_expander;
use core::{cmp, str};

View File

@ -21,7 +21,7 @@ use nb;
use void::Void;
use libconfig::Config;
use libcortex_a9::l2c::enable_l2_cache;
use libboard_artiq::{logger, identifier_read, pl};
use libboard_artiq::{logger, identifier_read, pl, io_expander};
const ASYNC_ERROR_COLLISION: u8 = 1 << 0;
const ASYNC_ERROR_BUSY: u8 = 1 << 1;
@ -46,8 +46,6 @@ mod mgmt;
mod analyzer;
mod irq;
mod i2c;
#[cfg(feature = "target_kasli_soc")]
mod io_expander;
static mut SEEN_ASYNC_ERRORS: u8 = 0;
@ -117,21 +115,17 @@ pub fn main_core0() {
#[cfg(feature = "target_kasli_soc")]
{
let (mut io_expander0, mut io_expander1) = (io_expander::IoExpander::new(0).unwrap(), io_expander::IoExpander::new(1).unwrap());
io_expander0.init().expect("I2C I/O expander #0 initialization failed");
io_expander1.init().expect("I2C I/O expander #1 initialization failed");
// Actively drive TX_DISABLE to false on SFP0..3
io_expander0.set_oe(0, 1 << 1).unwrap();
io_expander0.set_oe(1, 1 << 1).unwrap();
io_expander1.set_oe(0, 1 << 1).unwrap();
io_expander1.set_oe(1, 1 << 1).unwrap();
io_expander0.set(0, 1, false);
io_expander0.set(1, 1, false);
io_expander1.set(0, 1, false);
io_expander1.set(1, 1, false);
io_expander0.service().unwrap();
io_expander1.service().unwrap();
let i2c = unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() };
for expander_i in 0..2 {
let mut io_expander = io_expander::IoExpander::new(i2c, expander_i).unwrap();

expander_index, expander_i or just i

``expander_index``, ``expander_i`` or just ``i``
io_expander.init().expect("I2C I/O expander #0 initialization failed");
// Actively drive TX_DISABLE to false on SFP0..3
io_expander.set_oe(0, 1 << 1).unwrap();
io_expander.set_oe(1, 1 << 1).unwrap();
io_expander.set(0, 1, false);
io_expander.set(1, 1, false);
io_expander.service().unwrap();
}
}
let cfg = match Config::new() {

View File

@ -22,7 +22,7 @@ use libboard_zynq::{i2c::I2c, timer::GlobalTimer, time::Milliseconds, print, pri
use libsupport_zynq::ram;
#[cfg(has_si5324)]
use libboard_artiq::si5324;
use libboard_artiq::{pl::csr, drtio_routing, drtioaux, logger, identifier_read};
use libboard_artiq::{pl::csr, drtio_routing, drtioaux, logger, identifier_read, io_expander};
use libcortex_a9::{spin_lock_yield, interrupt_handler, regs::{MPIDR, SP}, notify_spin_lock, asm, l2c::enable_l2_cache};
use libregister::{RegisterW, RegisterR};
#[cfg(feature = "target_kasli_soc")]
@ -449,6 +449,19 @@ pub extern fn main_core0() -> i32 {
let mut i2c = I2c::i2c0();
i2c.init().expect("I2C initialization failed");
#[cfg(feature = "target_kasli_soc")]
{
for expander_i in 0..2 {
let mut io_expander = io_expander::IoExpander::new(&mut i2c, expander_i).unwrap();

I doubt the & and * are necessary here.

I doubt the & and * are necessary here.

& makes a slice from array (to make it iterable)

& makes a slice from array (to make it iterable)
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=6f1f8688caff98619cc0d08dd6d99a27

https://github.com/rust-lang/rust/issues/84837

error[E0277]: `[u8; 2]` is not an iterator
firmware>    --> runtime/src/main.rs:119:27
firmware>     |
firmware> 119 |         for expander_i in [0u8, 1] {
firmware>     |                           ^^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it
firmware>     |
firmware>     = help: the trait `Iterator` is not implemented for `[u8; 2]`
firmware>     = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
firmware>     = note: required because of the requirements on the impl of `IntoIterator` for `[u8; 2]`
firmware>     = note: required by `into_iter`
firmware> error: aborting due to previous error
firmware> For more information about this error, try `rustc --explain E0277`.
https://github.com/rust-lang/rust/issues/84837 ```rust error[E0277]: `[u8; 2]` is not an iterator firmware> --> runtime/src/main.rs:119:27 firmware> | firmware> 119 | for expander_i in [0u8, 1] { firmware> | ^^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it firmware> | firmware> = help: the trait `Iterator` is not implemented for `[u8; 2]` firmware> = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` firmware> = note: required because of the requirements on the impl of `IntoIterator` for `[u8; 2]` firmware> = note: required by `into_iter` firmware> error: aborting due to previous error firmware> For more information about this error, try `rustc --explain E0277`. ```

Doesn't seem relevant to this case?

Doesn't seem relevant to this case?

Maybe the link is not really relevant, but the compiler output is

Maybe the link is not really relevant, but the compiler output is

Seems to be a peculiar issue with the particular compiler version we use here. What was the problem with 0..2 that you had written earlier?

Seems to be a peculiar issue with the particular compiler version we use here. What was the problem with 0..2 that you had written earlier?

0..2 may seem be confusing, because only 0 and 1 are used, from my point of view

0..2 may seem be confusing, because only 0 and 1 are used, from my point of view

You can expect developers to know range boundaries.

You can expect developers to know range boundaries.

There's also the 0..=1 syntax...

There's also the ``0..=1`` syntax...
io_expander.init().expect("I2C I/O expander #0 initialization failed");
// Actively drive TX_DISABLE to false on SFP0..3
io_expander.set_oe(0, 1 << 1).unwrap();
io_expander.set_oe(1, 1 << 1).unwrap();
io_expander.set(0, 1, false);
io_expander.set(1, 1, false);
io_expander.service().unwrap();
}
}
#[cfg(has_si5324)]
si5324::setup(&mut i2c, &SI5324_SETTINGS, si5324::Input::Ckin1, &mut timer).expect("cannot initialize Si5324");