From 66dee9d1ad04870dbb1a69dd9849b28630c9fe3f Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 21 Jun 2017 16:50:51 +0800 Subject: [PATCH] drtio: send/process I2C and SPI aux packets (#740) --- artiq/firmware/runtime/kern_hwreq.rs | 147 +++++++++++++++++++++++---- artiq/firmware/satman/lib.rs | 45 ++++++++ 2 files changed, 172 insertions(+), 20 deletions(-) diff --git a/artiq/firmware/runtime/kern_hwreq.rs b/artiq/firmware/runtime/kern_hwreq.rs index 8dcd1c33b..ccc5a88b7 100644 --- a/artiq/firmware/runtime/kern_hwreq.rs +++ b/artiq/firmware/runtime/kern_hwreq.rs @@ -4,27 +4,84 @@ use kernel_proto as kern; use std::io; use sched::Io; -// TODO #[cfg(has_drtio)] mod drtio_i2c { - pub fn start(_busno: u32) -> Result<(), ()> { - Err(()) + use drtioaux; + + fn basic_reply() -> Result<(), ()> { + match drtioaux::hw::recv_timeout(None) { + Ok(drtioaux::Packet::I2cBasicReply { succeeded }) => { + if succeeded { Ok(()) } else { Err(()) } + } + Ok(_) => { + error!("received unexpected aux packet"); + Err(()) + } + Err(e) => { + error!("aux packet error ({})", e); + Err(()) + } + } } - pub fn restart(_busno: u32) -> Result<(), ()> { - Err(()) + pub fn start(busno: u32) -> Result<(), ()> { + let request = drtioaux::Packet::I2cStartRequest { busno: busno as u8 }; + drtioaux::hw::send(&request).unwrap(); + basic_reply() } - pub fn stop(_busno: u32) -> Result<(), ()> { - Err(()) + pub fn restart(busno: u32) -> Result<(), ()> { + let request = drtioaux::Packet::I2cRestartRequest { busno: busno as u8 }; + drtioaux::hw::send(&request).unwrap(); + basic_reply() } - pub fn write(_busno: u32, _data: u8) -> Result { - Err(()) + pub fn stop(busno: u32) -> Result<(), ()> { + let request = drtioaux::Packet::I2cStopRequest { busno: busno as u8 }; + drtioaux::hw::send(&request).unwrap(); + basic_reply() } - pub fn read(_busno: u32, _ack: bool) -> Result { - Err(()) + pub fn write(busno: u32, data: u8) -> Result { + let request = drtioaux::Packet::I2cWriteRequest { + busno: busno as u8, + data: data + }; + drtioaux::hw::send(&request).unwrap(); + match drtioaux::hw::recv_timeout(None) { + Ok(drtioaux::Packet::I2cWriteReply { succeeded, ack }) => { + if succeeded { Ok(ack) } else { Err(()) } + } + Ok(_) => { + error!("received unexpected aux packet"); + Err(()) + } + Err(e) => { + error!("aux packet error ({})", e); + Err(()) + } + } + } + + pub fn read(busno: u32, ack: bool) -> Result { + let request = drtioaux::Packet::I2cReadRequest { + busno: busno as u8, + ack: ack + }; + drtioaux::hw::send(&request).unwrap(); + match drtioaux::hw::recv_timeout(None) { + Ok(drtioaux::Packet::I2cReadReply { succeeded, data }) => { + if succeeded { Ok(data) } else { Err(()) } + } + Ok(_) => { + error!("received unexpected aux packet"); + Err(()) + } + Err(e) => { + error!("aux packet error ({})", e); + Err(()) + } + } } } @@ -106,23 +163,73 @@ mod i2c { } } -// TODO #[cfg(has_drtio)] mod drtio_spi { - pub fn set_config(_busno: u32, _flags: u8, _write_div: u8, _read_div: u8) -> Result<(), ()> { - Err(()) + use drtioaux; + + fn basic_reply() -> Result<(), ()> { + match drtioaux::hw::recv_timeout(None) { + Ok(drtioaux::Packet::SpiBasicReply { succeeded }) => { + if succeeded { Ok(()) } else { Err(()) } + } + Ok(_) => { + error!("received unexpected aux packet"); + Err(()) + } + Err(e) => { + error!("aux packet error ({})", e); + Err(()) + } + } } - pub fn set_xfer(_busno: u32, _chip_select: u16, _write_length: u8, _read_length: u8) -> Result<(), ()> { - Err(()) + pub fn set_config(busno: u32, flags: u8, write_div: u8, read_div: u8) -> Result<(), ()> { + let request = drtioaux::Packet::SpiSetConfigRequest { + busno: busno as u8, + flags: flags, + write_div: write_div, + read_div: read_div + }; + drtioaux::hw::send(&request).unwrap(); + basic_reply() } - pub fn write(_busno: u32, _data: u32) -> Result<(), ()> { - Err(()) + pub fn set_xfer(busno: u32, chip_select: u16, write_length: u8, read_length: u8) -> Result<(), ()> { + let request = drtioaux::Packet::SpiSetXferRequest { + busno: busno as u8, + chip_select: chip_select, + write_length: write_length, + read_length: read_length + }; + drtioaux::hw::send(&request).unwrap(); + basic_reply() } - pub fn read(_busno: u32) -> Result { - Err(()) + pub fn write(busno: u32, data: u32) -> Result<(), ()> { + let request = drtioaux::Packet::SpiWriteRequest { + busno: busno as u8, + data: data + }; + drtioaux::hw::send(&request).unwrap(); + basic_reply() + } + + pub fn read(busno: u32) -> Result { + let request = drtioaux::Packet::SpiReadRequest { busno: busno as u8 }; + drtioaux::hw::send(&request).unwrap(); + match drtioaux::hw::recv_timeout(None) { + Ok(drtioaux::Packet::SpiReadReply { succeeded, data }) => { + if succeeded { Ok(data) } else { Err(()) } + } + Ok(_) => { + error!("received unexpected aux packet"); + Err(()) + } + Err(e) => { + error!("aux packet error ({})", e); + Err(()) + } + } } } diff --git a/artiq/firmware/satman/lib.rs b/artiq/firmware/satman/lib.rs index 9de4c53f4..c8c8a6a04 100644 --- a/artiq/firmware/satman/lib.rs +++ b/artiq/firmware/satman/lib.rs @@ -76,6 +76,51 @@ fn process_aux_packet(p: &drtioaux::Packet) { let reply = drtioaux::Packet::InjectionStatusReply { value: value }; drtioaux::hw::send(&reply).unwrap(); }, + + drtioaux::Packet::I2cStartRequest { busno } => { + let succeeded = board::i2c::start(busno).is_ok(); + drtioaux::hw::send(&drtioaux::Packet::I2cBasicReply { succeeded: succeeded }).unwrap(); + } + drtioaux::Packet::I2cRestartRequest { busno } => { + let succeeded = board::i2c::restart(busno).is_ok(); + drtioaux::hw::send(&drtioaux::Packet::I2cBasicReply { succeeded: succeeded }).unwrap(); + } + drtioaux::Packet::I2cStopRequest { busno } => { + let succeeded = board::i2c::stop(busno).is_ok(); + drtioaux::hw::send(&drtioaux::Packet::I2cBasicReply { succeeded: succeeded }).unwrap(); + } + drtioaux::Packet::I2cWriteRequest { busno, data } => { + match board::i2c::write(busno, data) { + Ok(ack) => drtioaux::hw::send(&drtioaux::Packet::I2cWriteReply { succeeded: true, ack: ack }).unwrap(), + Err(_) => drtioaux::hw::send(&drtioaux::Packet::I2cWriteReply { succeeded: false, ack: false }).unwrap() + }; + } + drtioaux::Packet::I2cReadRequest { busno, ack } => { + match board::i2c::read(busno, ack) { + Ok(data) => drtioaux::hw::send(&drtioaux::Packet::I2cReadReply { succeeded: true, data: data }).unwrap(), + Err(_) => drtioaux::hw::send(&drtioaux::Packet::I2cReadReply { succeeded: false, data: 0xff }).unwrap() + }; + } + + drtioaux::Packet::SpiSetConfigRequest { busno, flags, write_div, read_div } => { + let succeeded = board::spi::set_config(busno, flags, write_div, read_div).is_ok(); + drtioaux::hw::send(&drtioaux::Packet::SpiBasicReply { succeeded: succeeded }).unwrap(); + }, + drtioaux::Packet::SpiSetXferRequest { busno, chip_select, write_length, read_length } => { + let succeeded = board::spi::set_xfer(busno, chip_select, write_length, read_length).is_ok(); + drtioaux::hw::send(&drtioaux::Packet::SpiBasicReply { succeeded: succeeded }).unwrap(); + } + drtioaux::Packet::SpiWriteRequest { busno, data } => { + let succeeded = board::spi::write(busno, data).is_ok(); + drtioaux::hw::send(&drtioaux::Packet::SpiBasicReply { succeeded: succeeded }).unwrap(); + } + drtioaux::Packet::SpiReadRequest { busno } => { + match board::spi::read(busno) { + Ok(data) => drtioaux::hw::send(&drtioaux::Packet::SpiReadReply { succeeded: true, data: data }).unwrap(), + Err(_) => drtioaux::hw::send(&drtioaux::Packet::SpiReadReply { succeeded: false, data: 0 }).unwrap() + }; + } + _ => warn!("received unexpected aux packet {:?}", p) } }