diff --git a/src/libboard_artiq/src/cxp_proto.rs b/src/libboard_artiq/src/cxp_proto.rs index 739aca4..1db00ce 100644 --- a/src/libboard_artiq/src/cxp_proto.rs +++ b/src/libboard_artiq/src/cxp_proto.rs @@ -1,7 +1,7 @@ use core::slice; use core_io::{Error as IoError, Read, Write}; -use crc::crc32; +use crc::crc32::checksum_ieee; use io::Cursor; use libboard_zynq::println; @@ -58,7 +58,14 @@ pub enum DownConnPacket { }, } -pub fn capture_ctrl_packet(reader: &mut Cursor<&mut [u8]>, with_tag: bool) -> Result { +// 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() +} + +fn capture_ctrl_packet(reader: &mut Cursor<&mut [u8]>, with_tag: bool) -> Result { let mut tag: Option = None; if with_tag { tag = Some((read_word(reader)? & 0xFF) as u8); @@ -71,6 +78,14 @@ pub fn capture_ctrl_packet(reader: &mut Cursor<&mut [u8]>, with_tag: bool) -> Re let length = read_word(reader)?; let mut data: [u8; DATA_MAXSIZE] = [0; DATA_MAXSIZE]; reader.read(&mut data[0..length as usize])?; + + let checksum = get_cxp_crc(&reader.get_ref()[0..reader.position()]); + let recv_checksum = read_word(reader)?; + println!("calculated checksum = {:#010X}", checksum); + println!("read checksum = {:#010X}", recv_checksum); + if recv_checksum != checksum { + return Err(Error::CorruptedPacket); + } return Ok(DownConnPacket::CtrlReply { tag, length, data }); } 0x01 => return Ok(DownConnPacket::CtrlAck { tag }), @@ -78,6 +93,14 @@ pub fn capture_ctrl_packet(reader: &mut Cursor<&mut [u8]>, with_tag: bool) -> Re let length = read_word(reader)?; let mut time: [u8; DATA_MAXSIZE] = [0; DATA_MAXSIZE]; reader.read(&mut time[0..length as usize])?; + + let checksum = get_cxp_crc(&reader.get_ref()[0..reader.position()]); + let recv_checksum = read_word(reader)?; + println!("calculated checksum = {:#010X}", checksum); + println!("read checksum = {:#010X}", recv_checksum); + if recv_checksum != checksum { + return Err(Error::CorruptedPacket); + } return Ok(DownConnPacket::CtrlDelay { tag, length, time }); } _ => return Err(Error::CtrlAckError(ackcode)), @@ -172,22 +195,18 @@ impl Packet { writer.write(&data[0..length as usize])?; } - let checksum = (!crc::crc32::checksum_ieee(&writer.get_ref()[4..writer.position()])).swap_bytes(); - writer.write(&checksum.to_be_bytes())?; + writer.write(&get_cxp_crc(&writer.get_ref()[4..writer.position()]).to_be_bytes())?; } _ => {} } // 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 + // The crc calculation does not include the first 4 bytes of packet_type match *self { Packet::CtrlRead { .. } | Packet::CtrlWrite { .. } | Packet::CtrlReadWithTag { .. } | Packet::CtrlWriteWithTag { .. } => { - let checksum = (!crc::crc32::checksum_ieee(&writer.get_ref()[4..writer.position()])).swap_bytes(); - writer.write(&checksum.to_be_bytes())?; + writer.write(&get_cxp_crc(&writer.get_ref()[4..writer.position()]).to_be_bytes())?; } _ => {} } @@ -204,27 +223,11 @@ pub fn receive(channel: usize) -> Result<(), Error> { let packet = match packet_type { 0x03 => capture_ctrl_packet(&mut reader, false), - 0x06 => capture_ctrl_packet(&mut reader, false), + 0x06 => capture_ctrl_packet(&mut reader, true), _ => return Err(Error::UnknownPacket(packet_type)), }; println!("{:?}", packet); - // 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(())