1
0
Fork 0

proto fw: use byteoder crate & add cxpwrite fn

This commit is contained in:
morgan 2024-10-04 16:01:51 +08:00
parent b15d9cc668
commit 3642d81612
1 changed files with 67 additions and 50 deletions

View File

@ -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)?;
}
_ => {}
}