i2c: expose restart as syscall, add structure for I2C-over-DRTIO

This commit is contained in:
Sebastien Bourdeauducq 2017-06-19 23:44:51 +08:00
parent 268b7d8aaf
commit c86029bca2
5 changed files with 155 additions and 15 deletions

View File

@ -8,6 +8,11 @@ def i2c_start(busno: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated") raise NotImplementedError("syscall not simulated")
@syscall(flags={"nounwind", "nowrite"})
def i2c_restart(busno: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated")
@syscall(flags={"nounwind", "nowrite"}) @syscall(flags={"nounwind", "nowrite"})
def i2c_stop(busno: TInt32) -> TNone: def i2c_stop(busno: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated") raise NotImplementedError("syscall not simulated")

View File

@ -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!(drtio_get_fifo_space_req_count = ::rtio::drtio_dbg::get_fifo_space_req_count),
api!(i2c_start = ::nrt_bus::i2c::start), api!(i2c_start = ::nrt_bus::i2c::start),
api!(i2c_restart = ::nrt_bus::i2c::restart),
api!(i2c_stop = ::nrt_bus::i2c::stop), api!(i2c_stop = ::nrt_bus::i2c::stop),
api!(i2c_write = ::nrt_bus::i2c::write), api!(i2c_write = ::nrt_bus::i2c::write),
api!(i2c_read = ::nrt_bus::i2c::read), api!(i2c_read = ::nrt_bus::i2c::read),

View File

@ -4,21 +4,28 @@ pub mod i2c {
use kernel_proto::*; use kernel_proto::*;
pub extern fn start(busno: i32) { 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 { recv!(&I2cBasicReply { succeeded } => if !succeeded {
raise!("I2CError", "I2C bus could not be accessed"); raise!("I2CError", "I2C bus could not be accessed");
}); });
} }
pub extern fn stop(busno: i32) { pub extern fn stop(busno: i32) {
send(&I2cStopRequest { busno: busno as u8 }); send(&I2cStopRequest { busno: busno as u32 });
recv!(&I2cBasicReply { succeeded } => if !succeeded { recv!(&I2cBasicReply { succeeded } => if !succeeded {
raise!("I2CError", "I2C bus could not be accessed"); raise!("I2CError", "I2C bus could not be accessed");
}); });
} }
pub extern fn write(busno: i32, data: i32) -> bool { 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 } => { recv!(&I2cWriteReply { succeeded, ack } => {
if !succeeded { if !succeeded {
raise!("I2CError", "I2C bus could not be accessed"); raise!("I2CError", "I2C bus could not be accessed");
@ -28,7 +35,7 @@ pub mod i2c {
} }
pub extern fn read(busno: i32, ack: bool) -> i32 { 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 } => { recv!(&I2cReadReply { succeeded, data } => {
if !succeeded { if !succeeded {
raise!("I2CError", "I2C bus could not be accessed"); raise!("I2CError", "I2C bus could not be accessed");

View File

@ -80,11 +80,12 @@ pub enum Message<'a> {
CachePutRequest { key: &'a str, value: &'a [i32] }, CachePutRequest { key: &'a str, value: &'a [i32] },
CachePutReply { succeeded: bool }, CachePutReply { succeeded: bool },
I2cStartRequest { busno: u8 }, I2cStartRequest { busno: u32 },
I2cStopRequest { busno: u8 }, I2cRestartRequest { busno: u32 },
I2cWriteRequest { busno: u8, data: u8 }, I2cStopRequest { busno: u32 },
I2cWriteRequest { busno: u32, data: u8 },
I2cWriteReply { succeeded: bool, ack: bool }, I2cWriteReply { succeeded: bool, ack: bool },
I2cReadRequest { busno: u8, ack: bool }, I2cReadRequest { busno: u32, ack: bool },
I2cReadReply { succeeded: bool, data: u8 }, I2cReadReply { succeeded: bool, data: u8 },
I2cBasicReply { succeeded: bool }, I2cBasicReply { succeeded: bool },

View File

@ -1,10 +1,132 @@
use session::{kern_acknowledge, kern_send}; use session::{kern_acknowledge, kern_send};
use rtio_mgt; use rtio_mgt;
use board;
use kernel_proto as kern; use kernel_proto as kern;
use std::io; use std::io;
use sched::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<bool, ()> {
Err(())
}
pub fn read(_busno: u32, _ack: bool) -> Result<u8, ()> {
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<bool, ()> {
Err(())
}
pub fn read(_busno: u32, _ack: bool) -> Result<u8, ()> {
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<bool, ()> {
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<u8, ()> {
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<u32, ()> {
Err(())
}
}
#[cfg(not(has_drtio))]
mod drtio_spi { mod drtio_spi {
pub fn set_config(_busno: u32, _flags: u8, _write_div: u8, _read_div: u8) -> Result<(), ()> { pub fn set_config(_busno: u32, _flags: u8, _write_div: u8, _read_div: u8) -> Result<(), ()> {
Err(()) Err(())
@ -99,25 +221,29 @@ pub fn process_kern_hwreq(io: &Io, request: &kern::Message) -> io::Result<bool>
} }
&kern::I2cStartRequest { busno } => { &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_send(io, &kern::I2cBasicReply { succeeded: succeeded })
} }
&kern::I2cStopRequest { busno } => { &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_send(io, &kern::I2cBasicReply { succeeded: succeeded })
} }
&kern::I2cWriteRequest { busno, data } => { &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 }), Ok(ack) => kern_send(io, &kern::I2cWriteReply { succeeded: true, ack: ack }),
Err(_) => kern_send(io, &kern::I2cWriteReply { succeeded: false, ack: false }) Err(_) => kern_send(io, &kern::I2cWriteReply { succeeded: false, ack: false })
} }
} }
&kern::I2cReadRequest { busno, ack } => { &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 }), Ok(data) => kern_send(io, &kern::I2cReadReply { succeeded: true, data: data }),
Err(_) => kern_send(io, &kern::I2cReadReply { succeeded: false, data: 0xff }) Err(_) => kern_send(io, &kern::I2cReadReply { succeeded: false, data: 0xff })
} }
}, }
&kern::SpiSetConfigRequest { busno, flags, write_div, read_div } => { &kern::SpiSetConfigRequest { busno, flags, write_div, read_div } => {
let succeeded = spi::set_config(busno, flags, write_div, read_div).is_ok(); 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<bool>
Ok(data) => kern_send(io, &kern::SpiReadReply { succeeded: true, data: data }), Ok(data) => kern_send(io, &kern::SpiReadReply { succeeded: true, data: data }),
Err(_) => kern_send(io, &kern::SpiReadReply { succeeded: false, data: 0 }) Err(_) => kern_send(io, &kern::SpiReadReply { succeeded: false, data: 0 })
} }
}, }
_ => return Ok(false) _ => return Ok(false)
}.and(Ok(true)) }.and(Ok(true))