diff --git a/artiq/coredevice/i2c.py b/artiq/coredevice/i2c.py index e647cfd41..ce8ca33ea 100644 --- a/artiq/coredevice/i2c.py +++ b/artiq/coredevice/i2c.py @@ -8,6 +8,11 @@ def i2c_start(busno: TInt32) -> TNone: raise NotImplementedError("syscall not simulated") +@syscall(flags={"nounwind", "nowrite"}) +def i2c_restart(busno: TInt32) -> TNone: + raise NotImplementedError("syscall not simulated") + + @syscall(flags={"nounwind", "nowrite"}) def i2c_stop(busno: TInt32) -> TNone: raise NotImplementedError("syscall not simulated") diff --git a/artiq/firmware/ksupport/api.rs b/artiq/firmware/ksupport/api.rs index 792f92f52..60e11b80a 100644 --- a/artiq/firmware/ksupport/api.rs +++ b/artiq/firmware/ksupport/api.rs @@ -118,6 +118,7 @@ static mut API: &'static [(&'static str, *const ())] = &[ api!(drtio_get_fifo_space_req_count = ::rtio::drtio_dbg::get_fifo_space_req_count), api!(i2c_start = ::nrt_bus::i2c::start), + api!(i2c_restart = ::nrt_bus::i2c::restart), api!(i2c_stop = ::nrt_bus::i2c::stop), api!(i2c_write = ::nrt_bus::i2c::write), api!(i2c_read = ::nrt_bus::i2c::read), diff --git a/artiq/firmware/ksupport/nrt_bus.rs b/artiq/firmware/ksupport/nrt_bus.rs index fedb41a64..c847bcf82 100644 --- a/artiq/firmware/ksupport/nrt_bus.rs +++ b/artiq/firmware/ksupport/nrt_bus.rs @@ -4,21 +4,28 @@ pub mod i2c { use kernel_proto::*; pub extern fn start(busno: i32) { - send(&I2cStartRequest { busno: busno as u8 }); + send(&I2cStartRequest { busno: busno as u32 }); + recv!(&I2cBasicReply { succeeded } => if !succeeded { + raise!("I2CError", "I2C bus could not be accessed"); + }); + } + + pub extern fn restart(busno: i32) { + send(&I2cRestartRequest { busno: busno as u32 }); recv!(&I2cBasicReply { succeeded } => if !succeeded { raise!("I2CError", "I2C bus could not be accessed"); }); } pub extern fn stop(busno: i32) { - send(&I2cStopRequest { busno: busno as u8 }); + send(&I2cStopRequest { busno: busno as u32 }); recv!(&I2cBasicReply { succeeded } => if !succeeded { raise!("I2CError", "I2C bus could not be accessed"); }); } pub extern fn write(busno: i32, data: i32) -> bool { - send(&I2cWriteRequest { busno: busno as u8, data: data as u8 }); + send(&I2cWriteRequest { busno: busno as u32, data: data as u8 }); recv!(&I2cWriteReply { succeeded, ack } => { if !succeeded { raise!("I2CError", "I2C bus could not be accessed"); @@ -28,7 +35,7 @@ pub mod i2c { } pub extern fn read(busno: i32, ack: bool) -> i32 { - send(&I2cReadRequest { busno: busno as u8, ack: ack }); + send(&I2cReadRequest { busno: busno as u32, ack: ack }); recv!(&I2cReadReply { succeeded, data } => { if !succeeded { raise!("I2CError", "I2C bus could not be accessed"); diff --git a/artiq/firmware/libproto/kernel_proto.rs b/artiq/firmware/libproto/kernel_proto.rs index 809bbdc47..4d4d66241 100644 --- a/artiq/firmware/libproto/kernel_proto.rs +++ b/artiq/firmware/libproto/kernel_proto.rs @@ -80,11 +80,12 @@ pub enum Message<'a> { CachePutRequest { key: &'a str, value: &'a [i32] }, CachePutReply { succeeded: bool }, - I2cStartRequest { busno: u8 }, - I2cStopRequest { busno: u8 }, - I2cWriteRequest { busno: u8, data: u8 }, + I2cStartRequest { busno: u32 }, + I2cRestartRequest { busno: u32 }, + I2cStopRequest { busno: u32 }, + I2cWriteRequest { busno: u32, data: u8 }, I2cWriteReply { succeeded: bool, ack: bool }, - I2cReadRequest { busno: u8, ack: bool }, + I2cReadRequest { busno: u32, ack: bool }, I2cReadReply { succeeded: bool, data: u8 }, I2cBasicReply { succeeded: bool }, diff --git a/artiq/firmware/runtime/kern_hwreq.rs b/artiq/firmware/runtime/kern_hwreq.rs index 9312a0d12..8dcd1c33b 100644 --- a/artiq/firmware/runtime/kern_hwreq.rs +++ b/artiq/firmware/runtime/kern_hwreq.rs @@ -1,10 +1,132 @@ use session::{kern_acknowledge, kern_send}; use rtio_mgt; -use board; 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(()) + } + + pub fn restart(_busno: u32) -> Result<(), ()> { + Err(()) + } + + pub fn stop(_busno: u32) -> Result<(), ()> { + Err(()) + } + + pub fn write(_busno: u32, _data: u8) -> Result { + Err(()) + } + + pub fn read(_busno: u32, _ack: bool) -> Result { + Err(()) + } +} + +#[cfg(not(has_drtio))] +mod drtio_i2c { + pub fn start(_busno: u32) -> Result<(), ()> { + Err(()) + } + + pub fn restart(_busno: u32) -> Result<(), ()> { + Err(()) + } + + pub fn stop(_busno: u32) -> Result<(), ()> { + Err(()) + } + + pub fn write(_busno: u32, _data: u8) -> Result { + Err(()) + } + + pub fn read(_busno: u32, _ack: bool) -> Result { + Err(()) + } +} + +mod i2c { + use board; + use super::drtio_i2c; + + pub fn start(busno: u32) -> Result<(), ()> { + let drtio = busno >> 16; + let dev_busno = busno as u8; + if drtio == 0 { + board::i2c::start(dev_busno) + } else { + drtio_i2c::start(busno) + } + } + + pub fn restart(busno: u32) -> Result<(), ()> { + let drtio = busno >> 16; + let dev_busno = busno as u8; + if drtio == 0 { + board::i2c::restart(dev_busno) + } else { + drtio_i2c::restart(busno) + } + } + + pub fn stop(busno: u32) -> Result<(), ()> { + let drtio = busno >> 16; + let dev_busno = busno as u8; + if drtio == 0 { + board::i2c::stop(dev_busno) + } else { + drtio_i2c::stop(busno) + } + } + + pub fn write(busno: u32, data: u8) -> Result { + let drtio = busno >> 16; + let dev_busno = busno as u8; + if drtio == 0 { + board::i2c::write(dev_busno, data) + } else { + drtio_i2c::write(busno, data) + } + } + + pub fn read(busno: u32, ack: bool) -> Result { + let drtio = busno >> 16; + let dev_busno = busno as u8; + if drtio == 0 { + board::i2c::read(dev_busno, ack) + } else { + drtio_i2c::read(busno, ack) + } + } +} + +// TODO +#[cfg(has_drtio)] +mod drtio_spi { + pub fn set_config(_busno: u32, _flags: u8, _write_div: u8, _read_div: u8) -> Result<(), ()> { + Err(()) + } + + pub fn set_xfer(_busno: u32, _chip_select: u16, _write_length: u8, _read_length: u8) -> Result<(), ()> { + Err(()) + } + + pub fn write(_busno: u32, _data: u32) -> Result<(), ()> { + Err(()) + } + + pub fn read(_busno: u32) -> Result { + Err(()) + } +} + +#[cfg(not(has_drtio))] mod drtio_spi { pub fn set_config(_busno: u32, _flags: u8, _write_div: u8, _read_div: u8) -> Result<(), ()> { Err(()) @@ -99,25 +221,29 @@ pub fn process_kern_hwreq(io: &Io, request: &kern::Message) -> io::Result } &kern::I2cStartRequest { busno } => { - let succeeded = board::i2c::start(busno).is_ok(); + let succeeded = i2c::start(busno).is_ok(); + kern_send(io, &kern::I2cBasicReply { succeeded: succeeded }) + } + &kern::I2cRestartRequest { busno } => { + let succeeded = i2c::restart(busno).is_ok(); kern_send(io, &kern::I2cBasicReply { succeeded: succeeded }) } &kern::I2cStopRequest { busno } => { - let succeeded = board::i2c::stop(busno).is_ok(); + let succeeded = i2c::stop(busno).is_ok(); kern_send(io, &kern::I2cBasicReply { succeeded: succeeded }) } &kern::I2cWriteRequest { busno, data } => { - match board::i2c::write(busno, data) { + match i2c::write(busno, data) { Ok(ack) => kern_send(io, &kern::I2cWriteReply { succeeded: true, ack: ack }), Err(_) => kern_send(io, &kern::I2cWriteReply { succeeded: false, ack: false }) } } &kern::I2cReadRequest { busno, ack } => { - match board::i2c::read(busno, ack) { + match i2c::read(busno, ack) { Ok(data) => kern_send(io, &kern::I2cReadReply { succeeded: true, data: data }), Err(_) => kern_send(io, &kern::I2cReadReply { succeeded: false, data: 0xff }) } - }, + } &kern::SpiSetConfigRequest { busno, flags, write_div, read_div } => { let succeeded = spi::set_config(busno, flags, write_div, read_div).is_ok(); @@ -136,7 +262,7 @@ pub fn process_kern_hwreq(io: &Io, request: &kern::Message) -> io::Result Ok(data) => kern_send(io, &kern::SpiReadReply { succeeded: true, data: data }), Err(_) => kern_send(io, &kern::SpiReadReply { succeeded: false, data: 0 }) } - }, + } _ => return Ok(false) }.and(Ok(true))