drtio: initial firmware support for multi-link

This commit is contained in:
Sebastien Bourdeauducq 2017-07-18 00:40:21 +08:00
parent 94ee48860a
commit 9045b4cc19
11 changed files with 407 additions and 329 deletions

View File

@ -1,3 +1,9 @@
"""
DRTIO debugging functions.
Those syscalls are intended for ARTIQ developers only.
"""
from artiq.language.core import syscall from artiq.language.core import syscall
from artiq.language.types import TTuple, TInt32, TInt64, TNone from artiq.language.types import TTuple, TInt32, TInt64, TNone
@ -18,9 +24,9 @@ def drtio_get_fifo_space(channel: TInt32) -> TNone:
@syscall(flags={"nounwind", "nowrite"}) @syscall(flags={"nounwind", "nowrite"})
def drtio_get_packet_counts() -> TTuple([TInt32, TInt32]): def drtio_get_packet_counts(linkno: TInt32) -> TTuple([TInt32, TInt32]):
raise NotImplementedError("syscall not simulated") raise NotImplementedError("syscall not simulated")
@syscall(flags={"nounwind", "nowrite"}) @syscall(flags={"nounwind", "nowrite"})
def drtio_get_fifo_space_req_count() -> TInt32: def drtio_get_fifo_space_req_count(linkno: TInt32) -> TInt32:
raise NotImplementedError("syscall not simulated") raise NotImplementedError("syscall not simulated")

View File

@ -182,14 +182,14 @@ pub mod drtio_dbg {
#[repr(C)] #[repr(C)]
pub struct PacketCounts(i32, i32); pub struct PacketCounts(i32, i32);
pub extern fn get_packet_counts() -> PacketCounts { pub extern fn get_packet_counts(linkno: i32) -> PacketCounts {
send(&DrtioPacketCountRequest); send(&DrtioPacketCountRequest { linkno: linkno as u8 });
recv!(&DrtioPacketCountReply { tx_cnt, rx_cnt } recv!(&DrtioPacketCountReply { tx_cnt, rx_cnt }
=> PacketCounts(tx_cnt as i32, rx_cnt as i32)) => PacketCounts(tx_cnt as i32, rx_cnt as i32))
} }
pub extern fn get_fifo_space_req_count() -> i32 { pub extern fn get_fifo_space_req_count(linkno: i32) -> i32 {
send(&DrtioFifoSpaceReqCountRequest); send(&DrtioFifoSpaceReqCountRequest { linkno: linkno as u8 });
recv!(&DrtioFifoSpaceReqCountReply { cnt } recv!(&DrtioFifoSpaceReqCountReply { cnt }
=> cnt as i32) => cnt as i32)
} }

View File

@ -252,50 +252,49 @@ pub mod hw {
use super::*; use super::*;
use std::io::Cursor; use std::io::Cursor;
const AUX_TX_BASE: usize = board::mem::DRTIO_AUX_BASE; fn rx_has_error(linkno: u8) -> bool {
const AUX_TX_SIZE: usize = board::mem::DRTIO_AUX_SIZE/2; let linkno = linkno as usize;
const AUX_RX_BASE: usize = AUX_TX_BASE + AUX_TX_SIZE;
fn rx_has_error() -> bool {
unsafe { unsafe {
let error = board::csr::drtio::aux_rx_error_read() != 0; let error = (board::csr::DRTIO[linkno].aux_rx_error_read)() != 0;
if error { if error {
board::csr::drtio::aux_rx_error_write(1) (board::csr::DRTIO[linkno].aux_rx_error_write)(1)
} }
error error
} }
} }
struct RxBuffer(&'static [u8]); struct RxBuffer(u8, &'static [u8]);
impl Drop for RxBuffer { impl Drop for RxBuffer {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
board::csr::drtio::aux_rx_present_write(1); (board::csr::DRTIO[self.0 as usize].aux_rx_present_write)(1);
} }
} }
} }
fn rx_get_buffer() -> Option<RxBuffer> { fn rx_get_buffer(linkno: u8) -> Option<RxBuffer> {
let linkidx = linkno as usize;
unsafe { unsafe {
if board::csr::drtio::aux_rx_present_read() == 1 { if (board::csr::DRTIO[linkidx].aux_rx_present_read)() == 1 {
let length = board::csr::drtio::aux_rx_length_read(); let length = (board::csr::DRTIO[linkidx].aux_rx_length_read)();
let sl = slice::from_raw_parts(AUX_RX_BASE as *mut u8, length as usize); let base = board::mem::DRTIO_AUX[linkidx].base + board::mem::DRTIO_AUX[linkidx].size/2;
Some(RxBuffer(sl)) let sl = slice::from_raw_parts(base as *mut u8, length as usize);
Some(RxBuffer(linkno, sl))
} else { } else {
None None
} }
} }
} }
pub fn recv() -> io::Result<Option<Packet>> { pub fn recv_link(linkno: u8) -> io::Result<Option<Packet>> {
if rx_has_error() { if rx_has_error(linkno) {
return Err(io::Error::new(io::ErrorKind::Other, "gateware reported error")) return Err(io::Error::new(io::ErrorKind::Other, "gateware reported error"))
} }
let buffer = rx_get_buffer(); let buffer = rx_get_buffer(linkno);
match buffer { match buffer {
Some(rxb) => { Some(rxb) => {
let slice = rxb.0; let slice = rxb.1;
let mut reader = Cursor::new(slice); let mut reader = Cursor::new(slice);
let len = slice.len(); let len = slice.len();
@ -320,11 +319,11 @@ pub mod hw {
} }
} }
pub fn recv_timeout(timeout_ms: Option<u64>) -> io::Result<Packet> { pub fn recv_timeout_link(linkno: u8, timeout_ms: Option<u64>) -> io::Result<Packet> {
let timeout_ms = timeout_ms.unwrap_or(10); let timeout_ms = timeout_ms.unwrap_or(10);
let limit = board::clock::get_ms() + timeout_ms; let limit = board::clock::get_ms() + timeout_ms;
while board::clock::get_ms() < limit { while board::clock::get_ms() < limit {
match recv() { match recv_link(linkno) {
Ok(None) => (), Ok(None) => (),
Ok(Some(packet)) => return Ok(packet), Ok(Some(packet)) => return Ok(packet),
Err(e) => return Err(e) Err(e) => return Err(e)
@ -333,22 +332,26 @@ pub mod hw {
return Err(io::Error::new(io::ErrorKind::TimedOut, "timed out waiting for data")) return Err(io::Error::new(io::ErrorKind::TimedOut, "timed out waiting for data"))
} }
fn tx_get_buffer() -> &'static mut [u8] { fn tx_get_buffer(linkno: u8) -> &'static mut [u8] {
let linkno = linkno as usize;
unsafe { unsafe {
while board::csr::drtio::aux_tx_read() != 0 {} while (board::csr::DRTIO[linkno].aux_tx_read)() != 0 {}
slice::from_raw_parts_mut(AUX_TX_BASE as *mut u8, AUX_TX_SIZE) let base = board::mem::DRTIO_AUX[linkno].base;
let size = board::mem::DRTIO_AUX[linkno].size/2;
slice::from_raw_parts_mut(base as *mut u8, size)
} }
} }
fn tx_ack_buffer(length: u16) { fn tx_ack_buffer(linkno: u8, length: u16) {
let linkno = linkno as usize;
unsafe { unsafe {
board::csr::drtio::aux_tx_length_write(length); (board::csr::DRTIO[linkno].aux_tx_length_write)(length);
board::csr::drtio::aux_tx_write(1) (board::csr::DRTIO[linkno].aux_tx_write)(1)
} }
} }
pub fn send(packet: &Packet) -> io::Result<()> { pub fn send_link(linkno: u8, packet: &Packet) -> io::Result<()> {
let sl = tx_get_buffer(); let sl = tx_get_buffer(linkno);
let mut writer = Cursor::new(sl); let mut writer = Cursor::new(sl);
packet.write_to(&mut writer)?; packet.write_to(&mut writer)?;
@ -366,8 +369,31 @@ pub mod hw {
write_u32(&mut writer, crc)?; write_u32(&mut writer, crc)?;
len += 4; len += 4;
tx_ack_buffer(len as u16); tx_ack_buffer(linkno, len as u16);
Ok(()) Ok(())
} }
// TODO: routing
fn get_linkno(nodeno: u8) -> io::Result<u8> {
if nodeno == 0 || nodeno as usize > board::csr::DRTIO.len() {
return Err(io::Error::new(io::ErrorKind::NotFound, "invalid node number"))
}
Ok(nodeno - 1)
}
pub fn recv(nodeno: u8) -> io::Result<Option<Packet>> {
let linkno = get_linkno(nodeno)?;
recv_link(linkno)
}
pub fn recv_timeout(nodeno: u8, timeout_ms: Option<u64>) -> io::Result<Packet> {
let linkno = get_linkno(nodeno)?;
recv_timeout_link(linkno, timeout_ms)
}
pub fn send(nodeno: u8, packet: &Packet) -> io::Result<()> {
let linkno = get_linkno(nodeno)?;
send_link(linkno, packet)
}
} }

View File

@ -50,9 +50,9 @@ pub enum Message<'a> {
DrtioChannelStateReply { fifo_space: u16, last_timestamp: u64 }, DrtioChannelStateReply { fifo_space: u16, last_timestamp: u64 },
DrtioResetChannelStateRequest { channel: u32 }, DrtioResetChannelStateRequest { channel: u32 },
DrtioGetFifoSpaceRequest { channel: u32 }, DrtioGetFifoSpaceRequest { channel: u32 },
DrtioPacketCountRequest, DrtioPacketCountRequest { linkno: u8 },
DrtioPacketCountReply { tx_cnt: u32, rx_cnt: u32 }, DrtioPacketCountReply { tx_cnt: u32, rx_cnt: u32 },
DrtioFifoSpaceReqCountRequest, DrtioFifoSpaceReqCountRequest { linkno: u8 },
DrtioFifoSpaceReqCountReply { cnt: u32 }, DrtioFifoSpaceReqCountReply { cnt: u32 },
RunFinished, RunFinished,

View File

@ -8,8 +8,8 @@ use sched::Io;
mod drtio_i2c { mod drtio_i2c {
use drtioaux; use drtioaux;
fn basic_reply() -> Result<(), ()> { fn basic_reply(nodeno: u8) -> Result<(), ()> {
match drtioaux::hw::recv_timeout(None) { match drtioaux::hw::recv_timeout(nodeno, None) {
Ok(drtioaux::Packet::I2cBasicReply { succeeded }) => { Ok(drtioaux::Packet::I2cBasicReply { succeeded }) => {
if succeeded { Ok(()) } else { Err(()) } if succeeded { Ok(()) } else { Err(()) }
} }
@ -24,31 +24,39 @@ mod drtio_i2c {
} }
} }
pub fn start(busno: u32) -> Result<(), ()> { pub fn start(nodeno: u8, busno: u8) -> Result<(), ()> {
let request = drtioaux::Packet::I2cStartRequest { busno: busno as u8 }; let request = drtioaux::Packet::I2cStartRequest { busno: busno };
drtioaux::hw::send(&request).unwrap(); if drtioaux::hw::send(nodeno, &request).is_err() {
basic_reply() return Err(())
}
basic_reply(nodeno)
} }
pub fn restart(busno: u32) -> Result<(), ()> { pub fn restart(nodeno: u8, busno: u8) -> Result<(), ()> {
let request = drtioaux::Packet::I2cRestartRequest { busno: busno as u8 }; let request = drtioaux::Packet::I2cRestartRequest { busno: busno };
drtioaux::hw::send(&request).unwrap(); if drtioaux::hw::send(nodeno, &request).is_err() {
basic_reply() return Err(())
}
basic_reply(nodeno)
} }
pub fn stop(busno: u32) -> Result<(), ()> { pub fn stop(nodeno: u8, busno: u8) -> Result<(), ()> {
let request = drtioaux::Packet::I2cStopRequest { busno: busno as u8 }; let request = drtioaux::Packet::I2cStopRequest { busno: busno };
drtioaux::hw::send(&request).unwrap(); if drtioaux::hw::send(nodeno, &request).is_err() {
basic_reply() return Err(())
}
basic_reply(nodeno)
} }
pub fn write(busno: u32, data: u8) -> Result<bool, ()> { pub fn write(nodeno: u8, busno: u8, data: u8) -> Result<bool, ()> {
let request = drtioaux::Packet::I2cWriteRequest { let request = drtioaux::Packet::I2cWriteRequest {
busno: busno as u8, busno: busno,
data: data data: data
}; };
drtioaux::hw::send(&request).unwrap(); if drtioaux::hw::send(nodeno, &request).is_err() {
match drtioaux::hw::recv_timeout(None) { return Err(())
}
match drtioaux::hw::recv_timeout(nodeno, None) {
Ok(drtioaux::Packet::I2cWriteReply { succeeded, ack }) => { Ok(drtioaux::Packet::I2cWriteReply { succeeded, ack }) => {
if succeeded { Ok(ack) } else { Err(()) } if succeeded { Ok(ack) } else { Err(()) }
} }
@ -63,13 +71,15 @@ mod drtio_i2c {
} }
} }
pub fn read(busno: u32, ack: bool) -> Result<u8, ()> { pub fn read(nodeno: u8, busno: u8, ack: bool) -> Result<u8, ()> {
let request = drtioaux::Packet::I2cReadRequest { let request = drtioaux::Packet::I2cReadRequest {
busno: busno as u8, busno: busno,
ack: ack ack: ack
}; };
drtioaux::hw::send(&request).unwrap(); if drtioaux::hw::send(nodeno, &request).is_err() {
match drtioaux::hw::recv_timeout(None) { return Err(())
}
match drtioaux::hw::recv_timeout(nodeno, None) {
Ok(drtioaux::Packet::I2cReadReply { succeeded, data }) => { Ok(drtioaux::Packet::I2cReadReply { succeeded, data }) => {
if succeeded { Ok(data) } else { Err(()) } if succeeded { Ok(data) } else { Err(()) }
} }
@ -87,23 +97,23 @@ mod drtio_i2c {
#[cfg(not(has_drtio))] #[cfg(not(has_drtio))]
mod drtio_i2c { mod drtio_i2c {
pub fn start(_busno: u32) -> Result<(), ()> { pub fn start(_nodeno: u8, _busno: u8) -> Result<(), ()> {
Err(()) Err(())
} }
pub fn restart(_busno: u32) -> Result<(), ()> { pub fn restart(_nodeno: u8, _busno: u8) -> Result<(), ()> {
Err(()) Err(())
} }
pub fn stop(_busno: u32) -> Result<(), ()> { pub fn stop(_nodeno: u8, _busno: u8) -> Result<(), ()> {
Err(()) Err(())
} }
pub fn write(_busno: u32, _data: u8) -> Result<bool, ()> { pub fn write(_nodeno: u8, _busno: u8, _data: u8) -> Result<bool, ()> {
Err(()) Err(())
} }
pub fn read(_busno: u32, _ack: bool) -> Result<u8, ()> { pub fn read(_nodeno: u8, _busno: u8, _ack: bool) -> Result<u8, ()> {
Err(()) Err(())
} }
} }
@ -113,52 +123,52 @@ mod i2c {
use super::drtio_i2c; use super::drtio_i2c;
pub fn start(busno: u32) -> Result<(), ()> { pub fn start(busno: u32) -> Result<(), ()> {
let drtio = busno >> 16; let nodeno = (busno >> 16) as u8;
let dev_busno = busno as u8; let node_busno = busno as u8;
if drtio == 0 { if nodeno == 0 {
board::i2c::start(dev_busno) board::i2c::start(node_busno)
} else { } else {
drtio_i2c::start(busno) drtio_i2c::start(nodeno, node_busno)
} }
} }
pub fn restart(busno: u32) -> Result<(), ()> { pub fn restart(busno: u32) -> Result<(), ()> {
let drtio = busno >> 16; let nodeno = (busno >> 16) as u8;
let dev_busno = busno as u8; let node_busno = busno as u8;
if drtio == 0 { if nodeno == 0 {
board::i2c::restart(dev_busno) board::i2c::restart(node_busno)
} else { } else {
drtio_i2c::restart(busno) drtio_i2c::restart(nodeno, node_busno)
} }
} }
pub fn stop(busno: u32) -> Result<(), ()> { pub fn stop(busno: u32) -> Result<(), ()> {
let drtio = busno >> 16; let nodeno = (busno >> 16) as u8;
let dev_busno = busno as u8; let node_busno = busno as u8;
if drtio == 0 { if nodeno == 0 {
board::i2c::stop(dev_busno) board::i2c::stop(node_busno)
} else { } else {
drtio_i2c::stop(busno) drtio_i2c::stop(nodeno, node_busno)
} }
} }
pub fn write(busno: u32, data: u8) -> Result<bool, ()> { pub fn write(busno: u32, data: u8) -> Result<bool, ()> {
let drtio = busno >> 16; let nodeno = (busno >> 16 )as u8;
let dev_busno = busno as u8; let node_busno = busno as u8;
if drtio == 0 { if nodeno == 0 {
board::i2c::write(dev_busno, data) board::i2c::write(node_busno, data)
} else { } else {
drtio_i2c::write(busno, data) drtio_i2c::write(nodeno, node_busno, data)
} }
} }
pub fn read(busno: u32, ack: bool) -> Result<u8, ()> { pub fn read(busno: u32, ack: bool) -> Result<u8, ()> {
let drtio = busno >> 16; let nodeno = (busno >> 16) as u8;
let dev_busno = busno as u8; let node_busno = busno as u8;
if drtio == 0 { if nodeno == 0 {
board::i2c::read(dev_busno, ack) board::i2c::read(node_busno, ack)
} else { } else {
drtio_i2c::read(busno, ack) drtio_i2c::read(nodeno, node_busno, ack)
} }
} }
} }
@ -167,8 +177,8 @@ mod i2c {
mod drtio_spi { mod drtio_spi {
use drtioaux; use drtioaux;
fn basic_reply() -> Result<(), ()> { fn basic_reply(nodeno: u8) -> Result<(), ()> {
match drtioaux::hw::recv_timeout(None) { match drtioaux::hw::recv_timeout(nodeno, None) {
Ok(drtioaux::Packet::SpiBasicReply { succeeded }) => { Ok(drtioaux::Packet::SpiBasicReply { succeeded }) => {
if succeeded { Ok(()) } else { Err(()) } if succeeded { Ok(()) } else { Err(()) }
} }
@ -183,41 +193,49 @@ mod drtio_spi {
} }
} }
pub fn set_config(busno: u32, flags: u8, write_div: u8, read_div: u8) -> Result<(), ()> { pub fn set_config(nodeno: u8, busno: u8, flags: u8, write_div: u8, read_div: u8) -> Result<(), ()> {
let request = drtioaux::Packet::SpiSetConfigRequest { let request = drtioaux::Packet::SpiSetConfigRequest {
busno: busno as u8, busno: busno,
flags: flags, flags: flags,
write_div: write_div, write_div: write_div,
read_div: read_div read_div: read_div
}; };
drtioaux::hw::send(&request).unwrap(); if drtioaux::hw::send(nodeno, &request).is_err() {
basic_reply() return Err(())
}
basic_reply(nodeno)
} }
pub fn set_xfer(busno: u32, chip_select: u16, write_length: u8, read_length: u8) -> Result<(), ()> { pub fn set_xfer(nodeno: u8, busno: u8, chip_select: u16, write_length: u8, read_length: u8) -> Result<(), ()> {
let request = drtioaux::Packet::SpiSetXferRequest { let request = drtioaux::Packet::SpiSetXferRequest {
busno: busno as u8, busno: busno,
chip_select: chip_select, chip_select: chip_select,
write_length: write_length, write_length: write_length,
read_length: read_length read_length: read_length
}; };
drtioaux::hw::send(&request).unwrap(); if drtioaux::hw::send(nodeno, &request).is_err() {
basic_reply() return Err(())
}
basic_reply(nodeno)
} }
pub fn write(busno: u32, data: u32) -> Result<(), ()> { pub fn write(nodeno: u8, busno: u8, data: u32) -> Result<(), ()> {
let request = drtioaux::Packet::SpiWriteRequest { let request = drtioaux::Packet::SpiWriteRequest {
busno: busno as u8, busno: busno,
data: data data: data
}; };
drtioaux::hw::send(&request).unwrap(); if drtioaux::hw::send(nodeno, &request).is_err() {
basic_reply() return Err(())
}
basic_reply(nodeno)
} }
pub fn read(busno: u32) -> Result<u32, ()> { pub fn read(nodeno: u8, busno: u8) -> Result<u32, ()> {
let request = drtioaux::Packet::SpiReadRequest { busno: busno as u8 }; let request = drtioaux::Packet::SpiReadRequest { busno: busno };
drtioaux::hw::send(&request).unwrap(); if drtioaux::hw::send(nodeno, &request).is_err() {
match drtioaux::hw::recv_timeout(None) { return Err(())
}
match drtioaux::hw::recv_timeout(nodeno, None) {
Ok(drtioaux::Packet::SpiReadReply { succeeded, data }) => { Ok(drtioaux::Packet::SpiReadReply { succeeded, data }) => {
if succeeded { Ok(data) } else { Err(()) } if succeeded { Ok(data) } else { Err(()) }
} }
@ -235,19 +253,19 @@ mod drtio_spi {
#[cfg(not(has_drtio))] #[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(_nodeno: u8, _busno: u8, _flags: u8, _write_div: u8, _read_div: u8) -> Result<(), ()> {
Err(()) Err(())
} }
pub fn set_xfer(_busno: u32, _chip_select: u16, _write_length: u8, _read_length: u8) -> Result<(), ()> { pub fn set_xfer(_nodeno: u8, _busno: u8, _chip_select: u16, _write_length: u8, _read_length: u8) -> Result<(), ()> {
Err(()) Err(())
} }
pub fn write(_busno: u32, _data: u32) -> Result<(), ()> { pub fn write(_nodeno: u8, _busno: u8, _data: u32) -> Result<(), ()> {
Err(()) Err(())
} }
pub fn read(_busno: u32) -> Result<u32, ()> { pub fn read(_nodeno: u8, _busno: u8) -> Result<u32, ()> {
Err(()) Err(())
} }
} }
@ -257,42 +275,42 @@ mod spi {
use super::drtio_spi; use super::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<(), ()> {
let drtio = busno >> 16; let nodeno = (busno >> 16) as u8;
let dev_busno = busno as u8; let node_busno = busno as u8;
if drtio == 0 { if nodeno == 0 {
board::spi::set_config(dev_busno, flags, write_div, read_div) board::spi::set_config(node_busno, flags, write_div, read_div)
} else { } else {
drtio_spi::set_config(busno, flags, write_div, read_div) drtio_spi::set_config(nodeno, node_busno, flags, write_div, read_div)
} }
} }
pub fn set_xfer(busno: u32, chip_select: u16, write_length: u8, read_length: u8) -> Result<(), ()> { pub fn set_xfer(busno: u32, chip_select: u16, write_length: u8, read_length: u8) -> Result<(), ()> {
let drtio = busno >> 16; let nodeno = (busno >> 16) as u8;
let dev_busno = busno as u8; let node_busno = busno as u8;
if drtio == 0 { if nodeno == 0 {
board::spi::set_xfer(dev_busno, chip_select, write_length, read_length) board::spi::set_xfer(node_busno, chip_select, write_length, read_length)
} else { } else {
drtio_spi::set_xfer(busno, chip_select, write_length, read_length) drtio_spi::set_xfer(nodeno, node_busno, chip_select, write_length, read_length)
} }
} }
pub fn write(busno: u32, data: u32) -> Result<(), ()> { pub fn write(busno: u32, data: u32) -> Result<(), ()> {
let drtio = busno >> 16; let nodeno = (busno >> 16) as u8;
let dev_busno = busno as u8; let node_busno = busno as u8;
if drtio == 0 { if nodeno == 0 {
board::spi::write(dev_busno, data) board::spi::write(node_busno, data)
} else { } else {
drtio_spi::write(busno, data) drtio_spi::write(nodeno, node_busno, data)
} }
} }
pub fn read(busno: u32) -> Result<u32, ()> { pub fn read(busno: u32) -> Result<u32, ()> {
let drtio = busno >> 16; let nodeno = (busno >> 16) as u8;
let dev_busno = busno as u8; let node_busno = busno as u8;
if drtio == 0 { if nodeno == 0 {
board::spi::read(dev_busno) board::spi::read(node_busno)
} else { } else {
drtio_spi::read(busno) drtio_spi::read(nodeno, node_busno)
} }
} }
} }
@ -318,12 +336,12 @@ pub fn process_kern_hwreq(io: &Io, request: &kern::Message) -> io::Result<bool>
rtio_mgt::drtio_dbg::get_fifo_space(channel); rtio_mgt::drtio_dbg::get_fifo_space(channel);
kern_acknowledge() kern_acknowledge()
} }
&kern::DrtioPacketCountRequest => { &kern::DrtioPacketCountRequest { linkno } => {
let (tx_cnt, rx_cnt) = rtio_mgt::drtio_dbg::get_packet_counts(); let (tx_cnt, rx_cnt) = rtio_mgt::drtio_dbg::get_packet_counts(linkno);
kern_send(io, &kern::DrtioPacketCountReply { tx_cnt: tx_cnt, rx_cnt: rx_cnt }) kern_send(io, &kern::DrtioPacketCountReply { tx_cnt: tx_cnt, rx_cnt: rx_cnt })
} }
&kern::DrtioFifoSpaceReqCountRequest => { &kern::DrtioFifoSpaceReqCountRequest { linkno } => {
let cnt = rtio_mgt::drtio_dbg::get_fifo_space_req_count(); let cnt = rtio_mgt::drtio_dbg::get_fifo_space_req_count(linkno);
kern_send(io, &kern::DrtioFifoSpaceReqCountReply { cnt: cnt }) kern_send(io, &kern::DrtioFifoSpaceReqCountReply { cnt: cnt })
} }

View File

@ -6,8 +6,6 @@ use sched::{TcpListener, TcpStream};
use board::{clock, csr}; use board::{clock, csr};
#[cfg(has_drtio)] #[cfg(has_drtio)]
use drtioaux; use drtioaux;
#[cfg(has_drtio)]
use rtio_mgt;
use moninj_proto::*; use moninj_proto::*;
@ -35,32 +33,36 @@ fn read_probe_local(channel: u16, probe: u8) -> u32 {
} }
#[cfg(has_drtio)] #[cfg(has_drtio)]
fn read_probe_drtio(channel: u16, probe: u8) -> u32 { fn read_probe_drtio(nodeno: u8, channel: u16, probe: u8) -> u32 {
if rtio_mgt::drtio::link_is_running() {
let request = drtioaux::Packet::MonitorRequest { channel: channel, probe: probe }; let request = drtioaux::Packet::MonitorRequest { channel: channel, probe: probe };
drtioaux::hw::send(&request).unwrap(); match drtioaux::hw::send(nodeno, &request) {
match drtioaux::hw::recv_timeout(None) { Ok(_) => (),
Err(e) => {
error!("aux packet error ({})", e);
return 0;
}
}
match drtioaux::hw::recv_timeout(nodeno, None) {
Ok(drtioaux::Packet::MonitorReply { value }) => return value, Ok(drtioaux::Packet::MonitorReply { value }) => return value,
Ok(_) => error!("received unexpected aux packet"), Ok(_) => error!("received unexpected aux packet"),
Err(e) => error!("aux packet error ({})", e) Err(e) => error!("aux packet error ({})", e)
} }
0 0
} else {
0
}
} }
fn read_probe(channel: u32, probe: u8) -> u32 { fn read_probe(channel: u32, probe: u8) -> u32 {
let nodeno = (channel >> 16) as u8;
let node_channel = channel as u16;
#[cfg(has_rtio_moninj)] #[cfg(has_rtio_moninj)]
{ {
if channel & 0xff0000 == 0 { if nodeno == 0 {
return read_probe_local(channel as u16, probe) return read_probe_local(node_channel, probe)
} }
} }
#[cfg(has_drtio)] #[cfg(has_drtio)]
{ {
if channel & 0xff0000 != 0 { if nodeno != 0 {
return read_probe_drtio(channel as u16, probe) return read_probe_drtio(nodeno, node_channel, probe)
} }
} }
error!("read_probe: unrecognized channel number {}", channel); error!("read_probe: unrecognized channel number {}", channel);
@ -77,29 +79,32 @@ fn inject_local(channel: u16, overrd: u8, value: u8) {
} }
#[cfg(has_drtio)] #[cfg(has_drtio)]
fn inject_drtio(channel: u16, overrd: u8, value: u8) { fn inject_drtio(nodeno: u8, channel: u16, overrd: u8, value: u8) {
if rtio_mgt::drtio::link_is_running() {
let request = drtioaux::Packet::InjectionRequest { let request = drtioaux::Packet::InjectionRequest {
channel: channel, channel: channel,
overrd: overrd, overrd: overrd,
value: value value: value
}; };
drtioaux::hw::send(&request).unwrap(); match drtioaux::hw::send(nodeno, &request) {
Ok(_) => (),
Err(e) => error!("aux packet error ({})", e)
} }
} }
fn inject(channel: u32, overrd: u8, value: u8) { fn inject(channel: u32, overrd: u8, value: u8) {
let nodeno = (channel >> 16) as u8;
let node_channel = channel as u16;
#[cfg(has_rtio_moninj)] #[cfg(has_rtio_moninj)]
{ {
if channel & 0xff0000 == 0 { if nodeno == 0 {
inject_local(channel as u16, overrd, value); inject_local(node_channel, overrd, value);
return return
} }
} }
#[cfg(has_drtio)] #[cfg(has_drtio)]
{ {
if channel & 0xff0000 != 0 { if nodeno != 0 {
inject_drtio(channel as u16, overrd, value); inject_drtio(nodeno, node_channel, overrd, value);
return return
} }
} }
@ -116,35 +121,39 @@ fn read_injection_status_local(channel: u16, overrd: u8) -> u8 {
} }
#[cfg(has_drtio)] #[cfg(has_drtio)]
fn read_injection_status_drtio(channel: u16, overrd: u8) -> u8 { fn read_injection_status_drtio(nodeno: u8, channel: u16, overrd: u8) -> u8 {
if rtio_mgt::drtio::link_is_running() {
let request = drtioaux::Packet::InjectionStatusRequest { let request = drtioaux::Packet::InjectionStatusRequest {
channel: channel, channel: channel,
overrd: overrd overrd: overrd
}; };
drtioaux::hw::send(&request).unwrap(); match drtioaux::hw::send(nodeno, &request) {
match drtioaux::hw::recv_timeout(None) { Ok(_) => (),
Err(e) => {
error!("aux packet error ({})", e);
return 0;
}
}
match drtioaux::hw::recv_timeout(nodeno, None) {
Ok(drtioaux::Packet::InjectionStatusReply { value }) => return value, Ok(drtioaux::Packet::InjectionStatusReply { value }) => return value,
Ok(_) => error!("received unexpected aux packet"), Ok(_) => error!("received unexpected aux packet"),
Err(e) => error!("aux packet error ({})", e) Err(e) => error!("aux packet error ({})", e)
} }
0 0
} else {
0
}
} }
fn read_injection_status(channel: u32, probe: u8) -> u8 { fn read_injection_status(channel: u32, probe: u8) -> u8 {
let nodeno = (channel >> 16) as u8;
let node_channel = channel as u16;
#[cfg(has_rtio_moninj)] #[cfg(has_rtio_moninj)]
{ {
if channel & 0xff0000 == 0 { if nodeno == 0 {
return read_injection_status_local(channel as u16, probe) return read_injection_status_local(node_channel, probe)
} }
} }
#[cfg(has_drtio)] #[cfg(has_drtio)]
{ {
if channel & 0xff0000 != 0 { if nodeno != 0 {
return read_injection_status_drtio(channel as u16, probe) return read_injection_status_drtio(nodeno, node_channel, probe)
} }
} }
error!("read_injection_status: unrecognized channel number {}", channel); error!("read_injection_status: unrecognized channel number {}", channel);

View File

@ -43,80 +43,70 @@ pub mod drtio {
pub fn startup(io: &Io) { pub fn startup(io: &Io) {
io.spawn(4096, link_thread); io.spawn(4096, link_thread);
io.spawn(4096, local_error_thread);
io.spawn(4096, aux_error_thread);
} }
static mut LINK_RUNNING: bool = false; fn link_rx_up(linkno: u8) -> bool {
let linkno = linkno as usize;
fn link_set_running(running: bool) {
unsafe { unsafe {
LINK_RUNNING = running (csr::DRTIO[linkno].link_status_read)() == 1
} }
} }
pub fn link_is_running() -> bool { fn reset_phy(linkno: u8) {
let linkno = linkno as usize;
unsafe { unsafe {
LINK_RUNNING (csr::DRTIO[linkno].reset_phy_write)(1);
while (csr::DRTIO[linkno].o_wait_read)() == 1 {}
} }
} }
fn link_is_up() -> bool { fn sync_tsc(linkno: u8) {
let linkno = linkno as usize;
unsafe { unsafe {
csr::drtio::link_status_read() == 1 (csr::DRTIO[linkno].set_time_write)(1);
while (csr::DRTIO[linkno].set_time_read)() == 1 {}
} }
} }
fn reset_phy() { fn init_link(linkno: u8) {
let linkidx = linkno as usize;
unsafe { unsafe {
csr::drtio::reset_phy_write(1); (csr::DRTIO[linkidx].reset_write)(1);
while csr::drtio::o_wait_read() == 1 {} while (csr::DRTIO[linkidx].o_wait_read)() == 1 {}
} }
} // TODO: determine actual number of remote FIFOs
for channel in 0..16 {
fn sync_tsc() {
unsafe { unsafe {
csr::drtio::set_time_write(1); (csr::DRTIO[linkidx].chan_sel_override_write)(channel);
while csr::drtio::set_time_read() == 1 {} (csr::DRTIO[linkidx].chan_sel_override_en_write)(1);
(csr::DRTIO[linkidx].o_reset_channel_status_write)(1);
(csr::DRTIO[linkidx].o_get_fifo_space_write)(1);
while (csr::DRTIO[linkidx].o_wait_read)() == 1 {}
info!("[LINK#{}] FIFO space on channel {} is {}",
linkno, channel, (csr::DRTIO[linkidx].o_dbg_fifo_space_read)());
(csr::DRTIO[linkidx].chan_sel_override_en_write)(0);
} }
} }
fn init_channel(channel: u16) {
unsafe {
csr::drtio::chan_sel_override_write(channel);
csr::drtio::chan_sel_override_en_write(1);
csr::drtio::o_reset_channel_status_write(1);
csr::drtio::o_get_fifo_space_write(1);
while csr::drtio::o_wait_read() == 1 {}
info!("FIFO space on channel {} is {}", channel, csr::drtio::o_dbg_fifo_space_read());
csr::drtio::chan_sel_override_en_write(0);
}
} }
pub fn init() { pub fn init() {
if link_is_running() { for linkno in 0..csr::DRTIO.len() {
unsafe { init_link(linkno as u8);
csr::drtio::reset_write(1);
while csr::drtio::o_wait_read() == 1 {}
}
for channel in 0..16 {
init_channel(channel);
}
} }
} }
fn ping_remote(io: &Io) -> u32 { fn ping_remote(linkno: u8, io: &Io) -> u32 {
let mut count = 0; let mut count = 0;
loop { loop {
if !link_is_up() { if !link_rx_up(linkno) {
return 0 return 0
} }
count += 1; count += 1;
drtioaux::hw::send(&drtioaux::Packet::EchoRequest).unwrap(); drtioaux::hw::send_link(linkno, &drtioaux::Packet::EchoRequest).unwrap();
io.sleep(100).unwrap(); io.sleep(100).unwrap();
let pr = drtioaux::hw::recv(); let pr = drtioaux::hw::recv_link(linkno);
match pr { match pr {
Ok(Some(drtioaux::Packet::EchoReply)) => return count, Ok(Some(drtioaux::Packet::EchoReply)) => return count,
_ => {} _ => {}
@ -124,59 +114,72 @@ pub mod drtio {
} }
} }
pub fn link_thread(io: Io) { fn process_local_errors(linkno: u8) {
loop { let errors;
io.until(link_is_up).unwrap(); let linkidx = linkno as usize;
info!("link RX is up, pinging");
let ping_count = ping_remote(&io);
if ping_count > 0 {
info!("remote replied after {} packets", ping_count);
link_set_running(true);
init(); // clear all FIFOs first
reset_phy();
sync_tsc();
info!("link initialization completed");
}
io.until(|| !link_is_up()).unwrap();
link_set_running(false);
info!("link is down");
}
}
pub fn local_error_thread(io: Io) {
loop {
unsafe { unsafe {
io.until(|| csr::drtio::protocol_error_read() != 0).unwrap(); errors = (csr::DRTIO[linkidx].protocol_error_read)();
let errors = csr::drtio::protocol_error_read(); (csr::DRTIO[linkidx].protocol_error_write)(errors);
}
if errors != 0 {
error!("[LINK#{}] found error(s)", linkno);
if errors & 1 != 0 { if errors & 1 != 0 {
error!("received packet of an unknown type"); error!("[LINK#{}] received packet of an unknown type", linkno);
} }
if errors & 2 != 0 { if errors & 2 != 0 {
error!("received truncated packet"); error!("[LINK#{}] received truncated packet", linkno);
} }
if errors & 4 != 0 { if errors & 4 != 0 {
error!("timeout attempting to get remote FIFO space"); error!("[LINK#{}] timeout attempting to get remote FIFO space", linkno);
}
csr::drtio::protocol_error_write(errors);
} }
} }
} }
pub fn aux_error_thread(io: Io) { fn process_aux_errors(linkno: u8) {
loop { drtioaux::hw::send_link(linkno, &drtioaux::Packet::RtioErrorRequest).unwrap();
io.sleep(200).unwrap(); match drtioaux::hw::recv_timeout_link(linkno, None) {
if link_is_running() {
drtioaux::hw::send(&drtioaux::Packet::RtioErrorRequest).unwrap();
match drtioaux::hw::recv_timeout(None) {
Ok(drtioaux::Packet::RtioNoErrorReply) => (), Ok(drtioaux::Packet::RtioNoErrorReply) => (),
Ok(drtioaux::Packet::RtioErrorCollisionReply) => error!("RTIO collision (in satellite)"), Ok(drtioaux::Packet::RtioErrorCollisionReply) =>
Ok(drtioaux::Packet::RtioErrorBusyReply) => error!("RTIO busy (in satellite)"), error!("[LINK#{}] RTIO collision", linkno),
Ok(_) => error!("received unexpected aux packet"), Ok(drtioaux::Packet::RtioErrorBusyReply) =>
Err(e) => error!("aux packet error ({})", e) error!("[LINK#{}] RTIO busy", linkno),
Ok(_) => error!("[LINK#{}] received unexpected aux packet", linkno),
Err(e) => error!("[LINK#{}] aux packet error ({})", linkno, e)
} }
} }
pub fn link_thread(io: Io) {
let mut link_up = vec![false; csr::DRTIO.len()];
loop {
for linkno in 0..csr::DRTIO.len() {
let linkno = linkno as u8;
if !link_up[linkno as usize] {
if link_rx_up(linkno) {
info!("[LINK#{}] link RX became up, pinging", linkno);
let ping_count = ping_remote(linkno, &io);
if ping_count > 0 {
info!("[LINK#{}] remote replied after {} packets", linkno, ping_count);
init_link(linkno); // clear all FIFOs first
reset_phy(linkno);
sync_tsc(linkno);
info!("[LINK#{}] link initialization completed", linkno);
link_up[linkno as usize] = true;
} else {
info!("[LINK#{}] ping failed", linkno);
}
} else {
if link_rx_up(linkno) {
process_local_errors(linkno);
process_aux_errors(linkno);
} else {
info!("[LINK#{}] link is down", linkno);
link_up[linkno as usize] = false;
}
}
}
}
io.sleep(200).unwrap();
} }
} }
} }
@ -248,45 +251,55 @@ pub fn init_core() {
pub mod drtio_dbg { pub mod drtio_dbg {
use board::csr; use board::csr;
// TODO: routing
pub fn get_channel_state(channel: u32) -> (u16, u64) { pub fn get_channel_state(channel: u32) -> (u16, u64) {
let linkno = ((channel >> 16) - 1) as usize;
let node_channel = channel as u16;
unsafe { unsafe {
csr::drtio::chan_sel_override_write(channel as u16); (csr::DRTIO[linkno].chan_sel_override_write)(node_channel as u16);
csr::drtio::chan_sel_override_en_write(1); (csr::DRTIO[linkno].chan_sel_override_en_write)(1);
let fifo_space = csr::drtio::o_dbg_fifo_space_read(); let fifo_space = (csr::DRTIO[linkno].o_dbg_fifo_space_read)();
let last_timestamp = csr::drtio::o_dbg_last_timestamp_read(); let last_timestamp = (csr::DRTIO[linkno].o_dbg_last_timestamp_read)();
csr::drtio::chan_sel_override_en_write(0); (csr::DRTIO[linkno].chan_sel_override_en_write)(0);
(fifo_space, last_timestamp) (fifo_space, last_timestamp)
} }
} }
pub fn reset_channel_state(channel: u32) { pub fn reset_channel_state(channel: u32) {
let linkno = ((channel >> 16) - 1) as usize;
let node_channel = channel as u16;
unsafe { unsafe {
csr::drtio::chan_sel_override_write(channel as u16); (csr::DRTIO[linkno].chan_sel_override_write)(node_channel);
csr::drtio::chan_sel_override_en_write(1); (csr::DRTIO[linkno].chan_sel_override_en_write)(1);
csr::drtio::o_reset_channel_status_write(1); (csr::DRTIO[linkno].o_reset_channel_status_write)(1);
csr::drtio::chan_sel_override_en_write(0); (csr::DRTIO[linkno].chan_sel_override_en_write)(0);
} }
} }
pub fn get_fifo_space(channel: u32) { pub fn get_fifo_space(channel: u32) {
let linkno = ((channel >> 16) - 1) as usize;
let node_channel = channel as u16;
unsafe { unsafe {
csr::drtio::chan_sel_override_write(channel as u16); (csr::DRTIO[linkno].chan_sel_override_write)(node_channel);
csr::drtio::chan_sel_override_en_write(1); (csr::DRTIO[linkno].chan_sel_override_en_write)(1);
csr::drtio::o_get_fifo_space_write(1); (csr::DRTIO[linkno].o_get_fifo_space_write)(1);
csr::drtio::chan_sel_override_en_write(0); (csr::DRTIO[linkno].chan_sel_override_en_write)(0);
} }
} }
pub fn get_packet_counts() -> (u32, u32) { pub fn get_packet_counts(linkno: u8) -> (u32, u32) {
let linkno = linkno as usize;
unsafe { unsafe {
csr::drtio::update_packet_cnt_write(1); (csr::DRTIO[linkno].update_packet_cnt_write)(1);
(csr::drtio::packet_cnt_tx_read(), csr::drtio::packet_cnt_rx_read()) ((csr::DRTIO[linkno].packet_cnt_tx_read)(),
(csr::DRTIO[linkno].packet_cnt_rx_read)())
} }
} }
pub fn get_fifo_space_req_count() -> u32 { pub fn get_fifo_space_req_count(linkno: u8) -> u32 {
let linkno = linkno as usize;
unsafe { unsafe {
csr::drtio::o_dbg_fifo_space_req_cnt_read() (csr::DRTIO[linkno].o_dbg_fifo_space_req_cnt_read)()
} }
} }
} }
@ -299,7 +312,7 @@ pub mod drtio_dbg {
pub fn get_fifo_space(_channel: u32) {} pub fn get_fifo_space(_channel: u32) {}
pub fn get_packet_counts() -> (u32, u32) { (0, 0) } pub fn get_packet_counts(_linkno: u8) -> (u32, u32) { (0, 0) }
pub fn get_fifo_space_req_count() -> u32 { 0 } pub fn get_fifo_space_req_count(_linkno: u8) -> u32 { 0 }
} }

View File

@ -15,25 +15,25 @@ fn process_aux_packet(p: &drtioaux::Packet) {
// In the code below, *_chan_sel_write takes an u8 if there are fewer than 256 channels, // In the code below, *_chan_sel_write takes an u8 if there are fewer than 256 channels,
// and u16 otherwise; hence the `as _` conversion. // and u16 otherwise; hence the `as _` conversion.
match *p { match *p {
drtioaux::Packet::EchoRequest => drtioaux::hw::send(&drtioaux::Packet::EchoReply).unwrap(), drtioaux::Packet::EchoRequest => drtioaux::hw::send_link(0, &drtioaux::Packet::EchoReply).unwrap(),
drtioaux::Packet::RtioErrorRequest => { drtioaux::Packet::RtioErrorRequest => {
let errors; let errors;
unsafe { unsafe {
errors = board::csr::drtio::rtio_error_read(); errors = (board::csr::DRTIO[0].rtio_error_read)();
} }
if errors & 1 != 0 { if errors & 1 != 0 {
unsafe { unsafe {
board::csr::drtio::rtio_error_write(1); (board::csr::DRTIO[0].rtio_error_write)(1);
} }
drtioaux::hw::send(&drtioaux::Packet::RtioErrorCollisionReply).unwrap(); drtioaux::hw::send_link(0, &drtioaux::Packet::RtioErrorCollisionReply).unwrap();
} else if errors & 2 != 0 { } else if errors & 2 != 0 {
unsafe { unsafe {
board::csr::drtio::rtio_error_write(2); (board::csr::DRTIO[0].rtio_error_write)(2);
} }
drtioaux::hw::send(&drtioaux::Packet::RtioErrorBusyReply).unwrap(); drtioaux::hw::send_link(0, &drtioaux::Packet::RtioErrorBusyReply).unwrap();
} else { } else {
drtioaux::hw::send(&drtioaux::Packet::RtioNoErrorReply).unwrap(); drtioaux::hw::send_link(0, &drtioaux::Packet::RtioNoErrorReply).unwrap();
} }
} }
@ -51,7 +51,7 @@ fn process_aux_packet(p: &drtioaux::Packet) {
value = 0; value = 0;
} }
let reply = drtioaux::Packet::MonitorReply { value: value as u32 }; let reply = drtioaux::Packet::MonitorReply { value: value as u32 };
drtioaux::hw::send(&reply).unwrap(); drtioaux::hw::send_link(0, &reply).unwrap();
}, },
drtioaux::Packet::InjectionRequest { channel, overrd, value } => { drtioaux::Packet::InjectionRequest { channel, overrd, value } => {
#[cfg(has_rtio_moninj)] #[cfg(has_rtio_moninj)]
@ -74,50 +74,50 @@ fn process_aux_packet(p: &drtioaux::Packet) {
value = 0; value = 0;
} }
let reply = drtioaux::Packet::InjectionStatusReply { value: value }; let reply = drtioaux::Packet::InjectionStatusReply { value: value };
drtioaux::hw::send(&reply).unwrap(); drtioaux::hw::send_link(0, &reply).unwrap();
}, },
drtioaux::Packet::I2cStartRequest { busno } => { drtioaux::Packet::I2cStartRequest { busno } => {
let succeeded = board::i2c::start(busno).is_ok(); let succeeded = board::i2c::start(busno).is_ok();
drtioaux::hw::send(&drtioaux::Packet::I2cBasicReply { succeeded: succeeded }).unwrap(); drtioaux::hw::send_link(0, &drtioaux::Packet::I2cBasicReply { succeeded: succeeded }).unwrap();
} }
drtioaux::Packet::I2cRestartRequest { busno } => { drtioaux::Packet::I2cRestartRequest { busno } => {
let succeeded = board::i2c::restart(busno).is_ok(); let succeeded = board::i2c::restart(busno).is_ok();
drtioaux::hw::send(&drtioaux::Packet::I2cBasicReply { succeeded: succeeded }).unwrap(); drtioaux::hw::send_link(0, &drtioaux::Packet::I2cBasicReply { succeeded: succeeded }).unwrap();
} }
drtioaux::Packet::I2cStopRequest { busno } => { drtioaux::Packet::I2cStopRequest { busno } => {
let succeeded = board::i2c::stop(busno).is_ok(); let succeeded = board::i2c::stop(busno).is_ok();
drtioaux::hw::send(&drtioaux::Packet::I2cBasicReply { succeeded: succeeded }).unwrap(); drtioaux::hw::send_link(0, &drtioaux::Packet::I2cBasicReply { succeeded: succeeded }).unwrap();
} }
drtioaux::Packet::I2cWriteRequest { busno, data } => { drtioaux::Packet::I2cWriteRequest { busno, data } => {
match board::i2c::write(busno, data) { match board::i2c::write(busno, data) {
Ok(ack) => drtioaux::hw::send(&drtioaux::Packet::I2cWriteReply { succeeded: true, ack: ack }).unwrap(), Ok(ack) => drtioaux::hw::send_link(0, &drtioaux::Packet::I2cWriteReply { succeeded: true, ack: ack }).unwrap(),
Err(_) => drtioaux::hw::send(&drtioaux::Packet::I2cWriteReply { succeeded: false, ack: false }).unwrap() Err(_) => drtioaux::hw::send_link(0, &drtioaux::Packet::I2cWriteReply { succeeded: false, ack: false }).unwrap()
}; };
} }
drtioaux::Packet::I2cReadRequest { busno, ack } => { drtioaux::Packet::I2cReadRequest { busno, ack } => {
match board::i2c::read(busno, ack) { match board::i2c::read(busno, ack) {
Ok(data) => drtioaux::hw::send(&drtioaux::Packet::I2cReadReply { succeeded: true, data: data }).unwrap(), Ok(data) => drtioaux::hw::send_link(0, &drtioaux::Packet::I2cReadReply { succeeded: true, data: data }).unwrap(),
Err(_) => drtioaux::hw::send(&drtioaux::Packet::I2cReadReply { succeeded: false, data: 0xff }).unwrap() Err(_) => drtioaux::hw::send_link(0, &drtioaux::Packet::I2cReadReply { succeeded: false, data: 0xff }).unwrap()
}; };
} }
drtioaux::Packet::SpiSetConfigRequest { busno, flags, write_div, read_div } => { drtioaux::Packet::SpiSetConfigRequest { busno, flags, write_div, read_div } => {
let succeeded = board::spi::set_config(busno, flags, write_div, read_div).is_ok(); let succeeded = board::spi::set_config(busno, flags, write_div, read_div).is_ok();
drtioaux::hw::send(&drtioaux::Packet::SpiBasicReply { succeeded: succeeded }).unwrap(); drtioaux::hw::send_link(0, &drtioaux::Packet::SpiBasicReply { succeeded: succeeded }).unwrap();
}, },
drtioaux::Packet::SpiSetXferRequest { busno, chip_select, write_length, read_length } => { 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(); 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::hw::send_link(0, &drtioaux::Packet::SpiBasicReply { succeeded: succeeded }).unwrap();
} }
drtioaux::Packet::SpiWriteRequest { busno, data } => { drtioaux::Packet::SpiWriteRequest { busno, data } => {
let succeeded = board::spi::write(busno, data).is_ok(); let succeeded = board::spi::write(busno, data).is_ok();
drtioaux::hw::send(&drtioaux::Packet::SpiBasicReply { succeeded: succeeded }).unwrap(); drtioaux::hw::send_link(0, &drtioaux::Packet::SpiBasicReply { succeeded: succeeded }).unwrap();
} }
drtioaux::Packet::SpiReadRequest { busno } => { drtioaux::Packet::SpiReadRequest { busno } => {
match board::spi::read(busno) { match board::spi::read(busno) {
Ok(data) => drtioaux::hw::send(&drtioaux::Packet::SpiReadReply { succeeded: true, data: data }).unwrap(), Ok(data) => drtioaux::hw::send_link(0, &drtioaux::Packet::SpiReadReply { succeeded: true, data: data }).unwrap(),
Err(_) => drtioaux::hw::send(&drtioaux::Packet::SpiReadReply { succeeded: false, data: 0 }).unwrap() Err(_) => drtioaux::hw::send_link(0, &drtioaux::Packet::SpiReadReply { succeeded: false, data: 0 }).unwrap()
}; };
} }
@ -126,7 +126,7 @@ fn process_aux_packet(p: &drtioaux::Packet) {
} }
fn process_aux_packets() { fn process_aux_packets() {
let pr = drtioaux::hw::recv(); let pr = drtioaux::hw::recv_link(0);
match pr { match pr {
Ok(None) => (), Ok(None) => (),
Ok(Some(p)) => process_aux_packet(&p), Ok(Some(p)) => process_aux_packet(&p),
@ -138,8 +138,8 @@ fn process_aux_packets() {
fn process_errors() { fn process_errors() {
let errors; let errors;
unsafe { unsafe {
errors = board::csr::drtio::protocol_error_read(); errors = (board::csr::DRTIO[0].protocol_error_read)();
board::csr::drtio::protocol_error_write(errors); (board::csr::DRTIO[0].protocol_error_write)(errors);
} }
if errors & 1 != 0 { if errors & 1 != 0 {
error!("received packet of an unknown type"); error!("received packet of an unknown type");
@ -185,7 +185,7 @@ const SI5324_SETTINGS: board::si5324::FrequencySettings
fn drtio_link_is_up() -> bool { fn drtio_link_is_up() -> bool {
unsafe { unsafe {
board::csr::drtio::link_status_read() == 1 (board::csr::DRTIO[0].link_status_read)() == 1
} }
} }

View File

@ -53,11 +53,14 @@ class Master(MiniSoC, AMPSoC):
sys_clk_freq=self.clk_freq, sys_clk_freq=self.clk_freq,
clock_div2=True) clock_div2=True)
self.submodules.drtio = DRTIOMaster(self.transceiver) self.submodules.drtio0 = DRTIOMaster(self.transceiver)
self.csr_devices.append("drtio") self.csr_devices.append("drtio0")
self.add_wb_slave(self.mem_map["drtio_aux"], 0x800, self.add_wb_slave(self.mem_map["drtio_aux"], 0x800,
self.drtio.aux_controller.bus) self.drtio0.aux_controller.bus)
self.add_memory_region("drtio_aux", self.mem_map["drtio_aux"] | self.shadow_base, 0x800) self.add_memory_region("drtio0_aux", self.mem_map["drtio_aux"] | self.shadow_base, 0x800)
self.config["has_drtio"] = None
self.add_csr_group("drtio", ["drtio0"])
self.add_memory_group("drtio_aux", ["drtio0_aux"])
platform.add_extension(ad9154_fmc_ebz) platform.add_extension(ad9154_fmc_ebz)
ad9154_spi = platform.request("ad9154_spi") ad9154_spi = platform.request("ad9154_spi")
@ -100,7 +103,7 @@ class Master(MiniSoC, AMPSoC):
self.register_kernel_cpu_csrdevice("rtio_dma") self.register_kernel_cpu_csrdevice("rtio_dma")
self.submodules.cri_con = rtio.CRIInterconnectShared( self.submodules.cri_con = rtio.CRIInterconnectShared(
[self.rtio.cri, self.rtio_dma.cri], [self.rtio.cri, self.rtio_dma.cri],
[self.rtio_core.cri, self.drtio.cri]) [self.rtio_core.cri, self.drtio0.cri])
self.register_kernel_cpu_csrdevice("cri_con") self.register_kernel_cpu_csrdevice("cri_con")

View File

@ -56,13 +56,16 @@ class Satellite(BaseSoC):
sys_clk_freq=self.clk_freq) sys_clk_freq=self.clk_freq)
self.submodules.rx_synchronizer = gtx_7series.RXSynchronizer( self.submodules.rx_synchronizer = gtx_7series.RXSynchronizer(
self.transceiver.rtio_clk_freq, initial_phase=180.0) self.transceiver.rtio_clk_freq, initial_phase=180.0)
self.submodules.drtio = DRTIOSatellite( self.submodules.drtio0 = DRTIOSatellite(
self.transceiver, rtio_channels, self.rx_synchronizer) self.transceiver, rtio_channels, self.rx_synchronizer)
self.csr_devices.append("rx_synchronizer") self.csr_devices.append("rx_synchronizer")
self.csr_devices.append("drtio") self.csr_devices.append("drtio0")
self.add_wb_slave(self.mem_map["drtio_aux"], 0x800, self.add_wb_slave(self.mem_map["drtio_aux"], 0x800,
self.drtio.aux_controller.bus) self.drtio0.aux_controller.bus)
self.add_memory_region("drtio_aux", self.mem_map["drtio_aux"] | self.shadow_base, 0x800) self.add_memory_region("drtio0_aux", self.mem_map["drtio_aux"] | self.shadow_base, 0x800)
self.config["has_drtio"] = None
self.add_csr_group("drtio", ["drtio0"])
self.add_memory_group("drtio_aux", ["drtio0_aux"])
self.config["RTIO_FREQUENCY"] = str(self.transceiver.rtio_clk_freq/1e6) self.config["RTIO_FREQUENCY"] = str(self.transceiver.rtio_clk_freq/1e6)
si5324_clkin = platform.request("si5324_clkin") si5324_clkin = platform.request("si5324_clkin")

View File

@ -15,7 +15,7 @@ requirements:
- python >=3.5.3,<3.6 - python >=3.5.3,<3.6
- setuptools 33.1.1 - setuptools 33.1.1
- migen 0.5.dev py_117+gite826cb9 - migen 0.5.dev py_117+gite826cb9
- misoc 0.6.dev py_32+gitc49a361c - misoc 0.6.dev py_35+gitd6f86c03
- jesd204b 0.3 - jesd204b 0.3
- binutils-or1k-linux >=2.27 - binutils-or1k-linux >=2.27
- llvm-or1k - llvm-or1k