forked from M-Labs/artiq
drtio: initial firmware support for multi-link
This commit is contained in:
parent
94ee48860a
commit
9045b4cc19
|
@ -1,3 +1,9 @@
|
|||
"""
|
||||
DRTIO debugging functions.
|
||||
|
||||
Those syscalls are intended for ARTIQ developers only.
|
||||
"""
|
||||
|
||||
from artiq.language.core import syscall
|
||||
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"})
|
||||
def drtio_get_packet_counts() -> TTuple([TInt32, TInt32]):
|
||||
def drtio_get_packet_counts(linkno: TInt32) -> TTuple([TInt32, TInt32]):
|
||||
raise NotImplementedError("syscall not simulated")
|
||||
|
||||
@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")
|
||||
|
|
|
@ -182,14 +182,14 @@ pub mod drtio_dbg {
|
|||
#[repr(C)]
|
||||
pub struct PacketCounts(i32, i32);
|
||||
|
||||
pub extern fn get_packet_counts() -> PacketCounts {
|
||||
send(&DrtioPacketCountRequest);
|
||||
pub extern fn get_packet_counts(linkno: i32) -> PacketCounts {
|
||||
send(&DrtioPacketCountRequest { linkno: linkno as u8 });
|
||||
recv!(&DrtioPacketCountReply { tx_cnt, rx_cnt }
|
||||
=> PacketCounts(tx_cnt as i32, rx_cnt as i32))
|
||||
}
|
||||
|
||||
pub extern fn get_fifo_space_req_count() -> i32 {
|
||||
send(&DrtioFifoSpaceReqCountRequest);
|
||||
pub extern fn get_fifo_space_req_count(linkno: i32) -> i32 {
|
||||
send(&DrtioFifoSpaceReqCountRequest { linkno: linkno as u8 });
|
||||
recv!(&DrtioFifoSpaceReqCountReply { cnt }
|
||||
=> cnt as i32)
|
||||
}
|
||||
|
|
|
@ -252,50 +252,49 @@ pub mod hw {
|
|||
use super::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const AUX_TX_BASE: usize = board::mem::DRTIO_AUX_BASE;
|
||||
const AUX_TX_SIZE: usize = board::mem::DRTIO_AUX_SIZE/2;
|
||||
const AUX_RX_BASE: usize = AUX_TX_BASE + AUX_TX_SIZE;
|
||||
|
||||
fn rx_has_error() -> bool {
|
||||
fn rx_has_error(linkno: u8) -> bool {
|
||||
let linkno = linkno as usize;
|
||||
unsafe {
|
||||
let error = board::csr::drtio::aux_rx_error_read() != 0;
|
||||
let error = (board::csr::DRTIO[linkno].aux_rx_error_read)() != 0;
|
||||
if error {
|
||||
board::csr::drtio::aux_rx_error_write(1)
|
||||
(board::csr::DRTIO[linkno].aux_rx_error_write)(1)
|
||||
}
|
||||
error
|
||||
}
|
||||
}
|
||||
|
||||
struct RxBuffer(&'static [u8]);
|
||||
struct RxBuffer(u8, &'static [u8]);
|
||||
|
||||
impl Drop for RxBuffer {
|
||||
fn drop(&mut self) {
|
||||
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 {
|
||||
if board::csr::drtio::aux_rx_present_read() == 1 {
|
||||
let length = board::csr::drtio::aux_rx_length_read();
|
||||
let sl = slice::from_raw_parts(AUX_RX_BASE as *mut u8, length as usize);
|
||||
Some(RxBuffer(sl))
|
||||
if (board::csr::DRTIO[linkidx].aux_rx_present_read)() == 1 {
|
||||
let length = (board::csr::DRTIO[linkidx].aux_rx_length_read)();
|
||||
let base = board::mem::DRTIO_AUX[linkidx].base + board::mem::DRTIO_AUX[linkidx].size/2;
|
||||
let sl = slice::from_raw_parts(base as *mut u8, length as usize);
|
||||
Some(RxBuffer(linkno, sl))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recv() -> io::Result<Option<Packet>> {
|
||||
if rx_has_error() {
|
||||
pub fn recv_link(linkno: u8) -> io::Result<Option<Packet>> {
|
||||
if rx_has_error(linkno) {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "gateware reported error"))
|
||||
}
|
||||
let buffer = rx_get_buffer();
|
||||
let buffer = rx_get_buffer(linkno);
|
||||
match buffer {
|
||||
Some(rxb) => {
|
||||
let slice = rxb.0;
|
||||
let slice = rxb.1;
|
||||
let mut reader = Cursor::new(slice);
|
||||
|
||||
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 limit = board::clock::get_ms() + timeout_ms;
|
||||
while board::clock::get_ms() < limit {
|
||||
match recv() {
|
||||
match recv_link(linkno) {
|
||||
Ok(None) => (),
|
||||
Ok(Some(packet)) => return Ok(packet),
|
||||
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"))
|
||||
}
|
||||
|
||||
fn tx_get_buffer() -> &'static mut [u8] {
|
||||
fn tx_get_buffer(linkno: u8) -> &'static mut [u8] {
|
||||
let linkno = linkno as usize;
|
||||
unsafe {
|
||||
while board::csr::drtio::aux_tx_read() != 0 {}
|
||||
slice::from_raw_parts_mut(AUX_TX_BASE as *mut u8, AUX_TX_SIZE)
|
||||
while (board::csr::DRTIO[linkno].aux_tx_read)() != 0 {}
|
||||
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 {
|
||||
board::csr::drtio::aux_tx_length_write(length);
|
||||
board::csr::drtio::aux_tx_write(1)
|
||||
(board::csr::DRTIO[linkno].aux_tx_length_write)(length);
|
||||
(board::csr::DRTIO[linkno].aux_tx_write)(1)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send(packet: &Packet) -> io::Result<()> {
|
||||
let sl = tx_get_buffer();
|
||||
pub fn send_link(linkno: u8, packet: &Packet) -> io::Result<()> {
|
||||
let sl = tx_get_buffer(linkno);
|
||||
|
||||
let mut writer = Cursor::new(sl);
|
||||
packet.write_to(&mut writer)?;
|
||||
|
@ -366,8 +369,31 @@ pub mod hw {
|
|||
write_u32(&mut writer, crc)?;
|
||||
len += 4;
|
||||
|
||||
tx_ack_buffer(len as u16);
|
||||
tx_ack_buffer(linkno, len as u16);
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,9 +50,9 @@ pub enum Message<'a> {
|
|||
DrtioChannelStateReply { fifo_space: u16, last_timestamp: u64 },
|
||||
DrtioResetChannelStateRequest { channel: u32 },
|
||||
DrtioGetFifoSpaceRequest { channel: u32 },
|
||||
DrtioPacketCountRequest,
|
||||
DrtioPacketCountRequest { linkno: u8 },
|
||||
DrtioPacketCountReply { tx_cnt: u32, rx_cnt: u32 },
|
||||
DrtioFifoSpaceReqCountRequest,
|
||||
DrtioFifoSpaceReqCountRequest { linkno: u8 },
|
||||
DrtioFifoSpaceReqCountReply { cnt: u32 },
|
||||
|
||||
RunFinished,
|
||||
|
|
|
@ -8,8 +8,8 @@ use sched::Io;
|
|||
mod drtio_i2c {
|
||||
use drtioaux;
|
||||
|
||||
fn basic_reply() -> Result<(), ()> {
|
||||
match drtioaux::hw::recv_timeout(None) {
|
||||
fn basic_reply(nodeno: u8) -> Result<(), ()> {
|
||||
match drtioaux::hw::recv_timeout(nodeno, None) {
|
||||
Ok(drtioaux::Packet::I2cBasicReply { succeeded }) => {
|
||||
if succeeded { Ok(()) } else { Err(()) }
|
||||
}
|
||||
|
@ -24,31 +24,39 @@ mod drtio_i2c {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn start(busno: u32) -> Result<(), ()> {
|
||||
let request = drtioaux::Packet::I2cStartRequest { busno: busno as u8 };
|
||||
drtioaux::hw::send(&request).unwrap();
|
||||
basic_reply()
|
||||
pub fn start(nodeno: u8, busno: u8) -> Result<(), ()> {
|
||||
let request = drtioaux::Packet::I2cStartRequest { busno: busno };
|
||||
if drtioaux::hw::send(nodeno, &request).is_err() {
|
||||
return Err(())
|
||||
}
|
||||
basic_reply(nodeno)
|
||||
}
|
||||
|
||||
pub fn restart(busno: u32) -> Result<(), ()> {
|
||||
let request = drtioaux::Packet::I2cRestartRequest { busno: busno as u8 };
|
||||
drtioaux::hw::send(&request).unwrap();
|
||||
basic_reply()
|
||||
pub fn restart(nodeno: u8, busno: u8) -> Result<(), ()> {
|
||||
let request = drtioaux::Packet::I2cRestartRequest { busno: busno };
|
||||
if drtioaux::hw::send(nodeno, &request).is_err() {
|
||||
return Err(())
|
||||
}
|
||||
basic_reply(nodeno)
|
||||
}
|
||||
|
||||
pub fn stop(busno: u32) -> Result<(), ()> {
|
||||
let request = drtioaux::Packet::I2cStopRequest { busno: busno as u8 };
|
||||
drtioaux::hw::send(&request).unwrap();
|
||||
basic_reply()
|
||||
pub fn stop(nodeno: u8, busno: u8) -> Result<(), ()> {
|
||||
let request = drtioaux::Packet::I2cStopRequest { busno: busno };
|
||||
if drtioaux::hw::send(nodeno, &request).is_err() {
|
||||
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 {
|
||||
busno: busno as u8,
|
||||
busno: busno,
|
||||
data: data
|
||||
};
|
||||
drtioaux::hw::send(&request).unwrap();
|
||||
match drtioaux::hw::recv_timeout(None) {
|
||||
if drtioaux::hw::send(nodeno, &request).is_err() {
|
||||
return Err(())
|
||||
}
|
||||
match drtioaux::hw::recv_timeout(nodeno, None) {
|
||||
Ok(drtioaux::Packet::I2cWriteReply { succeeded, ack }) => {
|
||||
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 {
|
||||
busno: busno as u8,
|
||||
busno: busno,
|
||||
ack: ack
|
||||
};
|
||||
drtioaux::hw::send(&request).unwrap();
|
||||
match drtioaux::hw::recv_timeout(None) {
|
||||
if drtioaux::hw::send(nodeno, &request).is_err() {
|
||||
return Err(())
|
||||
}
|
||||
match drtioaux::hw::recv_timeout(nodeno, None) {
|
||||
Ok(drtioaux::Packet::I2cReadReply { succeeded, data }) => {
|
||||
if succeeded { Ok(data) } else { Err(()) }
|
||||
}
|
||||
|
@ -87,23 +97,23 @@ mod drtio_i2c {
|
|||
|
||||
#[cfg(not(has_drtio))]
|
||||
mod drtio_i2c {
|
||||
pub fn start(_busno: u32) -> Result<(), ()> {
|
||||
pub fn start(_nodeno: u8, _busno: u8) -> Result<(), ()> {
|
||||
Err(())
|
||||
}
|
||||
|
||||
pub fn restart(_busno: u32) -> Result<(), ()> {
|
||||
pub fn restart(_nodeno: u8, _busno: u8) -> Result<(), ()> {
|
||||
Err(())
|
||||
}
|
||||
|
||||
pub fn stop(_busno: u32) -> Result<(), ()> {
|
||||
pub fn stop(_nodeno: u8, _busno: u8) -> Result<(), ()> {
|
||||
Err(())
|
||||
}
|
||||
|
||||
pub fn write(_busno: u32, _data: u8) -> Result<bool, ()> {
|
||||
pub fn write(_nodeno: u8, _busno: u8, _data: u8) -> Result<bool, ()> {
|
||||
Err(())
|
||||
}
|
||||
|
||||
pub fn read(_busno: u32, _ack: bool) -> Result<u8, ()> {
|
||||
pub fn read(_nodeno: u8, _busno: u8, _ack: bool) -> Result<u8, ()> {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
@ -113,52 +123,52 @@ mod i2c {
|
|||
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)
|
||||
let nodeno = (busno >> 16) as u8;
|
||||
let node_busno = busno as u8;
|
||||
if nodeno == 0 {
|
||||
board::i2c::start(node_busno)
|
||||
} else {
|
||||
drtio_i2c::start(busno)
|
||||
drtio_i2c::start(nodeno, node_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)
|
||||
let nodeno = (busno >> 16) as u8;
|
||||
let node_busno = busno as u8;
|
||||
if nodeno == 0 {
|
||||
board::i2c::restart(node_busno)
|
||||
} else {
|
||||
drtio_i2c::restart(busno)
|
||||
drtio_i2c::restart(nodeno, node_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)
|
||||
let nodeno = (busno >> 16) as u8;
|
||||
let node_busno = busno as u8;
|
||||
if nodeno == 0 {
|
||||
board::i2c::stop(node_busno)
|
||||
} else {
|
||||
drtio_i2c::stop(busno)
|
||||
drtio_i2c::stop(nodeno, node_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)
|
||||
let nodeno = (busno >> 16 )as u8;
|
||||
let node_busno = busno as u8;
|
||||
if nodeno == 0 {
|
||||
board::i2c::write(node_busno, data)
|
||||
} else {
|
||||
drtio_i2c::write(busno, data)
|
||||
drtio_i2c::write(nodeno, node_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)
|
||||
let nodeno = (busno >> 16) as u8;
|
||||
let node_busno = busno as u8;
|
||||
if nodeno == 0 {
|
||||
board::i2c::read(node_busno, ack)
|
||||
} else {
|
||||
drtio_i2c::read(busno, ack)
|
||||
drtio_i2c::read(nodeno, node_busno, ack)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -167,8 +177,8 @@ mod i2c {
|
|||
mod drtio_spi {
|
||||
use drtioaux;
|
||||
|
||||
fn basic_reply() -> Result<(), ()> {
|
||||
match drtioaux::hw::recv_timeout(None) {
|
||||
fn basic_reply(nodeno: u8) -> Result<(), ()> {
|
||||
match drtioaux::hw::recv_timeout(nodeno, None) {
|
||||
Ok(drtioaux::Packet::SpiBasicReply { succeeded }) => {
|
||||
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 {
|
||||
busno: busno as u8,
|
||||
busno: busno,
|
||||
flags: flags,
|
||||
write_div: write_div,
|
||||
read_div: read_div
|
||||
};
|
||||
drtioaux::hw::send(&request).unwrap();
|
||||
basic_reply()
|
||||
if drtioaux::hw::send(nodeno, &request).is_err() {
|
||||
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 {
|
||||
busno: busno as u8,
|
||||
busno: busno,
|
||||
chip_select: chip_select,
|
||||
write_length: write_length,
|
||||
read_length: read_length
|
||||
};
|
||||
drtioaux::hw::send(&request).unwrap();
|
||||
basic_reply()
|
||||
if drtioaux::hw::send(nodeno, &request).is_err() {
|
||||
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 {
|
||||
busno: busno as u8,
|
||||
busno: busno,
|
||||
data: data
|
||||
};
|
||||
drtioaux::hw::send(&request).unwrap();
|
||||
basic_reply()
|
||||
if drtioaux::hw::send(nodeno, &request).is_err() {
|
||||
return Err(())
|
||||
}
|
||||
basic_reply(nodeno)
|
||||
}
|
||||
|
||||
pub fn read(busno: u32) -> Result<u32, ()> {
|
||||
let request = drtioaux::Packet::SpiReadRequest { busno: busno as u8 };
|
||||
drtioaux::hw::send(&request).unwrap();
|
||||
match drtioaux::hw::recv_timeout(None) {
|
||||
pub fn read(nodeno: u8, busno: u8) -> Result<u32, ()> {
|
||||
let request = drtioaux::Packet::SpiReadRequest { busno: busno };
|
||||
if drtioaux::hw::send(nodeno, &request).is_err() {
|
||||
return Err(())
|
||||
}
|
||||
match drtioaux::hw::recv_timeout(nodeno, None) {
|
||||
Ok(drtioaux::Packet::SpiReadReply { succeeded, data }) => {
|
||||
if succeeded { Ok(data) } else { Err(()) }
|
||||
}
|
||||
|
@ -235,19 +253,19 @@ mod drtio_spi {
|
|||
|
||||
#[cfg(not(has_drtio))]
|
||||
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(())
|
||||
}
|
||||
|
||||
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(())
|
||||
}
|
||||
|
||||
pub fn write(_busno: u32, _data: u32) -> Result<(), ()> {
|
||||
pub fn write(_nodeno: u8, _busno: u8, _data: u32) -> Result<(), ()> {
|
||||
Err(())
|
||||
}
|
||||
|
||||
pub fn read(_busno: u32) -> Result<u32, ()> {
|
||||
pub fn read(_nodeno: u8, _busno: u8) -> Result<u32, ()> {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
@ -257,42 +275,42 @@ mod spi {
|
|||
use super::drtio_spi;
|
||||
|
||||
pub fn set_config(busno: u32, flags: u8, write_div: u8, read_div: u8) -> Result<(), ()> {
|
||||
let drtio = busno >> 16;
|
||||
let dev_busno = busno as u8;
|
||||
if drtio == 0 {
|
||||
board::spi::set_config(dev_busno, flags, write_div, read_div)
|
||||
let nodeno = (busno >> 16) as u8;
|
||||
let node_busno = busno as u8;
|
||||
if nodeno == 0 {
|
||||
board::spi::set_config(node_busno, flags, write_div, read_div)
|
||||
} 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<(), ()> {
|
||||
let drtio = busno >> 16;
|
||||
let dev_busno = busno as u8;
|
||||
if drtio == 0 {
|
||||
board::spi::set_xfer(dev_busno, chip_select, write_length, read_length)
|
||||
let nodeno = (busno >> 16) as u8;
|
||||
let node_busno = busno as u8;
|
||||
if nodeno == 0 {
|
||||
board::spi::set_xfer(node_busno, chip_select, write_length, read_length)
|
||||
} 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<(), ()> {
|
||||
let drtio = busno >> 16;
|
||||
let dev_busno = busno as u8;
|
||||
if drtio == 0 {
|
||||
board::spi::write(dev_busno, data)
|
||||
let nodeno = (busno >> 16) as u8;
|
||||
let node_busno = busno as u8;
|
||||
if nodeno == 0 {
|
||||
board::spi::write(node_busno, data)
|
||||
} else {
|
||||
drtio_spi::write(busno, data)
|
||||
drtio_spi::write(nodeno, node_busno, data)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(busno: u32) -> Result<u32, ()> {
|
||||
let drtio = busno >> 16;
|
||||
let dev_busno = busno as u8;
|
||||
if drtio == 0 {
|
||||
board::spi::read(dev_busno)
|
||||
let nodeno = (busno >> 16) as u8;
|
||||
let node_busno = busno as u8;
|
||||
if nodeno == 0 {
|
||||
board::spi::read(node_busno)
|
||||
} 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);
|
||||
kern_acknowledge()
|
||||
}
|
||||
&kern::DrtioPacketCountRequest => {
|
||||
let (tx_cnt, rx_cnt) = rtio_mgt::drtio_dbg::get_packet_counts();
|
||||
&kern::DrtioPacketCountRequest { linkno } => {
|
||||
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::DrtioFifoSpaceReqCountRequest => {
|
||||
let cnt = rtio_mgt::drtio_dbg::get_fifo_space_req_count();
|
||||
&kern::DrtioFifoSpaceReqCountRequest { linkno } => {
|
||||
let cnt = rtio_mgt::drtio_dbg::get_fifo_space_req_count(linkno);
|
||||
kern_send(io, &kern::DrtioFifoSpaceReqCountReply { cnt: cnt })
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@ use sched::{TcpListener, TcpStream};
|
|||
use board::{clock, csr};
|
||||
#[cfg(has_drtio)]
|
||||
use drtioaux;
|
||||
#[cfg(has_drtio)]
|
||||
use rtio_mgt;
|
||||
|
||||
use moninj_proto::*;
|
||||
|
||||
|
@ -35,32 +33,36 @@ fn read_probe_local(channel: u16, probe: u8) -> u32 {
|
|||
}
|
||||
|
||||
#[cfg(has_drtio)]
|
||||
fn read_probe_drtio(channel: u16, probe: u8) -> u32 {
|
||||
if rtio_mgt::drtio::link_is_running() {
|
||||
let request = drtioaux::Packet::MonitorRequest { channel: channel, probe: probe };
|
||||
drtioaux::hw::send(&request).unwrap();
|
||||
match drtioaux::hw::recv_timeout(None) {
|
||||
Ok(drtioaux::Packet::MonitorReply { value }) => return value,
|
||||
Ok(_) => error!("received unexpected aux packet"),
|
||||
Err(e) => error!("aux packet error ({})", e)
|
||||
fn read_probe_drtio(nodeno: u8, channel: u16, probe: u8) -> u32 {
|
||||
let request = drtioaux::Packet::MonitorRequest { channel: channel, probe: probe };
|
||||
match drtioaux::hw::send(nodeno, &request) {
|
||||
Ok(_) => (),
|
||||
Err(e) => {
|
||||
error!("aux packet error ({})", e);
|
||||
return 0;
|
||||
}
|
||||
0
|
||||
} else {
|
||||
0
|
||||
}
|
||||
match drtioaux::hw::recv_timeout(nodeno, None) {
|
||||
Ok(drtioaux::Packet::MonitorReply { value }) => return value,
|
||||
Ok(_) => error!("received unexpected aux packet"),
|
||||
Err(e) => error!("aux packet error ({})", e)
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
fn read_probe(channel: u32, probe: u8) -> u32 {
|
||||
let nodeno = (channel >> 16) as u8;
|
||||
let node_channel = channel as u16;
|
||||
#[cfg(has_rtio_moninj)]
|
||||
{
|
||||
if channel & 0xff0000 == 0 {
|
||||
return read_probe_local(channel as u16, probe)
|
||||
if nodeno == 0 {
|
||||
return read_probe_local(node_channel, probe)
|
||||
}
|
||||
}
|
||||
#[cfg(has_drtio)]
|
||||
{
|
||||
if channel & 0xff0000 != 0 {
|
||||
return read_probe_drtio(channel as u16, probe)
|
||||
if nodeno != 0 {
|
||||
return read_probe_drtio(nodeno, node_channel, probe)
|
||||
}
|
||||
}
|
||||
error!("read_probe: unrecognized channel number {}", channel);
|
||||
|
@ -77,29 +79,32 @@ fn inject_local(channel: u16, overrd: u8, value: u8) {
|
|||
}
|
||||
|
||||
#[cfg(has_drtio)]
|
||||
fn inject_drtio(channel: u16, overrd: u8, value: u8) {
|
||||
if rtio_mgt::drtio::link_is_running() {
|
||||
let request = drtioaux::Packet::InjectionRequest {
|
||||
channel: channel,
|
||||
overrd: overrd,
|
||||
value: value
|
||||
};
|
||||
drtioaux::hw::send(&request).unwrap();
|
||||
fn inject_drtio(nodeno: u8, channel: u16, overrd: u8, value: u8) {
|
||||
let request = drtioaux::Packet::InjectionRequest {
|
||||
channel: channel,
|
||||
overrd: overrd,
|
||||
value: value
|
||||
};
|
||||
match drtioaux::hw::send(nodeno, &request) {
|
||||
Ok(_) => (),
|
||||
Err(e) => error!("aux packet error ({})", e)
|
||||
}
|
||||
}
|
||||
|
||||
fn inject(channel: u32, overrd: u8, value: u8) {
|
||||
let nodeno = (channel >> 16) as u8;
|
||||
let node_channel = channel as u16;
|
||||
#[cfg(has_rtio_moninj)]
|
||||
{
|
||||
if channel & 0xff0000 == 0 {
|
||||
inject_local(channel as u16, overrd, value);
|
||||
if nodeno == 0 {
|
||||
inject_local(node_channel, overrd, value);
|
||||
return
|
||||
}
|
||||
}
|
||||
#[cfg(has_drtio)]
|
||||
{
|
||||
if channel & 0xff0000 != 0 {
|
||||
inject_drtio(channel as u16, overrd, value);
|
||||
if nodeno != 0 {
|
||||
inject_drtio(nodeno, node_channel, overrd, value);
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -116,35 +121,39 @@ fn read_injection_status_local(channel: u16, overrd: u8) -> u8 {
|
|||
}
|
||||
|
||||
#[cfg(has_drtio)]
|
||||
fn read_injection_status_drtio(channel: u16, overrd: u8) -> u8 {
|
||||
if rtio_mgt::drtio::link_is_running() {
|
||||
let request = drtioaux::Packet::InjectionStatusRequest {
|
||||
channel: channel,
|
||||
overrd: overrd
|
||||
};
|
||||
drtioaux::hw::send(&request).unwrap();
|
||||
match drtioaux::hw::recv_timeout(None) {
|
||||
Ok(drtioaux::Packet::InjectionStatusReply { value }) => return value,
|
||||
Ok(_) => error!("received unexpected aux packet"),
|
||||
Err(e) => error!("aux packet error ({})", e)
|
||||
fn read_injection_status_drtio(nodeno: u8, channel: u16, overrd: u8) -> u8 {
|
||||
let request = drtioaux::Packet::InjectionStatusRequest {
|
||||
channel: channel,
|
||||
overrd: overrd
|
||||
};
|
||||
match drtioaux::hw::send(nodeno, &request) {
|
||||
Ok(_) => (),
|
||||
Err(e) => {
|
||||
error!("aux packet error ({})", e);
|
||||
return 0;
|
||||
}
|
||||
0
|
||||
} else {
|
||||
0
|
||||
}
|
||||
match drtioaux::hw::recv_timeout(nodeno, None) {
|
||||
Ok(drtioaux::Packet::InjectionStatusReply { value }) => return value,
|
||||
Ok(_) => error!("received unexpected aux packet"),
|
||||
Err(e) => error!("aux packet error ({})", e)
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
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)]
|
||||
{
|
||||
if channel & 0xff0000 == 0 {
|
||||
return read_injection_status_local(channel as u16, probe)
|
||||
if nodeno == 0 {
|
||||
return read_injection_status_local(node_channel, probe)
|
||||
}
|
||||
}
|
||||
#[cfg(has_drtio)]
|
||||
{
|
||||
if channel & 0xff0000 != 0 {
|
||||
return read_injection_status_drtio(channel as u16, probe)
|
||||
if nodeno != 0 {
|
||||
return read_injection_status_drtio(nodeno, node_channel, probe)
|
||||
}
|
||||
}
|
||||
error!("read_injection_status: unrecognized channel number {}", channel);
|
||||
|
|
|
@ -43,80 +43,70 @@ pub mod drtio {
|
|||
|
||||
pub fn startup(io: &Io) {
|
||||
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_set_running(running: bool) {
|
||||
fn link_rx_up(linkno: u8) -> bool {
|
||||
let linkno = linkno as usize;
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
csr::drtio::reset_phy_write(1);
|
||||
while csr::drtio::o_wait_read() == 1 {}
|
||||
(csr::DRTIO[linkidx].reset_write)(1);
|
||||
while (csr::DRTIO[linkidx].o_wait_read)() == 1 {}
|
||||
}
|
||||
}
|
||||
// TODO: determine actual number of remote FIFOs
|
||||
for channel in 0..16 {
|
||||
unsafe {
|
||||
(csr::DRTIO[linkidx].chan_sel_override_write)(channel);
|
||||
(csr::DRTIO[linkidx].chan_sel_override_en_write)(1);
|
||||
|
||||
fn sync_tsc() {
|
||||
unsafe {
|
||||
csr::drtio::set_time_write(1);
|
||||
while csr::drtio::set_time_read() == 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)());
|
||||
|
||||
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);
|
||||
(csr::DRTIO[linkidx].chan_sel_override_en_write)(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
if link_is_running() {
|
||||
unsafe {
|
||||
csr::drtio::reset_write(1);
|
||||
while csr::drtio::o_wait_read() == 1 {}
|
||||
}
|
||||
for channel in 0..16 {
|
||||
init_channel(channel);
|
||||
}
|
||||
for linkno in 0..csr::DRTIO.len() {
|
||||
init_link(linkno as u8);
|
||||
}
|
||||
}
|
||||
|
||||
fn ping_remote(io: &Io) -> u32 {
|
||||
fn ping_remote(linkno: u8, io: &Io) -> u32 {
|
||||
let mut count = 0;
|
||||
loop {
|
||||
if !link_is_up() {
|
||||
if !link_rx_up(linkno) {
|
||||
return 0
|
||||
}
|
||||
count += 1;
|
||||
drtioaux::hw::send(&drtioaux::Packet::EchoRequest).unwrap();
|
||||
drtioaux::hw::send_link(linkno, &drtioaux::Packet::EchoRequest).unwrap();
|
||||
io.sleep(100).unwrap();
|
||||
let pr = drtioaux::hw::recv();
|
||||
let pr = drtioaux::hw::recv_link(linkno);
|
||||
match pr {
|
||||
Ok(Some(drtioaux::Packet::EchoReply)) => return count,
|
||||
_ => {}
|
||||
|
@ -124,59 +114,72 @@ pub mod drtio {
|
|||
}
|
||||
}
|
||||
|
||||
fn process_local_errors(linkno: u8) {
|
||||
let errors;
|
||||
let linkidx = linkno as usize;
|
||||
unsafe {
|
||||
errors = (csr::DRTIO[linkidx].protocol_error_read)();
|
||||
(csr::DRTIO[linkidx].protocol_error_write)(errors);
|
||||
}
|
||||
if errors != 0 {
|
||||
error!("[LINK#{}] found error(s)", linkno);
|
||||
if errors & 1 != 0 {
|
||||
error!("[LINK#{}] received packet of an unknown type", linkno);
|
||||
}
|
||||
if errors & 2 != 0 {
|
||||
error!("[LINK#{}] received truncated packet", linkno);
|
||||
}
|
||||
if errors & 4 != 0 {
|
||||
error!("[LINK#{}] timeout attempting to get remote FIFO space", linkno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn process_aux_errors(linkno: u8) {
|
||||
drtioaux::hw::send_link(linkno, &drtioaux::Packet::RtioErrorRequest).unwrap();
|
||||
match drtioaux::hw::recv_timeout_link(linkno, None) {
|
||||
Ok(drtioaux::Packet::RtioNoErrorReply) => (),
|
||||
Ok(drtioaux::Packet::RtioErrorCollisionReply) =>
|
||||
error!("[LINK#{}] RTIO collision", linkno),
|
||||
Ok(drtioaux::Packet::RtioErrorBusyReply) =>
|
||||
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) {
|
||||
loop {
|
||||
io.until(link_is_up).unwrap();
|
||||
info!("link RX is up, pinging");
|
||||
let mut link_up = vec![false; csr::DRTIO.len()];
|
||||
|
||||
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");
|
||||
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.until(|| !link_is_up()).unwrap();
|
||||
link_set_running(false);
|
||||
info!("link is down");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_error_thread(io: Io) {
|
||||
loop {
|
||||
unsafe {
|
||||
io.until(|| csr::drtio::protocol_error_read() != 0).unwrap();
|
||||
let errors = csr::drtio::protocol_error_read();
|
||||
if errors & 1 != 0 {
|
||||
error!("received packet of an unknown type");
|
||||
}
|
||||
if errors & 2 != 0 {
|
||||
error!("received truncated packet");
|
||||
}
|
||||
if errors & 4 != 0 {
|
||||
error!("timeout attempting to get remote FIFO space");
|
||||
}
|
||||
csr::drtio::protocol_error_write(errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn aux_error_thread(io: Io) {
|
||||
loop {
|
||||
io.sleep(200).unwrap();
|
||||
if link_is_running() {
|
||||
drtioaux::hw::send(&drtioaux::Packet::RtioErrorRequest).unwrap();
|
||||
match drtioaux::hw::recv_timeout(None) {
|
||||
Ok(drtioaux::Packet::RtioNoErrorReply) => (),
|
||||
Ok(drtioaux::Packet::RtioErrorCollisionReply) => error!("RTIO collision (in satellite)"),
|
||||
Ok(drtioaux::Packet::RtioErrorBusyReply) => error!("RTIO busy (in satellite)"),
|
||||
Ok(_) => error!("received unexpected aux packet"),
|
||||
Err(e) => error!("aux packet error ({})", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -248,45 +251,55 @@ pub fn init_core() {
|
|||
pub mod drtio_dbg {
|
||||
use board::csr;
|
||||
|
||||
// TODO: routing
|
||||
pub fn get_channel_state(channel: u32) -> (u16, u64) {
|
||||
let linkno = ((channel >> 16) - 1) as usize;
|
||||
let node_channel = channel as u16;
|
||||
unsafe {
|
||||
csr::drtio::chan_sel_override_write(channel as u16);
|
||||
csr::drtio::chan_sel_override_en_write(1);
|
||||
let fifo_space = csr::drtio::o_dbg_fifo_space_read();
|
||||
let last_timestamp = csr::drtio::o_dbg_last_timestamp_read();
|
||||
csr::drtio::chan_sel_override_en_write(0);
|
||||
(csr::DRTIO[linkno].chan_sel_override_write)(node_channel as u16);
|
||||
(csr::DRTIO[linkno].chan_sel_override_en_write)(1);
|
||||
let fifo_space = (csr::DRTIO[linkno].o_dbg_fifo_space_read)();
|
||||
let last_timestamp = (csr::DRTIO[linkno].o_dbg_last_timestamp_read)();
|
||||
(csr::DRTIO[linkno].chan_sel_override_en_write)(0);
|
||||
(fifo_space, last_timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_channel_state(channel: u32) {
|
||||
let linkno = ((channel >> 16) - 1) as usize;
|
||||
let node_channel = channel as u16;
|
||||
unsafe {
|
||||
csr::drtio::chan_sel_override_write(channel as u16);
|
||||
csr::drtio::chan_sel_override_en_write(1);
|
||||
csr::drtio::o_reset_channel_status_write(1);
|
||||
csr::drtio::chan_sel_override_en_write(0);
|
||||
(csr::DRTIO[linkno].chan_sel_override_write)(node_channel);
|
||||
(csr::DRTIO[linkno].chan_sel_override_en_write)(1);
|
||||
(csr::DRTIO[linkno].o_reset_channel_status_write)(1);
|
||||
(csr::DRTIO[linkno].chan_sel_override_en_write)(0);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_fifo_space(channel: u32) {
|
||||
let linkno = ((channel >> 16) - 1) as usize;
|
||||
let node_channel = channel as u16;
|
||||
unsafe {
|
||||
csr::drtio::chan_sel_override_write(channel as u16);
|
||||
csr::drtio::chan_sel_override_en_write(1);
|
||||
csr::drtio::o_get_fifo_space_write(1);
|
||||
csr::drtio::chan_sel_override_en_write(0);
|
||||
(csr::DRTIO[linkno].chan_sel_override_write)(node_channel);
|
||||
(csr::DRTIO[linkno].chan_sel_override_en_write)(1);
|
||||
(csr::DRTIO[linkno].o_get_fifo_space_write)(1);
|
||||
(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 {
|
||||
csr::drtio::update_packet_cnt_write(1);
|
||||
(csr::drtio::packet_cnt_tx_read(), csr::drtio::packet_cnt_rx_read())
|
||||
(csr::DRTIO[linkno].update_packet_cnt_write)(1);
|
||||
((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 {
|
||||
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_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 }
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
// and u16 otherwise; hence the `as _` conversion.
|
||||
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 => {
|
||||
let errors;
|
||||
unsafe {
|
||||
errors = board::csr::drtio::rtio_error_read();
|
||||
errors = (board::csr::DRTIO[0].rtio_error_read)();
|
||||
}
|
||||
if errors & 1 != 0 {
|
||||
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 {
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
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 } => {
|
||||
#[cfg(has_rtio_moninj)]
|
||||
|
@ -74,50 +74,50 @@ fn process_aux_packet(p: &drtioaux::Packet) {
|
|||
value = 0;
|
||||
}
|
||||
let reply = drtioaux::Packet::InjectionStatusReply { value: value };
|
||||
drtioaux::hw::send(&reply).unwrap();
|
||||
drtioaux::hw::send_link(0, &reply).unwrap();
|
||||
},
|
||||
|
||||
drtioaux::Packet::I2cStartRequest { busno } => {
|
||||
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 } => {
|
||||
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 } => {
|
||||
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 } => {
|
||||
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()
|
||||
Ok(ack) => drtioaux::hw::send_link(0, &drtioaux::Packet::I2cWriteReply { succeeded: true, ack: ack }).unwrap(),
|
||||
Err(_) => drtioaux::hw::send_link(0, &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()
|
||||
Ok(data) => drtioaux::hw::send_link(0, &drtioaux::Packet::I2cReadReply { succeeded: true, data: data }).unwrap(),
|
||||
Err(_) => drtioaux::hw::send_link(0, &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::hw::send_link(0, &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::hw::send_link(0, &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::hw::send_link(0, &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()
|
||||
Ok(data) => drtioaux::hw::send_link(0, &drtioaux::Packet::SpiReadReply { succeeded: true, data: data }).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() {
|
||||
let pr = drtioaux::hw::recv();
|
||||
let pr = drtioaux::hw::recv_link(0);
|
||||
match pr {
|
||||
Ok(None) => (),
|
||||
Ok(Some(p)) => process_aux_packet(&p),
|
||||
|
@ -138,8 +138,8 @@ fn process_aux_packets() {
|
|||
fn process_errors() {
|
||||
let errors;
|
||||
unsafe {
|
||||
errors = board::csr::drtio::protocol_error_read();
|
||||
board::csr::drtio::protocol_error_write(errors);
|
||||
errors = (board::csr::DRTIO[0].protocol_error_read)();
|
||||
(board::csr::DRTIO[0].protocol_error_write)(errors);
|
||||
}
|
||||
if errors & 1 != 0 {
|
||||
error!("received packet of an unknown type");
|
||||
|
@ -185,7 +185,7 @@ const SI5324_SETTINGS: board::si5324::FrequencySettings
|
|||
|
||||
fn drtio_link_is_up() -> bool {
|
||||
unsafe {
|
||||
board::csr::drtio::link_status_read() == 1
|
||||
(board::csr::DRTIO[0].link_status_read)() == 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,11 +53,14 @@ class Master(MiniSoC, AMPSoC):
|
|||
sys_clk_freq=self.clk_freq,
|
||||
clock_div2=True)
|
||||
|
||||
self.submodules.drtio = DRTIOMaster(self.transceiver)
|
||||
self.csr_devices.append("drtio")
|
||||
self.submodules.drtio0 = DRTIOMaster(self.transceiver)
|
||||
self.csr_devices.append("drtio0")
|
||||
self.add_wb_slave(self.mem_map["drtio_aux"], 0x800,
|
||||
self.drtio.aux_controller.bus)
|
||||
self.add_memory_region("drtio_aux", self.mem_map["drtio_aux"] | self.shadow_base, 0x800)
|
||||
self.drtio0.aux_controller.bus)
|
||||
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)
|
||||
ad9154_spi = platform.request("ad9154_spi")
|
||||
|
@ -100,7 +103,7 @@ class Master(MiniSoC, AMPSoC):
|
|||
self.register_kernel_cpu_csrdevice("rtio_dma")
|
||||
self.submodules.cri_con = rtio.CRIInterconnectShared(
|
||||
[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")
|
||||
|
||||
|
||||
|
|
|
@ -56,13 +56,16 @@ class Satellite(BaseSoC):
|
|||
sys_clk_freq=self.clk_freq)
|
||||
self.submodules.rx_synchronizer = gtx_7series.RXSynchronizer(
|
||||
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.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.drtio.aux_controller.bus)
|
||||
self.add_memory_region("drtio_aux", self.mem_map["drtio_aux"] | self.shadow_base, 0x800)
|
||||
self.drtio0.aux_controller.bus)
|
||||
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)
|
||||
si5324_clkin = platform.request("si5324_clkin")
|
||||
|
|
|
@ -15,7 +15,7 @@ requirements:
|
|||
- python >=3.5.3,<3.6
|
||||
- setuptools 33.1.1
|
||||
- migen 0.5.dev py_117+gite826cb9
|
||||
- misoc 0.6.dev py_32+gitc49a361c
|
||||
- misoc 0.6.dev py_35+gitd6f86c03
|
||||
- jesd204b 0.3
|
||||
- binutils-or1k-linux >=2.27
|
||||
- llvm-or1k
|
||||
|
|
Loading…
Reference in New Issue