From 9c6a993a7f39639e0482a0b76625b4b466aabeb4 Mon Sep 17 00:00:00 2001 From: MorganTL Date: Mon, 31 Jul 2023 10:49:54 +0800 Subject: [PATCH 01/10] use csr::virtual_leds for SFP0..3 LED indication --- src/gateware/kasli_soc.py | 17 +++++++++++++- src/libboard_artiq/src/io_expander.rs | 27 ++++++++++++++++++++++ src/runtime/src/main.rs | 33 +++++++++++++++++++++++++++ src/satman/src/main.rs | 11 +++++++++ 4 files changed, 87 insertions(+), 1 deletion(-) diff --git a/src/gateware/kasli_soc.py b/src/gateware/kasli_soc.py index 102d672..b308304 100755 --- a/src/gateware/kasli_soc.py +++ b/src/gateware/kasli_soc.py @@ -10,6 +10,7 @@ from migen.genlib.cdc import MultiReg from migen_axi.integration.soc_core import SoCCore from migen_axi.platforms import kasli_soc from misoc.interconnect.csr import * +from misoc.cores import virtual_leds from misoc.integration import cpu_interface from artiq.coredevice import jsondesc @@ -303,6 +304,14 @@ class GenericMaster(SoCCore): if has_grabber: self.rustc_cfg["has_grabber"] = None self.add_csr_group("grabber", self.grabber_csr_group) + + + self.submodules.virtual_leds = virtual_leds.VirtualLeds() + self.csr_devices.append("virtual_leds") + + self.comb += [self.virtual_leds.get(i).eq(channel.rx_ready) + for i, channel in enumerate(self.drtio_transceiver.channels)] + class GenericSatellite(SoCCore): @@ -466,7 +475,13 @@ class GenericSatellite(SoCCore): self.rustc_cfg["has_grabber"] = None self.add_csr_group("grabber", self.grabber_csr_group) # no RTIO CRG here - + + self.submodules.virtual_leds = virtual_leds.VirtualLeds() + self.csr_devices.append("virtual_leds") + + self.comb += [self.virtual_leds.get(i).eq(channel.rx_ready) + for i, channel in enumerate(self.drtio_transceiver.channels)] + def write_mem_file(soc, filename): with open(filename, "w") as f: diff --git a/src/libboard_artiq/src/io_expander.rs b/src/libboard_artiq/src/io_expander.rs index 918b773..4312bc0 100644 --- a/src/libboard_artiq/src/io_expander.rs +++ b/src/libboard_artiq/src/io_expander.rs @@ -1,6 +1,8 @@ use libboard_zynq::i2c; use log::info; +use crate::pl::csr; + // Only the bare minimum registers. Bits/IO connections equivalent between IC types. struct Registers { // PCA9539 equivalent register names in comments @@ -10,6 +12,26 @@ struct Registers { gpiob: u8, // Output Port 1 } +//IO expanders pins +const IO_DIR_INPUT_ALL: u8 = 0xFF; +const IO_DIR_OUT_SFP_TX_DISABLE: u8 = !0x02; +const IO_DIR_OUT_SFP_LED: u8 = !0x40; +#[cfg(hw_rev = "v1.0")] +const IO_DIR_OUT_SFP0_LED: u8 = !0x40; +#[cfg(hw_rev = "v1.1")] +const IO_DIR_OUT_SFP0_LED: u8 = !0x80; + +//IO expander port direction +const IO_DIR_MAPPING0: [u8; 2] = [ + IO_DIR_INPUT_ALL & IO_DIR_OUT_SFP_TX_DISABLE & (IO_DIR_OUT_SFP0_LED), + IO_DIR_INPUT_ALL & IO_DIR_OUT_SFP_TX_DISABLE & IO_DIR_OUT_SFP_LED, +]; + +const IO_DIR_MAPPING1: [u8; 2] = [ + IO_DIR_INPUT_ALL & IO_DIR_OUT_SFP_TX_DISABLE & IO_DIR_OUT_SFP_LED, + IO_DIR_INPUT_ALL & IO_DIR_OUT_SFP_TX_DISABLE & IO_DIR_OUT_SFP_LED, +]; + pub struct IoExpander<'a> { i2c: &'a mut i2c::I2c, address: u8, @@ -123,6 +145,11 @@ impl<'a> IoExpander<'a> { } pub fn service(&mut self) -> Result<(), &'static str> { + for (led, port, bit) in self.virtual_led_mapping.iter() { + let level = unsafe { csr::virtual_leds::status_read() >> led & 1 }; + self.set(*port, *bit, level != 0); + } + if self.out_target != self.out_current { self.select()?; if self.out_target[0] != self.out_current[0] { diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index 3789888..efc44a9 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -102,6 +102,39 @@ async fn report_async_rtio_errors() { } } +#[cfg(all(feature = "target_kasli_soc", has_drtio))] +static mut SEEN_RTIO_LED: u8 = 0; +#[cfg(all(feature = "target_kasli_soc", has_drtio))] +static mut READ_RTIO_LED: u8 = 0; + +#[cfg(all(feature = "target_kasli_soc", has_drtio))] +fn wait_for_rtio_led_change() -> nb::Result<(), Void> { + unsafe { + let len: usize = pl::csr::DRTIO.len(); + READ_RTIO_LED = 0; + for linkno in 0..len { + READ_RTIO_LED |= (pl::csr::DRTIO[linkno].rx_up_read)() << linkno; + } + if READ_RTIO_LED != SEEN_RTIO_LED { + Ok(()) + } else { + Err(nb::Error::WouldBlock) + } + } +} +#[cfg(all(feature = "target_kasli_soc", has_drtio))] +async fn async_rtio_led() { + let _ = block_async!(wait_for_rtio_led_change()).await; + unsafe { + let i2c = (&mut i2c::I2C_BUS).as_mut().unwrap(); + for expander_i in 0..=1 { + let mut io_expander = io_expander::IoExpander::new(i2c, expander_i).unwrap(); + io_expander.service().expect("I2C I/O expander service failed"); + } + SEEN_RTIO_LED = READ_RTIO_LED; + }; +} + static mut LOG_BUFFER: [u8; 1 << 17] = [0; 1 << 17]; #[no_mangle] diff --git a/src/satman/src/main.rs b/src/satman/src/main.rs index 0938e18..03ba48f 100644 --- a/src/satman/src/main.rs +++ b/src/satman/src/main.rs @@ -664,6 +664,12 @@ pub extern "C" fn main_core0() -> i32 { for mut rep in repeaters.iter_mut() { rep.service(&routing_table, rank, &mut timer); } + #[cfg(all(feature = "target_kasli_soc", has_drtio))] + for expander_i in 0..=1 { + let mut io_expander = io_expander::IoExpander::new(&mut i2c, expander_i).unwrap(); + io_expander.service().expect("I2C I/O expander service failed") + } + hardware_tick(&mut hardware_tick_ts, &mut timer); } @@ -700,6 +706,11 @@ pub extern "C" fn main_core0() -> i32 { for mut rep in repeaters.iter_mut() { rep.service(&routing_table, rank, &mut timer); } + #[cfg(all(feature = "target_kasli_soc", has_drtio))] + for expander_i in 0..=1 { + let mut io_expander = io_expander::IoExpander::new(&mut i2c, expander_i).unwrap(); + io_expander.service().expect("I2C I/O expander service failed") + } hardware_tick(&mut hardware_tick_ts, &mut timer); if drtiosat_tsc_loaded() { info!("TSC loaded from uplink"); -- 2.42.0 From cee22f43aae532986ccc59b64802f30485b4026f Mon Sep 17 00:00:00 2001 From: MorganTL Date: Tue, 1 Aug 2023 16:20:56 +0800 Subject: [PATCH 02/10] fix SPF LED stay on after removal --- src/runtime/src/main.rs | 33 ++++++++++++++------------------- src/satman/src/main.rs | 19 +++++++++++++------ 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index efc44a9..85b564f 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -103,19 +103,13 @@ async fn report_async_rtio_errors() { } #[cfg(all(feature = "target_kasli_soc", has_drtio))] -static mut SEEN_RTIO_LED: u8 = 0; -#[cfg(all(feature = "target_kasli_soc", has_drtio))] -static mut READ_RTIO_LED: u8 = 0; +static mut LAST_VIRTUAL_LED_STATUS: u8 = 0; #[cfg(all(feature = "target_kasli_soc", has_drtio))] -fn wait_for_rtio_led_change() -> nb::Result<(), Void> { +fn wait_for_virtual_leds_change() -> nb::Result<(), Void> { unsafe { - let len: usize = pl::csr::DRTIO.len(); - READ_RTIO_LED = 0; - for linkno in 0..len { - READ_RTIO_LED |= (pl::csr::DRTIO[linkno].rx_up_read)() << linkno; - } - if READ_RTIO_LED != SEEN_RTIO_LED { + if pl::csr::virtual_leds::status_read() != LAST_VIRTUAL_LED_STATUS { + LAST_VIRTUAL_LED_STATUS = pl::csr::virtual_leds::status_read(); Ok(()) } else { Err(nb::Error::WouldBlock) @@ -124,15 +118,16 @@ fn wait_for_rtio_led_change() -> nb::Result<(), Void> { } #[cfg(all(feature = "target_kasli_soc", has_drtio))] async fn async_rtio_led() { - let _ = block_async!(wait_for_rtio_led_change()).await; - unsafe { - let i2c = (&mut i2c::I2C_BUS).as_mut().unwrap(); - for expander_i in 0..=1 { - let mut io_expander = io_expander::IoExpander::new(i2c, expander_i).unwrap(); - io_expander.service().expect("I2C I/O expander service failed"); - } - SEEN_RTIO_LED = READ_RTIO_LED; - }; + let i2c0 = unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() }; + let i2c1 = unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() }; + let mut io_expander0 = io_expander::IoExpander::new(i2c0, 0).unwrap(); + let mut io_expander1 = io_expander::IoExpander::new(i2c1, 1).unwrap(); + loop{ + let _ = block_async!(wait_for_virtual_leds_change()).await; + info!("switching"); + io_expander0.service().expect("I2C I/O expander #0 service failed"); + io_expander1.service().expect("I2C I/O expander #1 service failed"); + } } static mut LOG_BUFFER: [u8; 1 << 17] = [0; 1 << 17]; diff --git a/src/satman/src/main.rs b/src/satman/src/main.rs index 03ba48f..56b2faf 100644 --- a/src/satman/src/main.rs +++ b/src/satman/src/main.rs @@ -657,6 +657,13 @@ pub extern "C" fn main_core0() -> i32 { let mut hardware_tick_ts = 0; + let mut i2c0 = I2c::i2c0(); + let mut i2c1 = I2c::i2c0(); + i2c0.init().expect("I2C0 initialization failed"); + i2c1.init().expect("I2C1 initialization failed"); + let mut io_expander0 = io_expander::IoExpander::new(&mut i2c0, 0).unwrap(); + let mut io_expander1 = io_expander::IoExpander::new(&mut i2c1, 1).unwrap(); + loop { while !drtiosat_link_rx_up() { drtiosat_process_errors(); @@ -665,9 +672,9 @@ pub extern "C" fn main_core0() -> i32 { rep.service(&routing_table, rank, &mut timer); } #[cfg(all(feature = "target_kasli_soc", has_drtio))] - for expander_i in 0..=1 { - let mut io_expander = io_expander::IoExpander::new(&mut i2c, expander_i).unwrap(); - io_expander.service().expect("I2C I/O expander service failed") + { + io_expander0.service().expect("I2C I/O expander #0 service failed"); + io_expander1.service().expect("I2C I/O expander #1 service failed"); } hardware_tick(&mut hardware_tick_ts, &mut timer); @@ -707,9 +714,9 @@ pub extern "C" fn main_core0() -> i32 { rep.service(&routing_table, rank, &mut timer); } #[cfg(all(feature = "target_kasli_soc", has_drtio))] - for expander_i in 0..=1 { - let mut io_expander = io_expander::IoExpander::new(&mut i2c, expander_i).unwrap(); - io_expander.service().expect("I2C I/O expander service failed") + { + io_expander0.service().expect("I2C I/O expander #0 service failed"); + io_expander1.service().expect("I2C I/O expander #1 service failed"); } hardware_tick(&mut hardware_tick_ts, &mut timer); if drtiosat_tsc_loaded() { -- 2.42.0 From f917c62948c3ff510911b4a879262bac87f9ee00 Mon Sep 17 00:00:00 2001 From: MorganTL Date: Tue, 1 Aug 2023 16:29:39 +0800 Subject: [PATCH 03/10] rust format --- src/runtime/src/main.rs | 4 ++-- src/satman/src/main.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index 85b564f..b64a738 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -109,7 +109,7 @@ static mut LAST_VIRTUAL_LED_STATUS: u8 = 0; fn wait_for_virtual_leds_change() -> nb::Result<(), Void> { unsafe { if pl::csr::virtual_leds::status_read() != LAST_VIRTUAL_LED_STATUS { - LAST_VIRTUAL_LED_STATUS = pl::csr::virtual_leds::status_read(); + LAST_VIRTUAL_LED_STATUS = pl::csr::virtual_leds::status_read(); Ok(()) } else { Err(nb::Error::WouldBlock) @@ -122,7 +122,7 @@ async fn async_rtio_led() { let i2c1 = unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() }; let mut io_expander0 = io_expander::IoExpander::new(i2c0, 0).unwrap(); let mut io_expander1 = io_expander::IoExpander::new(i2c1, 1).unwrap(); - loop{ + loop { let _ = block_async!(wait_for_virtual_leds_change()).await; info!("switching"); io_expander0.service().expect("I2C I/O expander #0 service failed"); diff --git a/src/satman/src/main.rs b/src/satman/src/main.rs index 56b2faf..a0b732c 100644 --- a/src/satman/src/main.rs +++ b/src/satman/src/main.rs @@ -660,7 +660,7 @@ pub extern "C" fn main_core0() -> i32 { let mut i2c0 = I2c::i2c0(); let mut i2c1 = I2c::i2c0(); i2c0.init().expect("I2C0 initialization failed"); - i2c1.init().expect("I2C1 initialization failed"); + i2c1.init().expect("I2C1 initialization failed"); let mut io_expander0 = io_expander::IoExpander::new(&mut i2c0, 0).unwrap(); let mut io_expander1 = io_expander::IoExpander::new(&mut i2c1, 1).unwrap(); -- 2.42.0 From 097cfd9996a8f24bb557f8010169842ee29d3e7b Mon Sep 17 00:00:00 2001 From: MorganTL Date: Tue, 1 Aug 2023 16:59:07 +0800 Subject: [PATCH 04/10] - remove debug message - save 1 csr call --- src/runtime/src/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index b64a738..c63aeb3 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -108,8 +108,9 @@ static mut LAST_VIRTUAL_LED_STATUS: u8 = 0; #[cfg(all(feature = "target_kasli_soc", has_drtio))] fn wait_for_virtual_leds_change() -> nb::Result<(), Void> { unsafe { - if pl::csr::virtual_leds::status_read() != LAST_VIRTUAL_LED_STATUS { - LAST_VIRTUAL_LED_STATUS = pl::csr::virtual_leds::status_read(); + let current = pl::csr::virtual_leds::status_read(); + if current != LAST_VIRTUAL_LED_STATUS { + LAST_VIRTUAL_LED_STATUS = current; Ok(()) } else { Err(nb::Error::WouldBlock) @@ -124,7 +125,6 @@ async fn async_rtio_led() { let mut io_expander1 = io_expander::IoExpander::new(i2c1, 1).unwrap(); loop { let _ = block_async!(wait_for_virtual_leds_change()).await; - info!("switching"); io_expander0.service().expect("I2C I/O expander #0 service failed"); io_expander1.service().expect("I2C I/O expander #1 service failed"); } -- 2.42.0 From 3a9699589c133fba92e468138dc361e36dc9a3c3 Mon Sep 17 00:00:00 2001 From: MorganTL Date: Wed, 2 Aug 2023 17:41:58 +0800 Subject: [PATCH 05/10] - inline i2c0..1 into io_expander - remove redundant i2c.init --- src/runtime/src/main.rs | 6 ++---- src/satman/src/main.rs | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index c63aeb3..fa9c700 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -119,10 +119,8 @@ fn wait_for_virtual_leds_change() -> nb::Result<(), Void> { } #[cfg(all(feature = "target_kasli_soc", has_drtio))] async fn async_rtio_led() { - let i2c0 = unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() }; - let i2c1 = unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() }; - let mut io_expander0 = io_expander::IoExpander::new(i2c0, 0).unwrap(); - let mut io_expander1 = io_expander::IoExpander::new(i2c1, 1).unwrap(); + let mut io_expander0 = io_expander::IoExpander::new(unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() }, 0).unwrap(); + let mut io_expander1 = io_expander::IoExpander::new(unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() }, 1).unwrap(); loop { let _ = block_async!(wait_for_virtual_leds_change()).await; io_expander0.service().expect("I2C I/O expander #0 service failed"); diff --git a/src/satman/src/main.rs b/src/satman/src/main.rs index a0b732c..1a104ec 100644 --- a/src/satman/src/main.rs +++ b/src/satman/src/main.rs @@ -660,7 +660,6 @@ pub extern "C" fn main_core0() -> i32 { let mut i2c0 = I2c::i2c0(); let mut i2c1 = I2c::i2c0(); i2c0.init().expect("I2C0 initialization failed"); - i2c1.init().expect("I2C1 initialization failed"); let mut io_expander0 = io_expander::IoExpander::new(&mut i2c0, 0).unwrap(); let mut io_expander1 = io_expander::IoExpander::new(&mut i2c1, 1).unwrap(); -- 2.42.0 From 28aa03b2911a2711353276d3c7c8b9a0dbcec181 Mon Sep 17 00:00:00 2001 From: MorganTL Date: Fri, 4 Aug 2023 13:32:02 +0800 Subject: [PATCH 06/10] -runtime main: rename function - satman: change i2c0..1 to use raw pointer - add reverted SFP LED commit --- src/libboard_artiq/src/io_expander.rs | 24 ++++++++++++++++++++++-- src/runtime/src/main.rs | 7 ++++--- src/satman/src/main.rs | 10 +++------- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/libboard_artiq/src/io_expander.rs b/src/libboard_artiq/src/io_expander.rs index 4312bc0..009c334 100644 --- a/src/libboard_artiq/src/io_expander.rs +++ b/src/libboard_artiq/src/io_expander.rs @@ -39,16 +39,27 @@ pub struct IoExpander<'a> { out_current: [u8; 2], out_target: [u8; 2], registers: Registers, + virtual_led_mapping: &'static [(u8, u8, u8)], + channel: usize, } impl<'a> IoExpander<'a> { pub fn new(i2c: &'a mut i2c::I2c, index: u8) -> Result { + #[cfg(hw_rev = "v1.0")] + const VIRTUAL_LED_MAPPING0: [(u8, u8, u8); 2] = [(0, 0, 6), (1, 1, 6)]; + #[cfg(hw_rev = "v1.1")] + const VIRTUAL_LED_MAPPING0: [(u8, u8, u8); 2] = [(0, 0, 7), (1, 1, 6)]; + + const VIRTUAL_LED_MAPPING1: [(u8, u8, u8); 2] = [(2, 0, 6), (3, 1, 6)]; + // Both expanders on SHARED I2C bus let mut io_expander = match index { 0 => IoExpander { i2c, + channel: 0, address: 0x40, - iodir: [0xff; 2], + virtual_led_mapping: &VIRTUAL_LED_MAPPING0, + iodir: IO_DIR_MAPPING0, out_current: [0; 2], out_target: [0; 2], registers: Registers { @@ -60,8 +71,10 @@ impl<'a> IoExpander<'a> { }, 1 => IoExpander { i2c, + channel: 1, address: 0x42, - iodir: [0xff; 2], + virtual_led_mapping: &VIRTUAL_LED_MAPPING1, + iodir: IO_DIR_MAPPING1, out_current: [0; 2], out_target: [0; 2], registers: Registers { @@ -121,6 +134,13 @@ impl<'a> IoExpander<'a> { pub fn init(&mut self) -> Result<(), &'static str> { self.select()?; + + self.iodir = match self.channel { + 0 => IO_DIR_MAPPING0, + 1 => IO_DIR_MAPPING1, + _ => [IO_DIR_INPUT_ALL; 2], + }; + self.update_iodir()?; self.out_current[0] = 0x00; diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index fa9c700..229c042 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -118,7 +118,7 @@ fn wait_for_virtual_leds_change() -> nb::Result<(), Void> { } } #[cfg(all(feature = "target_kasli_soc", has_drtio))] -async fn async_rtio_led() { +async fn async_io_expanders_service() { let mut io_expander0 = io_expander::IoExpander::new(unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() }, 0).unwrap(); let mut io_expander1 = io_expander::IoExpander::new(unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() }, 1).unwrap(); loop { @@ -156,8 +156,6 @@ pub fn main_core0() { let mut io_expander = io_expander::IoExpander::new(i2c, expander_i).unwrap(); 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(); @@ -176,5 +174,8 @@ pub fn main_core0() { task::spawn(report_async_rtio_errors()); + #[cfg(all(feature = "target_kasli_soc", has_drtio))] + task::spawn(async_io_expanders_service()); + comms::main(timer, cfg); } diff --git a/src/satman/src/main.rs b/src/satman/src/main.rs index 1a104ec..d79bd9f 100644 --- a/src/satman/src/main.rs +++ b/src/satman/src/main.rs @@ -610,6 +610,7 @@ pub extern "C" fn main_core0() -> i32 { ram::init_alloc_core0(); let mut i2c = I2c::i2c0(); + let i2c_ptr = &mut i2c as *mut I2c; i2c.init().expect("I2C initialization failed"); #[cfg(feature = "target_kasli_soc")] { @@ -617,8 +618,6 @@ pub extern "C" fn main_core0() -> i32 { let mut io_expander = io_expander::IoExpander::new(&mut i2c, expander_i).unwrap(); 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(); @@ -657,11 +656,8 @@ pub extern "C" fn main_core0() -> i32 { let mut hardware_tick_ts = 0; - let mut i2c0 = I2c::i2c0(); - let mut i2c1 = I2c::i2c0(); - i2c0.init().expect("I2C0 initialization failed"); - let mut io_expander0 = io_expander::IoExpander::new(&mut i2c0, 0).unwrap(); - let mut io_expander1 = io_expander::IoExpander::new(&mut i2c1, 1).unwrap(); + let mut io_expander0 = io_expander::IoExpander::new(unsafe { &mut *i2c_ptr }, 0).unwrap(); + let mut io_expander1 = io_expander::IoExpander::new(unsafe { &mut *i2c_ptr }, 1).unwrap(); loop { while !drtiosat_link_rx_up() { -- 2.42.0 From f7fbb03f7ab018ece6827c5439eb16d963d9e8a0 Mon Sep 17 00:00:00 2001 From: MorganTL Date: Fri, 4 Aug 2023 14:32:21 +0800 Subject: [PATCH 07/10] add "hw_rev" rustc_cfg --- src/gateware/kasli_soc.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gateware/kasli_soc.py b/src/gateware/kasli_soc.py index b308304..6fbeb4b 100755 --- a/src/gateware/kasli_soc.py +++ b/src/gateware/kasli_soc.py @@ -87,6 +87,8 @@ class GenericStandalone(SoCCore): self.acpki = acpki self.rustc_cfg = dict() + self.rustc_cfg["hw_rev"] = description["hw_rev"] + platform = kasli_soc.Platform() platform.toolchain.bitstream_commands.extend([ "set_property BITSTREAM.GENERAL.COMPRESS True [current_design]", @@ -179,6 +181,8 @@ class GenericMaster(SoCCore): self.acpki = acpki self.rustc_cfg = dict() + self.rustc_cfg["hw_rev"] = description["hw_rev"] + platform = kasli_soc.Platform() platform.toolchain.bitstream_commands.extend([ "set_property BITSTREAM.GENERAL.COMPRESS True [current_design]", @@ -321,6 +325,8 @@ class GenericSatellite(SoCCore): self.acpki = acpki self.rustc_cfg = dict() + self.rustc_cfg["hw_rev"] = description["hw_rev"] + platform = kasli_soc.Platform() platform.toolchain.bitstream_commands.extend([ "set_property BITSTREAM.GENERAL.COMPRESS True [current_design]", -- 2.42.0 From f814a2006fd1dc46b35a8a762801ba8ee989b15d Mon Sep 17 00:00:00 2001 From: MorganTL Date: Thu, 10 Aug 2023 12:31:10 +0800 Subject: [PATCH 08/10] - io_expander: modify function to take i2c - io_expander: remove i2c in struct - io_expander: rename variable - satman: create ioexpander object earlier in main - runtime: create ioexpander object earlier in main - runtime: rename async io_expander_service & takes in refcell - runtime: inline wait function in block_async parameter --- src/libboard_artiq/src/io_expander.rs | 105 +++++++++++--------------- src/runtime/src/main.rs | 79 ++++++++++++------- src/satman/src/main.rs | 45 +++++++---- 3 files changed, 125 insertions(+), 104 deletions(-) diff --git a/src/libboard_artiq/src/io_expander.rs b/src/libboard_artiq/src/io_expander.rs index 009c334..f9d79ac 100644 --- a/src/libboard_artiq/src/io_expander.rs +++ b/src/libboard_artiq/src/io_expander.rs @@ -13,38 +13,35 @@ struct Registers { } //IO expanders pins -const IO_DIR_INPUT_ALL: u8 = 0xFF; -const IO_DIR_OUT_SFP_TX_DISABLE: u8 = !0x02; -const IO_DIR_OUT_SFP_LED: u8 = !0x40; +const IODIR_OUT_SFP_TX_DISABLE: u8 = 0x02; +const IODIR_OUT_SFP_LED: u8 = 0x40; #[cfg(hw_rev = "v1.0")] -const IO_DIR_OUT_SFP0_LED: u8 = !0x40; +const IODIR_OUT_SFP0_LED: u8 = 0x40; #[cfg(hw_rev = "v1.1")] -const IO_DIR_OUT_SFP0_LED: u8 = !0x80; +const IODIR_OUT_SFP0_LED: u8 = 0x80; //IO expander port direction -const IO_DIR_MAPPING0: [u8; 2] = [ - IO_DIR_INPUT_ALL & IO_DIR_OUT_SFP_TX_DISABLE & (IO_DIR_OUT_SFP0_LED), - IO_DIR_INPUT_ALL & IO_DIR_OUT_SFP_TX_DISABLE & IO_DIR_OUT_SFP_LED, +const IODIR0: [u8; 2] = [ + 0xFF & !IODIR_OUT_SFP_TX_DISABLE & !IODIR_OUT_SFP0_LED, + 0xFF & !IODIR_OUT_SFP_TX_DISABLE & !IODIR_OUT_SFP_LED, ]; -const IO_DIR_MAPPING1: [u8; 2] = [ - IO_DIR_INPUT_ALL & IO_DIR_OUT_SFP_TX_DISABLE & IO_DIR_OUT_SFP_LED, - IO_DIR_INPUT_ALL & IO_DIR_OUT_SFP_TX_DISABLE & IO_DIR_OUT_SFP_LED, +const IODIR1: [u8; 2] = [ + 0xFF & !IODIR_OUT_SFP_TX_DISABLE & !IODIR_OUT_SFP_LED, + 0xFF & !IODIR_OUT_SFP_TX_DISABLE & !IODIR_OUT_SFP_LED, ]; -pub struct IoExpander<'a> { - i2c: &'a mut i2c::I2c, +pub struct IoExpander { address: u8, + virtual_led_mapping: &'static [(u8, u8, u8)], iodir: [u8; 2], out_current: [u8; 2], out_target: [u8; 2], registers: Registers, - virtual_led_mapping: &'static [(u8, u8, u8)], - channel: usize, } -impl<'a> IoExpander<'a> { - pub fn new(i2c: &'a mut i2c::I2c, index: u8) -> Result { +impl IoExpander { + pub fn new(i2c: &mut i2c::I2c, index: u8) -> Result { #[cfg(hw_rev = "v1.0")] const VIRTUAL_LED_MAPPING0: [(u8, u8, u8); 2] = [(0, 0, 6), (1, 1, 6)]; #[cfg(hw_rev = "v1.1")] @@ -55,11 +52,9 @@ impl<'a> IoExpander<'a> { // Both expanders on SHARED I2C bus let mut io_expander = match index { 0 => IoExpander { - i2c, - channel: 0, address: 0x40, virtual_led_mapping: &VIRTUAL_LED_MAPPING0, - iodir: IO_DIR_MAPPING0, + iodir: IODIR0, out_current: [0; 2], out_target: [0; 2], registers: Registers { @@ -70,11 +65,9 @@ impl<'a> IoExpander<'a> { }, }, 1 => IoExpander { - i2c, - channel: 1, address: 0x42, virtual_led_mapping: &VIRTUAL_LED_MAPPING1, - iodir: IO_DIR_MAPPING1, + iodir: IODIR1, out_current: [0; 2], out_target: [0; 2], registers: Registers { @@ -86,7 +79,7 @@ impl<'a> IoExpander<'a> { }, _ => return Err("incorrect I/O expander index"), }; - if !io_expander.check_ack()? { + if !io_expander.check_ack(i2c)? { info!("MCP23017 io expander {} not found. Checking for PCA9539.", index); io_expander.address += 0xa8; // translate to PCA9539 addresses (see schematic) io_expander.registers = Registers { @@ -95,64 +88,58 @@ impl<'a> IoExpander<'a> { gpioa: 0x02, gpiob: 0x03, }; - if !io_expander.check_ack()? { + if !io_expander.check_ack(i2c)? { return Err("Neither MCP23017 nor PCA9539 io expander found."); }; } Ok(io_expander) } - fn select(&mut self) -> Result<(), &'static str> { - self.i2c.pca954x_select(0x70, None)?; - self.i2c.pca954x_select(0x71, Some(3))?; + fn select(&self, i2c: &mut i2c::I2c) -> Result<(), &'static str> { + i2c.pca954x_select(0x70, None)?; + i2c.pca954x_select(0x71, Some(3))?; Ok(()) } - 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()?; + fn write(&self, i2c: &mut i2c::I2c, addr: u8, value: u8) -> Result<(), &'static str> { + i2c.start()?; + i2c.write(self.address)?; + i2c.write(addr)?; + i2c.write(value)?; + i2c.stop()?; Ok(()) } - fn check_ack(&mut self) -> Result { + fn check_ack(&self, i2c: &mut i2c::I2c) -> Result { // Check for ack from io expander - self.select()?; - self.i2c.start()?; - let ack = self.i2c.write(self.address)?; - self.i2c.stop()?; + self.select(i2c)?; + i2c.start()?; + let ack = i2c.write(self.address)?; + i2c.stop()?; Ok(ack) } - fn update_iodir(&mut self) -> Result<(), &'static str> { - self.write(self.registers.iodira, self.iodir[0])?; - self.write(self.registers.iodirb, self.iodir[1])?; + fn update_iodir(&self, i2c: &mut i2c::I2c) -> Result<(), &'static str> { + self.write(i2c, self.registers.iodira, self.iodir[0])?; + self.write(i2c, self.registers.iodirb, self.iodir[1])?; Ok(()) } - pub fn init(&mut self) -> Result<(), &'static str> { - self.select()?; + pub fn init(&mut self, i2c: &mut i2c::I2c) -> Result<(), &'static str> { + self.select(i2c)?; - self.iodir = match self.channel { - 0 => IO_DIR_MAPPING0, - 1 => IO_DIR_MAPPING1, - _ => [IO_DIR_INPUT_ALL; 2], - }; - - self.update_iodir()?; + self.update_iodir(i2c)?; self.out_current[0] = 0x00; - self.write(self.registers.gpioa, 0x00)?; + self.write(i2c, self.registers.gpioa, 0x00)?; self.out_current[1] = 0x00; - self.write(self.registers.gpiob, 0x00)?; + self.write(i2c, self.registers.gpiob, 0x00)?; Ok(()) } - pub fn set_oe(&mut self, port: u8, outputs: u8) -> Result<(), &'static str> { + pub fn set_oe(&mut self, i2c: &mut i2c::I2c, port: u8, outputs: u8) -> Result<(), &'static str> { self.iodir[port as usize] &= !outputs; - self.update_iodir()?; + self.update_iodir(i2c)?; Ok(()) } @@ -164,20 +151,20 @@ impl<'a> IoExpander<'a> { } } - pub fn service(&mut self) -> Result<(), &'static str> { + pub fn service(&mut self, i2c: &mut i2c::I2c) -> Result<(), &'static str> { for (led, port, bit) in self.virtual_led_mapping.iter() { let level = unsafe { csr::virtual_leds::status_read() >> led & 1 }; self.set(*port, *bit, level != 0); } if self.out_target != self.out_current { - self.select()?; + self.select(i2c)?; if self.out_target[0] != self.out_current[0] { - self.write(self.registers.gpioa, self.out_target[0])?; + self.write(i2c, self.registers.gpioa, self.out_target[0])?; self.out_current[0] = self.out_target[0]; } if self.out_target[1] != self.out_current[1] { - self.write(self.registers.gpiob, self.out_target[1])?; + self.write(i2c, self.registers.gpiob, self.out_target[1])?; self.out_current[1] = self.out_target[1]; } } diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index 229c042..3d6ebdc 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -12,6 +12,8 @@ #[macro_use] extern crate alloc; +use core::cell::RefCell; + use libasync::{block_async, task}; #[cfg(feature = "target_kasli_soc")] use libboard_artiq::io_expander; @@ -106,25 +108,33 @@ async fn report_async_rtio_errors() { static mut LAST_VIRTUAL_LED_STATUS: u8 = 0; #[cfg(all(feature = "target_kasli_soc", has_drtio))] -fn wait_for_virtual_leds_change() -> nb::Result<(), Void> { - unsafe { - let current = pl::csr::virtual_leds::status_read(); - if current != LAST_VIRTUAL_LED_STATUS { - LAST_VIRTUAL_LED_STATUS = current; - Ok(()) - } else { - Err(nb::Error::WouldBlock) - } - } -} -#[cfg(all(feature = "target_kasli_soc", has_drtio))] -async fn async_io_expanders_service() { - let mut io_expander0 = io_expander::IoExpander::new(unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() }, 0).unwrap(); - let mut io_expander1 = io_expander::IoExpander::new(unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() }, 1).unwrap(); +async fn io_expanders_service( + i2c_bus: RefCell<&mut libboard_zynq::i2c::I2c>, + io_expander0: RefCell, + io_expander1: RefCell, +) { loop { - let _ = block_async!(wait_for_virtual_leds_change()).await; - io_expander0.service().expect("I2C I/O expander #0 service failed"); - io_expander1.service().expect("I2C I/O expander #1 service failed"); + let _ = block_async!((|| -> nb::Result<(), Void> { + unsafe { + let current = pl::csr::virtual_leds::status_read(); + if current != LAST_VIRTUAL_LED_STATUS { + LAST_VIRTUAL_LED_STATUS = current; + Ok(()) + } else { + Err(nb::Error::WouldBlock) + } + } + })()) + .await; + + io_expander0 + .borrow_mut() + .service(&mut i2c_bus.borrow_mut()) + .expect("I2C I/O expander #0 service failed"); + io_expander1 + .borrow_mut() + .service(&mut i2c_bus.borrow_mut()) + .expect("I2C I/O expander #1 service failed"); } } @@ -148,18 +158,26 @@ pub fn main_core0() { info!("gateware ident: {}", identifier_read(&mut [0; 64])); i2c::init(); + let i2c_bus = unsafe { (i2c::I2C_BUS).as_mut().unwrap() }; + let (mut io_expander0, mut io_expander1); #[cfg(feature = "target_kasli_soc")] { - let i2c = unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() }; - for expander_i in 0..=1 { - let mut io_expander = io_expander::IoExpander::new(i2c, expander_i).unwrap(); - io_expander.init().expect("I2C I/O expander #0 initialization failed"); - // Actively drive TX_DISABLE to false on SFP0..3 - io_expander.set(0, 1, false); - io_expander.set(1, 1, false); - io_expander.service().unwrap(); - } + io_expander0 = io_expander::IoExpander::new(i2c_bus, 0).unwrap(); + io_expander1 = io_expander::IoExpander::new(i2c_bus, 1).unwrap(); + io_expander0 + .init(i2c_bus) + .expect("I2C I/O expander #0 initialization failed"); + io_expander1 + .init(i2c_bus) + .expect("I2C I/O expander #1 initialization failed"); + // Actively drive TX_DISABLE to false on SFP0..3 + io_expander0.set(0, 1, false); + io_expander1.set(0, 1, false); + io_expander0.set(1, 1, false); + io_expander1.set(1, 1, false); + io_expander0.service(i2c_bus).unwrap(); + io_expander1.service(i2c_bus).unwrap(); } let cfg = match Config::new() { @@ -175,7 +193,10 @@ pub fn main_core0() { task::spawn(report_async_rtio_errors()); #[cfg(all(feature = "target_kasli_soc", has_drtio))] - task::spawn(async_io_expanders_service()); - + task::spawn(io_expanders_service( + RefCell::new(i2c_bus), + RefCell::new(io_expander0), + RefCell::new(io_expander1), + )); comms::main(timer, cfg); } diff --git a/src/satman/src/main.rs b/src/satman/src/main.rs index d79bd9f..6fcd991 100644 --- a/src/satman/src/main.rs +++ b/src/satman/src/main.rs @@ -610,18 +610,26 @@ pub extern "C" fn main_core0() -> i32 { ram::init_alloc_core0(); let mut i2c = I2c::i2c0(); - let i2c_ptr = &mut i2c as *mut I2c; i2c.init().expect("I2C initialization failed"); + + let (mut io_expander0, mut io_expander1); #[cfg(feature = "target_kasli_soc")] { - for expander_i in 0..=1 { - let mut io_expander = io_expander::IoExpander::new(&mut i2c, expander_i).unwrap(); - io_expander.init().expect("I2C I/O expander #0 initialization failed"); - // Actively drive TX_DISABLE to false on SFP0..3 - io_expander.set(0, 1, false); - io_expander.set(1, 1, false); - io_expander.service().unwrap(); - } + io_expander0 = io_expander::IoExpander::new(&mut i2c, 0).unwrap(); + io_expander1 = io_expander::IoExpander::new(&mut i2c, 1).unwrap(); + io_expander0 + .init(&mut i2c) + .expect("I2C I/O expander #0 initialization failed"); + io_expander1 + .init(&mut i2c) + .expect("I2C I/O expander #1 initialization failed"); + // Actively drive TX_DISABLE to false on SFP0..3 + io_expander0.set(0, 1, false); + io_expander1.set(0, 1, false); + io_expander0.set(1, 1, false); + io_expander1.set(1, 1, false); + io_expander0.service(&mut i2c).unwrap(); + io_expander1.service(&mut i2c).unwrap(); } #[cfg(has_si5324)] @@ -656,9 +664,6 @@ pub extern "C" fn main_core0() -> i32 { let mut hardware_tick_ts = 0; - let mut io_expander0 = io_expander::IoExpander::new(unsafe { &mut *i2c_ptr }, 0).unwrap(); - let mut io_expander1 = io_expander::IoExpander::new(unsafe { &mut *i2c_ptr }, 1).unwrap(); - loop { while !drtiosat_link_rx_up() { drtiosat_process_errors(); @@ -668,8 +673,12 @@ pub extern "C" fn main_core0() -> i32 { } #[cfg(all(feature = "target_kasli_soc", has_drtio))] { - io_expander0.service().expect("I2C I/O expander #0 service failed"); - io_expander1.service().expect("I2C I/O expander #1 service failed"); + io_expander0 + .service(&mut i2c) + .expect("I2C I/O expander #0 service failed"); + io_expander1 + .service(&mut i2c) + .expect("I2C I/O expander #1 service failed"); } hardware_tick(&mut hardware_tick_ts, &mut timer); @@ -710,8 +719,12 @@ pub extern "C" fn main_core0() -> i32 { } #[cfg(all(feature = "target_kasli_soc", has_drtio))] { - io_expander0.service().expect("I2C I/O expander #0 service failed"); - io_expander1.service().expect("I2C I/O expander #1 service failed"); + io_expander0 + .service(&mut i2c) + .expect("I2C I/O expander #0 service failed"); + io_expander1 + .service(&mut i2c) + .expect("I2C I/O expander #1 service failed"); } hardware_tick(&mut hardware_tick_ts, &mut timer); if drtiosat_tsc_loaded() { -- 2.42.0 From cfe53a57a370e375ee38cdea78d310894ba18969 Mon Sep 17 00:00:00 2001 From: MorganTL Date: Fri, 18 Aug 2023 13:34:25 +0800 Subject: [PATCH 09/10] - runtime: replace block_sync with r#yield - runtime: chagne cfg that uses has_drtio - satman: chagne cfg that uses has_drtio --- src/runtime/src/main.rs | 21 +++------------------ src/satman/src/main.rs | 4 ++-- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index 3d6ebdc..4f6433e 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -104,29 +104,14 @@ async fn report_async_rtio_errors() { } } -#[cfg(all(feature = "target_kasli_soc", has_drtio))] -static mut LAST_VIRTUAL_LED_STATUS: u8 = 0; - -#[cfg(all(feature = "target_kasli_soc", has_drtio))] +#[cfg(feature = "target_kasli_soc")] async fn io_expanders_service( i2c_bus: RefCell<&mut libboard_zynq::i2c::I2c>, io_expander0: RefCell, io_expander1: RefCell, ) { loop { - let _ = block_async!((|| -> nb::Result<(), Void> { - unsafe { - let current = pl::csr::virtual_leds::status_read(); - if current != LAST_VIRTUAL_LED_STATUS { - LAST_VIRTUAL_LED_STATUS = current; - Ok(()) - } else { - Err(nb::Error::WouldBlock) - } - } - })()) - .await; - + task::r#yield().await; io_expander0 .borrow_mut() .service(&mut i2c_bus.borrow_mut()) @@ -192,7 +177,7 @@ pub fn main_core0() { task::spawn(report_async_rtio_errors()); - #[cfg(all(feature = "target_kasli_soc", has_drtio))] + #[cfg(feature = "target_kasli_soc")] task::spawn(io_expanders_service( RefCell::new(i2c_bus), RefCell::new(io_expander0), diff --git a/src/satman/src/main.rs b/src/satman/src/main.rs index 6fcd991..db82244 100644 --- a/src/satman/src/main.rs +++ b/src/satman/src/main.rs @@ -671,7 +671,7 @@ pub extern "C" fn main_core0() -> i32 { for mut rep in repeaters.iter_mut() { rep.service(&routing_table, rank, &mut timer); } - #[cfg(all(feature = "target_kasli_soc", has_drtio))] + #[cfg(feature = "target_kasli_soc")] { io_expander0 .service(&mut i2c) @@ -717,7 +717,7 @@ pub extern "C" fn main_core0() -> i32 { for mut rep in repeaters.iter_mut() { rep.service(&routing_table, rank, &mut timer); } - #[cfg(all(feature = "target_kasli_soc", has_drtio))] + #[cfg(feature = "target_kasli_soc")] { io_expander0 .service(&mut i2c) -- 2.42.0 From 831140b20df63131bcfcb01f1dc887defbb35bc8 Mon Sep 17 00:00:00 2001 From: MorganTL Date: Mon, 28 Aug 2023 16:07:02 +0800 Subject: [PATCH 10/10] kasli_soc: rename drtio_transceiver to gt_drtio --- src/gateware/kasli_soc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gateware/kasli_soc.py b/src/gateware/kasli_soc.py index 6fbeb4b..106e6cb 100755 --- a/src/gateware/kasli_soc.py +++ b/src/gateware/kasli_soc.py @@ -314,7 +314,7 @@ class GenericMaster(SoCCore): self.csr_devices.append("virtual_leds") self.comb += [self.virtual_leds.get(i).eq(channel.rx_ready) - for i, channel in enumerate(self.drtio_transceiver.channels)] + for i, channel in enumerate(self.gt_drtio.channels)] @@ -486,7 +486,7 @@ class GenericSatellite(SoCCore): self.csr_devices.append("virtual_leds") self.comb += [self.virtual_leds.get(i).eq(channel.rx_ready) - for i, channel in enumerate(self.drtio_transceiver.channels)] + for i, channel in enumerate(self.gt_drtio.channels)] def write_mem_file(soc, filename): -- 2.42.0