forked from M-Labs/artiq-zynq
proto fw: use byteoder crate & add cxpwrite fn
This commit is contained in:
parent
b15d9cc668
commit
3642d81612
|
@ -1,11 +1,11 @@
|
|||
use core::slice;
|
||||
|
||||
use byteorder::{ByteOrder, NetworkEndian};
|
||||
use core_io::{Error as IoError, Read, Write};
|
||||
use crc::crc32::checksum_ieee;
|
||||
use io::Cursor;
|
||||
use libboard_zynq::println;
|
||||
|
||||
// TODO: fix the import
|
||||
use crate::{mem::mem::{CXP_LOOPBACK_MEM, CXP_RX_MEM, CXP_TX_MEM},
|
||||
pl::csr::CXP};
|
||||
|
||||
|
@ -41,6 +41,33 @@ impl From<IoError> for Error {
|
|||
}
|
||||
}
|
||||
|
||||
// Section 9.2.2.2 (CXP-001-2021)
|
||||
// Only Control packet need CRC32 appended in the end of the packet
|
||||
// CoaXpress use the polynomial of IEEE-802.3 (Ethernet) CRC but the checksum calculation is different
|
||||
fn get_cxp_crc(bytes: &[u8]) -> u32 {
|
||||
(!checksum_ieee(bytes)).swap_bytes()
|
||||
}
|
||||
|
||||
trait CxpRead {
|
||||
fn read_4x_u8(&mut self) -> Result<u8, Error>;
|
||||
|
||||
fn read_u32(&mut self) -> Result<u32, Error>;
|
||||
}
|
||||
impl<Cursor: Read> CxpRead for Cursor {
|
||||
fn read_4x_u8(&mut self) -> Result<u8, Error> {
|
||||
// TODO: add error correction
|
||||
let mut bytes = [0; 4];
|
||||
self.read_exact(&mut bytes)?;
|
||||
Ok(bytes[0])
|
||||
}
|
||||
|
||||
fn read_u32(&mut self) -> Result<u32, Error> {
|
||||
let mut bytes = [0; 4];
|
||||
self.read_exact(&mut bytes)?;
|
||||
Ok(NetworkEndian::read_u32(&bytes))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DownConnPacket {
|
||||
CtrlReply {
|
||||
|
@ -58,35 +85,6 @@ pub enum DownConnPacket {
|
|||
},
|
||||
}
|
||||
|
||||
// Section 9.2.2.2 (CXP-001-2021)
|
||||
// Only Control packet need CRC32 appended in the end of the packet
|
||||
// CoaXpress use the polynomial of IEEE-802.3 (Ethernet) CRC but the checksum calculation is different
|
||||
fn get_cxp_crc(bytes: &[u8]) -> u32 {
|
||||
(!checksum_ieee(bytes)).swap_bytes()
|
||||
}
|
||||
|
||||
trait CxpRead {
|
||||
fn read_4x_u8(&mut self) -> Result<u8, Error>;
|
||||
|
||||
fn read_u32(&mut self) -> Result<u32, Error>;
|
||||
}
|
||||
impl<Cursor: Read> CxpRead for Cursor {
|
||||
#[inline]
|
||||
fn read_4x_u8(&mut self) -> Result<u8, Error> {
|
||||
// TODO: add error correction
|
||||
let mut bytes = [0; 4];
|
||||
self.read_exact(&mut bytes)?;
|
||||
Ok(bytes[0])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_u32(&mut self) -> Result<u32, Error> {
|
||||
let mut bytes = [0; 4];
|
||||
self.read_exact(&mut bytes)?;
|
||||
Ok(u32::from_be_bytes(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
fn capture_ctrl_packet(reader: &mut Cursor<&mut [u8]>, with_tag: bool) -> Result<DownConnPacket, Error> {
|
||||
let mut tag: Option<u8> = None;
|
||||
if with_tag {
|
||||
|
@ -145,6 +143,25 @@ pub fn receive(channel: usize) -> Result<(), Error> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
trait CxpWrite {
|
||||
fn write_4x_u8(&mut self, value: u8) -> Result<(), Error>;
|
||||
|
||||
fn write_u32(&mut self, value: u32) -> Result<(), Error>;
|
||||
}
|
||||
impl<Cursor: Write> CxpWrite for Cursor {
|
||||
fn write_4x_u8(&mut self, value: u8) -> Result<(), Error> {
|
||||
self.write_all(&[value; 4])?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_u32(&mut self, value: u32) -> Result<(), Error> {
|
||||
let mut bytes = [0; 4];
|
||||
NetworkEndian::write_u32(&mut bytes, value);
|
||||
self.write_all(&bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum UpConnPacket {
|
||||
CtrlRead {
|
||||
|
@ -178,20 +195,20 @@ impl UpConnPacket {
|
|||
UpConnPacket::CtrlRead { tag, addr, length } => {
|
||||
match tag {
|
||||
Some(t) => {
|
||||
writer.write(&[0x05; 4])?;
|
||||
writer.write(&[t; 4])?;
|
||||
writer.write_4x_u8(0x05)?;
|
||||
writer.write_4x_u8(t)?;
|
||||
}
|
||||
None => {
|
||||
writer.write(&[0x02; 4])?;
|
||||
writer.write_4x_u8(0x02)?;
|
||||
}
|
||||
}
|
||||
writer.write(&[0x00, 0x00, 0x00, length])?;
|
||||
writer.write(&addr.to_be_bytes())?;
|
||||
writer.write_all(&[0x00, 0x00, 0x00, length])?;
|
||||
writer.write_u32(addr)?;
|
||||
|
||||
// Section 9.6.2 (CXP-001-2021)
|
||||
// only bytes after the first 4 are used in calculating the checksum
|
||||
let checksum = get_cxp_crc(&writer.get_ref()[4..writer.position()]);
|
||||
writer.write(&checksum.to_be_bytes())?;
|
||||
writer.write_u32(checksum)?;
|
||||
}
|
||||
UpConnPacket::CtrlWrite {
|
||||
tag,
|
||||
|
@ -201,38 +218,38 @@ impl UpConnPacket {
|
|||
} => {
|
||||
match tag {
|
||||
Some(t) => {
|
||||
writer.write(&[0x05; 4])?;
|
||||
writer.write(&[t; 4])?;
|
||||
writer.write_4x_u8(0x05)?;
|
||||
writer.write_4x_u8(t)?;
|
||||
}
|
||||
None => {
|
||||
writer.write(&[0x02; 4])?;
|
||||
writer.write_4x_u8(0x02)?;
|
||||
}
|
||||
}
|
||||
writer.write(&[0x01, 0x00, 0x00, length])?;
|
||||
writer.write(&addr.to_be_bytes())?;
|
||||
writer.write(&data[0..length as usize])?;
|
||||
writer.write_all(&[0x01, 0x00, 0x00, length])?;
|
||||
writer.write_u32(addr)?;
|
||||
writer.write_all(&data[0..length as usize])?;
|
||||
|
||||
// Section 9.6.2 (CXP-001-2021)
|
||||
// only bytes after the first 4 are used in calculating the checksum
|
||||
let checksum = get_cxp_crc(&writer.get_ref()[4..writer.position()]);
|
||||
writer.write(&checksum.to_be_bytes())?;
|
||||
writer.write_u32(checksum)?;
|
||||
}
|
||||
UpConnPacket::EventAck { packet_tag } => {
|
||||
writer.write(&[0x08; 4])?;
|
||||
writer.write(&[packet_tag; 4])?;
|
||||
writer.write_4x_u8(0x08)?;
|
||||
writer.write_4x_u8(packet_tag)?;
|
||||
}
|
||||
// DEBUG: Loopback message
|
||||
UpConnPacket::CtrlAckLoopback { ackcode, length, data } => {
|
||||
writer.write(&[0x03; 4])?;
|
||||
writer.write(&[ackcode; 4])?;
|
||||
writer.write_4x_u8(0x03)?;
|
||||
writer.write_4x_u8(ackcode)?;
|
||||
|
||||
if ackcode == 0x00 || ackcode == 0x04 {
|
||||
writer.write(&[0x00, 0x00, 0x00, length])?;
|
||||
writer.write(&data[0..length as usize])?;
|
||||
writer.write_all(&[0x00, 0x00, 0x00, length])?;
|
||||
writer.write_all(&data[0..length as usize])?;
|
||||
}
|
||||
|
||||
let checksum = get_cxp_crc(&writer.get_ref()[4..writer.position()]);
|
||||
writer.write(&checksum.to_be_bytes())?;
|
||||
writer.write_u32(checksum)?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue