forked from M-Labs/artiq-zynq
proto fw: add rx crc check
This commit is contained in:
parent
bea80d0c1e
commit
0f9be29f4e
|
@ -16,16 +16,32 @@ const MEM_LEN: usize = 0x200;
|
|||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
BufferError,
|
||||
CorruptedPacket,
|
||||
CtrlAckError(u8),
|
||||
LinkDown,
|
||||
UnknownPacket(u8),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CtrlError {
|
||||
AddressReadOnly,
|
||||
AddressWriteOnly,
|
||||
CRCFailed,
|
||||
DataSizeDifferent,
|
||||
InvalidAddress,
|
||||
InvalidData,
|
||||
InvalidOpcode,
|
||||
MalformedPacket,
|
||||
SizeToolarge,
|
||||
}
|
||||
|
||||
impl From<IoError> for Error {
|
||||
fn from(_: IoError) -> Error {
|
||||
Error::BufferError
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Packet {
|
||||
// Upconn packet
|
||||
CtrlRead {
|
||||
|
@ -56,13 +72,13 @@ pub enum Packet {
|
|||
// Downconn packet
|
||||
CtrlAck {
|
||||
ackcode: u8,
|
||||
length: u8,
|
||||
length: u32,
|
||||
data: [u8; DATA_MAXSIZE],
|
||||
},
|
||||
CtrlAckWithTag {
|
||||
tag: u8,
|
||||
ackcode: u8,
|
||||
length: u8,
|
||||
length: u32,
|
||||
data: [u8; DATA_MAXSIZE],
|
||||
},
|
||||
CtrlAckNoData {
|
||||
|
@ -88,18 +104,26 @@ fn read_word(reader: &mut Cursor<&mut [u8]>) -> Result<u32, Error> {
|
|||
}
|
||||
|
||||
impl Packet {
|
||||
pub fn read_from(reader: &mut Cursor<&mut [u8]>, packet_type: u8) -> Result<(), Error> {
|
||||
pub fn read_from(reader: &mut Cursor<&mut [u8]>, packet_type: u8) -> Result<Self, Error> {
|
||||
match packet_type {
|
||||
0x03 => {
|
||||
let ackcode4x = read_word(reader);
|
||||
println!("ackcode4x = {:#010X}", ackcode4x.unwrap());
|
||||
let len = read_word(reader);
|
||||
println!("len = {:#010X}", len.unwrap());
|
||||
let ackcode: u8 = (read_word(reader)? & 0xFF) as u8;
|
||||
let length = read_word(reader)?;
|
||||
|
||||
let mut data: [u8; DATA_MAXSIZE] = [0; DATA_MAXSIZE];
|
||||
if ackcode == 0x00 || ackcode == 0x04 {
|
||||
reader.read(&mut data[0..length as usize])?;
|
||||
};
|
||||
|
||||
match ackcode {
|
||||
0x00 | 0x04 => return Ok(Packet::CtrlAck { ackcode, length, data }),
|
||||
0x01 => return Ok(Packet::CtrlAckNoData { ackcode }),
|
||||
_ => return Err(Error::CtrlAckError(ackcode)),
|
||||
}
|
||||
}
|
||||
0x06 => {}
|
||||
_ => {}
|
||||
0x06 => return Err(Error::UnknownPacket(packet_type)),
|
||||
_ => return Err(Error::UnknownPacket(packet_type)),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn write_to(&self, writer: &mut Cursor<&mut [u8]>) -> Result<(), Error> {
|
||||
// CoaXpress use big endian
|
||||
|
@ -146,9 +170,12 @@ impl Packet {
|
|||
if ackcode == 0x00 || ackcode == 0x04 {
|
||||
writer.write(&[0x00, 0x00, 0x00, length])?;
|
||||
writer.write(&data[0..length as usize])?;
|
||||
let checksum = crc32::checksum_ieee(&writer.get_ref()[4..writer.position()]);
|
||||
writer.write(&(!checksum).to_le_bytes())?;
|
||||
}
|
||||
|
||||
print_packet(&writer.get_ref()[4..writer.position()]);
|
||||
|
||||
let checksum = crc32::checksum_ieee(&writer.get_ref()[4..writer.position()]);
|
||||
writer.write(&(!checksum).to_le_bytes())?;
|
||||
}
|
||||
_ => return Err(Error::UnknownPacket(0)),
|
||||
}
|
||||
|
@ -177,9 +204,26 @@ pub fn receive(channel: usize) -> Result<(), Error> {
|
|||
let mut reader = Cursor::new(slice::from_raw_parts_mut(ptr as *mut u8, MEM_LEN));
|
||||
let packet_type = (CXP[channel].downconn_packet_type_read)();
|
||||
|
||||
Packet::read_from(&mut reader, packet_type);
|
||||
let packet = Packet::read_from(&mut reader, packet_type)?;
|
||||
println!("{:?}", packet);
|
||||
|
||||
// print_packet(slice::from_raw_parts_mut(ptr as *mut u8, MEM_LEN));
|
||||
// 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
|
||||
// Also, the calculation does not include the first 4 bytes of packet_type
|
||||
if packet_type == 0x03 || packet_type == 0x06 {
|
||||
let checksum_at = reader.position();
|
||||
let checksum = (!crc::crc32::checksum_ieee(&reader.get_ref()[0..checksum_at])).swap_bytes();
|
||||
println!("checksum location = {:#010X}", checksum_at);
|
||||
println!("calculated checksum = {:#010X}", checksum);
|
||||
println!("read checksum = {:#010X}", read_word(&mut reader)?);
|
||||
reader.set_position(checksum_at);
|
||||
if read_word(&mut reader)? != checksum {
|
||||
return Err(Error::CorruptedPacket);
|
||||
}
|
||||
}
|
||||
|
||||
print_packet(slice::from_raw_parts_mut(ptr as *mut u8, MEM_LEN));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue