diff --git a/artiq/coredevice/i2c.py b/artiq/coredevice/i2c.py index b51a6add2..8fbe56ceb 100644 --- a/artiq/coredevice/i2c.py +++ b/artiq/coredevice/i2c.py @@ -30,6 +30,9 @@ def i2c_read(busno: TInt32, ack: TBool) -> TInt32: class PCA9548: """Driver for the PCA9548 I2C bus switch. + I2C transactions not real-time, and are performed by the CPU without + involving RTIO. + On the KC705, this chip is used for selecting the I2C buses on the two FMC connectors. HPC=1, LPC=2. """ @@ -72,6 +75,9 @@ class PCA9548: class TCA6424A: """Driver for the TCA6424A I2C I/O expander. + I2C transactions not real-time, and are performed by the CPU without + involving RTIO. + On the NIST QC2 hardware, this chip is used for switching the directions of TTL buffers.""" def __init__(self, dmgr, busno=0, address=0x44, core_device="core"): diff --git a/artiq/coredevice/spi.py b/artiq/coredevice/spi.py index 6c4b3e7ea..3b1129604 100644 --- a/artiq/coredevice/spi.py +++ b/artiq/coredevice/spi.py @@ -1,10 +1,20 @@ import numpy -from artiq.language.core import kernel, portable, now_mu, delay_mu +from artiq.language.core import syscall, kernel, portable, now_mu, delay_mu +from artiq.language.types import TInt32, TNone from artiq.language.units import MHz from artiq.coredevice.rtio import rtio_output, rtio_input_data +__all__ = [ + "SPI_DATA_ADDR", "SPI_XFER_ADDR", "SPI_CONFIG_ADDR", + "SPI_OFFLINE", "SPI_ACTIVE", "SPI_PENDING", + "SPI_CS_POLARITY", "SPI_CLK_POLARITY", "SPI_CLK_PHASE", + "SPI_LSB_FIRST", "SPI_HALF_DUPLEX", + "SPIMaster", "NRTSPIMaster" +] + + SPI_DATA_ADDR, SPI_XFER_ADDR, SPI_CONFIG_ADDR = range(3) ( SPI_OFFLINE, @@ -262,3 +272,65 @@ class SPIMaster: rtio_output(now_mu(), self.channel, SPI_CONFIG_ADDR | SPI_RT2WB_READ, 0) return rtio_input_data(self.channel) + + +@syscall(flags={"nounwind", "nowrite"}) +def spi_set_config(busno: TInt32, flags: TInt32, write_div: TInt32, read_div: TInt32) -> TNone: + raise NotImplementedError("syscall not simulated") + + +@syscall(flags={"nounwind", "nowrite"}) +def spi_set_xfer(busno: TInt32, chip_select: TInt32, write_length: TInt32, read_length: TInt32) -> TNone: + raise NotImplementedError("syscall not simulated") + + +@syscall(flags={"nounwind", "nowrite"}) +def spi_write(busno: TInt32, data: TInt32) -> TNone: + raise NotImplementedError("syscall not simulated") + + +@syscall(flags={"nounwind", "nowrite"}) +def spi_read(busno: TInt32) -> TInt32: + raise NotImplementedError("syscall not simulated") + + +class NRTSPIMaster: + """Core device non-realtime Serial Peripheral Interface (SPI) bus master. + Owns one non-realtime SPI bus. + + With this driver, SPI transactions and are performed by the CPU without + involving RTIO. + + Realtime and non-realtime buses are separate and defined at bitstream + compilation time. + + See :class:`SPIMaster` for a description of the methods. + """ + def __init__(self, dmgr, busno, core_device="core"): + self.core = dmgr.get(core_device) + self.busno = busno + + @kernel + def set_config_mu(self, flags=0, write_div=6, read_div=6): + """Set the ``config`` register. + + Note that the non-realtime SPI cores are usually clocked by the system + clock and not the RTIO clock. In many cases, the SPI configuration is + already set by the firmware and you do not need to call this method. + + The offline bit cannot be set using this method. + The SPI bus is briefly taken offline when this method is called. + """ + spi_set_config(self.busno, flags, write_div, read_div) + + @kernel + def set_xfer(self, chip_select=0, write_length=0, read_length=0): + spi_set_xfer(self.busno, chip_select, write_length, read_length) + + @kernel + def write(self, data=0): + spi_write(self.busno, data) + + @kernel + def read(self): + return spi_read(self.busno) diff --git a/artiq/firmware/ksupport/api.rs b/artiq/firmware/ksupport/api.rs index efb458f68..792f92f52 100644 --- a/artiq/firmware/ksupport/api.rs +++ b/artiq/firmware/ksupport/api.rs @@ -117,8 +117,13 @@ static mut API: &'static [(&'static str, *const ())] = &[ api!(drtio_get_packet_counts = ::rtio::drtio_dbg::get_packet_counts), api!(drtio_get_fifo_space_req_count = ::rtio::drtio_dbg::get_fifo_space_req_count), - api!(i2c_start = ::i2c_start), - api!(i2c_stop = ::i2c_stop), - api!(i2c_write = ::i2c_write), - api!(i2c_read = ::i2c_read), + api!(i2c_start = ::nrt_bus::i2c::start), + api!(i2c_stop = ::nrt_bus::i2c::stop), + api!(i2c_write = ::nrt_bus::i2c::write), + api!(i2c_read = ::nrt_bus::i2c::read), + + api!(spi_set_config = ::nrt_bus::spi::set_config), + api!(spi_set_xfer = ::nrt_bus::spi::set_xfer), + api!(spi_write = ::nrt_bus::spi::write), + api!(spi_read = ::nrt_bus::spi::read), ]; diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index 0fd8c9f9b..2f06b0118 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -89,6 +89,7 @@ macro_rules! raise { pub mod eh; mod api; mod rtio; +mod nrt_bus; static mut NOW: u64 = 0; static mut LIBRARY: Option> = None; @@ -220,24 +221,6 @@ extern fn cache_put(key: CSlice, list: CSlice) { }) } -extern fn i2c_start(busno: i32) { - send(&I2cStartRequest { busno: busno as u8 }); -} - -extern fn i2c_stop(busno: i32) { - send(&I2cStopRequest { busno: busno as u8 }); -} - -extern fn i2c_write(busno: i32, data: i32) -> bool { - send(&I2cWriteRequest { busno: busno as u8, data: data as u8 }); - recv!(&I2cWriteReply { ack } => ack) -} - -extern fn i2c_read(busno: i32, ack: bool) -> i32 { - send(&I2cReadRequest { busno: busno as u8, ack: ack }); - recv!(&I2cReadReply { data } => data) as i32 -} - const DMA_BUFFER_SIZE: usize = 64 * 1024; struct DmaRecorder { diff --git a/artiq/firmware/ksupport/nrt_bus.rs b/artiq/firmware/ksupport/nrt_bus.rs new file mode 100644 index 000000000..1f05f189b --- /dev/null +++ b/artiq/firmware/ksupport/nrt_bus.rs @@ -0,0 +1,48 @@ +pub mod i2c { + use ::send; + use ::recv; + use kernel_proto::*; + + pub extern fn start(busno: i32) { + send(&I2cStartRequest { busno: busno as u8 }); + } + + pub extern fn stop(busno: i32) { + send(&I2cStopRequest { busno: busno as u8 }); + } + + pub extern fn write(busno: i32, data: i32) -> bool { + send(&I2cWriteRequest { busno: busno as u8, data: data as u8 }); + recv!(&I2cWriteReply { ack } => ack) + } + + pub extern fn read(busno: i32, ack: bool) -> i32 { + send(&I2cReadRequest { busno: busno as u8, ack: ack }); + recv!(&I2cReadReply { data } => data) as i32 + } +} + +pub mod spi { + use ::send; + use ::recv; + use kernel_proto::*; + + pub extern fn set_config(busno: i32, flags: i32, write_div: i32, read_div: i32) { + send(&SpiSetConfigRequest { busno: busno as u32, flags: flags as u8, + write_div: write_div as u8, read_div: read_div as u8 }); + } + + pub extern fn set_xfer(busno: i32, chip_select: i32, write_length: i32, read_length: i32) { + send(&SpiSetXferRequest { busno: busno as u32, chip_select: chip_select as u16, + write_length: write_length as u8, read_length: read_length as u8 }); + } + + pub extern fn write(busno: i32, data: i32) { + send(&SpiWriteRequest { busno: busno as u32, data: data as u32 }); + } + + pub extern fn read(busno: i32) -> i32 { + send(&SpiReadRequest { busno: busno as u32 }); + recv!(&SpiReadReply { data } => data) as i32 + } +} diff --git a/artiq/firmware/libboard/i2c.rs b/artiq/firmware/libboard/i2c.rs index 6a2fb61c8..4f9c6b7b3 100644 --- a/artiq/firmware/libboard/i2c.rs +++ b/artiq/firmware/libboard/i2c.rs @@ -1,147 +1,171 @@ use csr; -use clock; -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) } +#[cfg(has_i2c)] +mod io { + use csr; + use clock; -fn sda_i(busno: u8) -> bool { - unsafe { - csr::i2c::in_read() & sda_bit(busno) != 0 - } -} - -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) }; - csr::i2c::oe_write(reg) - } -} - -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) }; - csr::i2c::out_write(reg) - } -} - -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) }; - csr::i2c::oe_write(reg) - } -} - -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) + pub 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 { + unsafe { + csr::i2c::in_read() & sda_bit(busno) != 0 + } + } + + pub 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) }; + csr::i2c::oe_write(reg) + } + } + + pub 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) }; + csr::i2c::out_write(reg) + } + } + + pub 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) }; + csr::i2c::oe_write(reg) + } + } + + pub 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 - scl_o(busno, true); - scl_oe(busno, true); + io::scl_o(busno, true); + io::scl_oe(busno, true); // Prepare a zero level on SDA so that sda_oe pulls it down - sda_o(busno, false); + io::sda_o(busno, false); // Release SDA - sda_oe(busno, false); + io::sda_oe(busno, false); // Check the I2C bus is ready - half_period(); - half_period(); - if !sda_i(busno) { + io::half_period(); + io::half_period(); + if !io::sda_i(busno) { error!("SDA is stuck low on bus #{}", busno) } } } +#[cfg(has_i2c)] pub fn start(busno: u8) { // Set SCL high then SDA low - scl_o(busno, true); - half_period(); - sda_oe(busno, true); - half_period(); + io::scl_o(busno, true); + io::half_period(); + io::sda_oe(busno, true); + io::half_period(); } +#[cfg(has_i2c)] pub fn restart(busno: u8) { // Set SCL low then SDA high */ - scl_o(busno, false); - half_period(); - sda_oe(busno, false); - half_period(); + io::scl_o(busno, false); + io::half_period(); + io::sda_oe(busno, false); + io::half_period(); // Do a regular start start(busno); } +#[cfg(has_i2c)] pub fn stop(busno: u8) { // First, make sure SCL is low, so that the target releases the SDA line - scl_o(busno, false); - half_period(); + io::scl_o(busno, false); + io::half_period(); // Set SCL high then SDA high - sda_oe(busno, true); - scl_o(busno, true); - half_period(); - sda_oe(busno, false); - half_period(); + io::sda_oe(busno, true); + io::scl_o(busno, true); + io::half_period(); + io::sda_oe(busno, false); + io::half_period(); } +#[cfg(has_i2c)] pub fn write(busno: u8, data: u8) -> bool { // 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(); + 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 - scl_o(busno, true); - half_period(); + io::scl_o(busno, true); + io::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); + io::scl_o(busno, false); + io::half_period(); + io::sda_oe(busno, false); // Set SCL high and check for ack - scl_o(busno, true); - half_period(); + io::scl_o(busno, true); + io::half_period(); // returns true if acked (I2C target pulled SDA low) - !sda_i(busno) + !io::sda_i(busno) } +#[cfg(has_i2c)] pub fn read(busno: u8, ack: bool) -> u8 { // 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); + 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() { - scl_o(busno, false); - half_period(); + io::scl_o(busno, false); + io::half_period(); // Set SCL high and shift data - scl_o(busno, true); - half_period(); - if sda_i(busno) { data |= 1 << bit } + 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 - scl_o(busno, false); - if ack { sda_oe(busno, true) } - half_period(); + io::scl_o(busno, false); + if ack { io::sda_oe(busno, true) } + io::half_period(); // then set SCL high - scl_o(busno, true); - half_period(); + io::scl_o(busno, true); + io::half_period(); data } + +#[cfg(not(has_i2c))] +pub fn init() {} +#[cfg(not(has_i2c))] +pub fn start(_busno: u8) {} +#[cfg(not(has_i2c))] +pub fn restart(_busno: u8) {} +#[cfg(not(has_i2c))] +pub fn stop(_busno: u8) {} +#[cfg(not(has_i2c))] +pub fn write(_busno: u8, _data: u8) -> bool { false } +#[cfg(not(has_i2c))] +pub fn read(_busno: u8, _ack: bool) { 0xff } diff --git a/artiq/firmware/libboard/lib.rs b/artiq/firmware/libboard/lib.rs index 3c1f3cac8..d0c6ecc77 100644 --- a/artiq/firmware/libboard/lib.rs +++ b/artiq/firmware/libboard/lib.rs @@ -19,8 +19,9 @@ pub mod uart_console; #[cfg(has_spiflash)] pub mod spiflash; -#[cfg(has_i2c)] pub mod i2c; +pub mod spi; + #[cfg(has_si5324)] pub mod si5324; diff --git a/artiq/firmware/libboard/spi.rs b/artiq/firmware/libboard/spi.rs new file mode 100644 index 000000000..afacb652a --- /dev/null +++ b/artiq/firmware/libboard/spi.rs @@ -0,0 +1,54 @@ +#[cfg(has_converter_spi)] +use csr; + +// Later this module should support other buses than the converter SPI bus, +// and add a busno parameter to differentiate them. + +#[cfg(has_converter_spi)] +pub fn set_config(flags: u8, write_div: u8, read_div: u8) { + unsafe { + csr::converter_spi::offline_write(1); + csr::converter_spi::cs_polarity_write(flags >> 3 & 1); + csr::converter_spi::clk_polarity_write(flags >> 4 & 1); + csr::converter_spi::clk_phase_write(flags >> 5 & 1); + csr::converter_spi::lsb_first_write(flags >> 6 & 1); + csr::converter_spi::half_duplex_write(flags >> 7 & 1); + csr::converter_spi::clk_div_write_write(write_div); + csr::converter_spi::clk_div_read_write(read_div); + csr::converter_spi::offline_write(0); + } +} + +#[cfg(has_converter_spi)] +pub fn set_xfer(chip_select: u16, write_length: u8, read_length: u8) { + unsafe { + csr::converter_spi::cs_write(chip_select as _); + csr::converter_spi::xfer_len_write_write(write_length); + csr::converter_spi::xfer_len_read_write(read_length); + } +} + +#[cfg(has_converter_spi)] +pub fn write(data: u32) { + unsafe { + csr::converter_spi::data_write_write(data); + while csr::converter_spi::pending_read() != 0 {} + while csr::converter_spi::active_read() != 0 {} + } +} + +#[cfg(has_converter_spi)] +pub fn read() -> u32 { + unsafe { + csr::converter_spi::data_read_read() + } +} + +#[cfg(not(has_converter_spi))] +pub fn set_config(_flags: u8, _write_div: u8, _read_div: u8) {} +#[cfg(not(has_converter_spi))] +pub fn set_xfer(_chip_select: u16, _write_length: u8, _read_length: u8) {} +#[cfg(not(has_converter_spi))] +pub fn write(_data: u32) {} +#[cfg(not(has_converter_spi))] +pub fn read() -> u32 { 0 } diff --git a/artiq/firmware/libproto/kernel_proto.rs b/artiq/firmware/libproto/kernel_proto.rs index 8688e534a..22fd38a18 100644 --- a/artiq/firmware/libproto/kernel_proto.rs +++ b/artiq/firmware/libproto/kernel_proto.rs @@ -87,6 +87,12 @@ pub enum Message<'a> { I2cReadRequest { busno: u8, ack: bool }, I2cReadReply { data: u8 }, + SpiSetConfigRequest { busno: u32, flags: u8, write_div: u8, read_div: u8 }, + SpiSetXferRequest { busno: u32, chip_select: u16, write_length: u8, read_length: u8 }, + SpiWriteRequest { busno: u32, data: u32 }, + SpiReadRequest { busno: u32 }, + SpiReadReply { data: u32 }, + Log(fmt::Arguments<'a>), LogSlice(&'a str) } diff --git a/artiq/firmware/runtime/kern_hwreq.rs b/artiq/firmware/runtime/kern_hwreq.rs new file mode 100644 index 000000000..ca21b5ed7 --- /dev/null +++ b/artiq/firmware/runtime/kern_hwreq.rs @@ -0,0 +1,123 @@ +use session::{kern_acknowledge, kern_send}; +use rtio_mgt; +use board; +use kernel_proto as kern; +use std::io; +use sched::Io; + +// TODO +mod drtio_spi { + pub fn set_config(_busno: u32, _flags: u8, _write_div: u8, _read_div: u8) {} + pub fn set_xfer(_busno: u32, _chip_select: u16, _write_length: u8, _read_length: u8) {} + pub fn write(_busno: u32, _data: u32) {} + pub fn read(_busno: u32) -> u32 { 0 } +} + +mod spi { + use board; + use super::drtio_spi; + + pub fn set_config(busno: u32, flags: u8, write_div: u8, read_div: u8) { + let drtio = busno >> 16; + if drtio == 0 { + board::spi::set_config(flags, write_div, read_div) + } else { + drtio_spi::set_config(busno, flags, write_div, read_div) + } + } + + pub fn set_xfer(busno: u32, chip_select: u16, write_length: u8, read_length: u8) { + let drtio = busno >> 16; + if drtio == 0 { + board::spi::set_xfer(chip_select, write_length, read_length) + } else { + drtio_spi::set_xfer(busno, chip_select, write_length, read_length) + } + } + + pub fn write(busno: u32, data: u32) { + let drtio = busno >> 16; + if drtio == 0 { + board::spi::write(data) + } else { + drtio_spi::write(busno, data) + } + } + + pub fn read(busno: u32) -> u32 { + let drtio = busno >> 16; + if drtio == 0 { + board::spi::read() + } else { + drtio_spi::read(busno) + } + } +} + +pub fn process_kern_hwreq(io: &Io, request: &kern::Message) -> io::Result { + match request { + &kern::RtioInitRequest => { + info!("resetting RTIO"); + rtio_mgt::init_core(); + kern_acknowledge() + } + + &kern::DrtioChannelStateRequest { channel } => { + let (fifo_space, last_timestamp) = rtio_mgt::drtio_dbg::get_channel_state(channel); + kern_send(io, &kern::DrtioChannelStateReply { fifo_space: fifo_space, + last_timestamp: last_timestamp }) + } + &kern::DrtioResetChannelStateRequest { channel } => { + rtio_mgt::drtio_dbg::reset_channel_state(channel); + kern_acknowledge() + } + &kern::DrtioGetFifoSpaceRequest { channel } => { + rtio_mgt::drtio_dbg::get_fifo_space(channel); + kern_acknowledge() + } + &kern::DrtioPacketCountRequest => { + let (tx_cnt, rx_cnt) = rtio_mgt::drtio_dbg::get_packet_counts(); + kern_send(io, &kern::DrtioPacketCountReply { tx_cnt: tx_cnt, rx_cnt: rx_cnt }) + } + &kern::DrtioFifoSpaceReqCountRequest => { + let cnt = rtio_mgt::drtio_dbg::get_fifo_space_req_count(); + kern_send(io, &kern::DrtioFifoSpaceReqCountReply { cnt: cnt }) + } + + &kern::I2cStartRequest { busno } => { + board::i2c::start(busno); + kern_acknowledge() + } + &kern::I2cStopRequest { busno } => { + board::i2c::stop(busno); + kern_acknowledge() + } + &kern::I2cWriteRequest { busno, data } => { + let ack = board::i2c::write(busno, data); + kern_send(io, &kern::I2cWriteReply { ack: ack }) + } + &kern::I2cReadRequest { busno, ack } => { + let data = board::i2c::read(busno, ack); + kern_send(io, &kern::I2cReadReply { data: data }) + }, + + &kern::SpiSetConfigRequest { busno, flags, write_div, read_div } => { + spi::set_config(busno, flags, write_div, read_div); + kern_acknowledge() + }, + &kern::SpiSetXferRequest { busno, chip_select, write_length, read_length } => { + spi::set_xfer(busno, chip_select, write_length, read_length); + kern_acknowledge() + } + &kern::SpiWriteRequest { busno, data } => { + spi::write(busno, data); + kern_acknowledge() + } + &kern::SpiReadRequest { busno } => { + let data = spi::read(busno); + kern_send(io, &kern::SpiReadReply { data: data }) + }, + + _ => return Ok(false) + }.and(Ok(true)) +} diff --git a/artiq/firmware/runtime/lib.rs b/artiq/firmware/runtime/lib.rs index f5a7a16b5..c9cc36315 100644 --- a/artiq/firmware/runtime/lib.rs +++ b/artiq/firmware/runtime/lib.rs @@ -47,6 +47,7 @@ mod rtio_dma; mod mgmt; mod kernel; +mod kern_hwreq; mod session; #[cfg(any(has_rtio_moninj, has_drtio))] mod moninj; diff --git a/artiq/firmware/runtime/session.rs b/artiq/firmware/runtime/session.rs index b1bbf49d0..9feb59d0b 100644 --- a/artiq/firmware/runtime/session.rs +++ b/artiq/firmware/runtime/session.rs @@ -15,6 +15,7 @@ use board; use rpc_proto as rpc; use session_proto as host; use kernel_proto as kern; +use kern_hwreq; macro_rules! unexpected { ($($arg:tt)*) => { @@ -125,7 +126,7 @@ fn host_write(stream: &mut Write, reply: host::Reply) -> io::Result<()> { reply.write_to(stream) } -fn kern_send(io: &Io, request: &kern::Message) -> io::Result<()> { +pub fn kern_send(io: &Io, request: &kern::Message) -> io::Result<()> { match request { &kern::LoadRequest(_) => debug!("comm->kern LoadRequest(...)"), &kern::DmaRetrieveReply { trace, duration } => { @@ -176,7 +177,7 @@ fn kern_recv(io: &Io, f: F) -> io::Result }) } -fn kern_acknowledge() -> io::Result<()> { +pub fn kern_acknowledge() -> io::Result<()> { mailbox::acknowledge(); Ok(()) } @@ -364,6 +365,9 @@ fn process_kern_message(io: &Io, mut stream: Option<&mut TcpStream>, } kern_recv_dotrace(request); + if kern_hwreq::process_kern_hwreq(io, request)? { + return Ok(false) + } match request { &kern::Log(args) => { use std::fmt::Write; @@ -387,12 +391,6 @@ fn process_kern_message(io: &Io, mut stream: Option<&mut TcpStream>, kern_acknowledge() } - &kern::RtioInitRequest => { - info!("resetting RTIO"); - rtio_mgt::init_core(); - kern_acknowledge() - } - &kern::DmaRecordStart(name) => { session.congress.dma_manager.record_start(name); kern_acknowledge() @@ -419,28 +417,6 @@ fn process_kern_message(io: &Io, mut stream: Option<&mut TcpStream>, }) } - &kern::DrtioChannelStateRequest { channel } => { - let (fifo_space, last_timestamp) = rtio_mgt::drtio_dbg::get_channel_state(channel); - kern_send(io, &kern::DrtioChannelStateReply { fifo_space: fifo_space, - last_timestamp: last_timestamp }) - } - &kern::DrtioResetChannelStateRequest { channel } => { - rtio_mgt::drtio_dbg::reset_channel_state(channel); - kern_acknowledge() - } - &kern::DrtioGetFifoSpaceRequest { channel } => { - rtio_mgt::drtio_dbg::get_fifo_space(channel); - kern_acknowledge() - } - &kern::DrtioPacketCountRequest => { - let (tx_cnt, rx_cnt) = rtio_mgt::drtio_dbg::get_packet_counts(); - kern_send(io, &kern::DrtioPacketCountReply { tx_cnt: tx_cnt, rx_cnt: rx_cnt }) - } - &kern::DrtioFifoSpaceReqCountRequest => { - let cnt = rtio_mgt::drtio_dbg::get_fifo_space_req_count(); - kern_send(io, &kern::DrtioFifoSpaceReqCountReply { cnt: cnt }) - } - &kern::WatchdogSetRequest { ms } => { let id = session.watchdog_set.set_ms(ms) .map_err(|()| io_error("out of watchdogs"))?; @@ -478,44 +454,6 @@ fn process_kern_message(io: &Io, mut stream: Option<&mut TcpStream>, kern_send(io, &kern::CachePutReply { succeeded: succeeded }) } - #[cfg(has_i2c)] - &kern::I2cStartRequest { busno } => { - board::i2c::start(busno); - kern_acknowledge() - } - #[cfg(has_i2c)] - &kern::I2cStopRequest { busno } => { - board::i2c::stop(busno); - kern_acknowledge() - } - #[cfg(has_i2c)] - &kern::I2cWriteRequest { busno, data } => { - let ack = board::i2c::write(busno, data); - kern_send(io, &kern::I2cWriteReply { ack: ack }) - } - #[cfg(has_i2c)] - &kern::I2cReadRequest { busno, ack } => { - let data = board::i2c::read(busno, ack); - kern_send(io, &kern::I2cReadReply { data: data }) - } - - #[cfg(not(has_i2c))] - &kern::I2cStartRequest { .. } => { - kern_acknowledge() - } - #[cfg(not(has_i2c))] - &kern::I2cStopRequest { .. } => { - kern_acknowledge() - } - #[cfg(not(has_i2c))] - &kern::I2cWriteRequest { .. } => { - kern_send(io, &kern::I2cWriteReply { ack: false }) - } - #[cfg(not(has_i2c))] - &kern::I2cReadRequest { .. } => { - kern_send(io, &kern::I2cReadReply { data: 0xff }) - } - &kern::RunFinished => { unsafe { kernel::stop() } session.kernel_state = KernelState::Absent;