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)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
BufferError,
|
BufferError,
|
||||||
|
CorruptedPacket,
|
||||||
|
CtrlAckError(u8),
|
||||||
LinkDown,
|
LinkDown,
|
||||||
UnknownPacket(u8),
|
UnknownPacket(u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum CtrlError {
|
||||||
|
AddressReadOnly,
|
||||||
|
AddressWriteOnly,
|
||||||
|
CRCFailed,
|
||||||
|
DataSizeDifferent,
|
||||||
|
InvalidAddress,
|
||||||
|
InvalidData,
|
||||||
|
InvalidOpcode,
|
||||||
|
MalformedPacket,
|
||||||
|
SizeToolarge,
|
||||||
|
}
|
||||||
|
|
||||||
impl From<IoError> for Error {
|
impl From<IoError> for Error {
|
||||||
fn from(_: IoError) -> Error {
|
fn from(_: IoError) -> Error {
|
||||||
Error::BufferError
|
Error::BufferError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum Packet {
|
pub enum Packet {
|
||||||
// Upconn packet
|
// Upconn packet
|
||||||
CtrlRead {
|
CtrlRead {
|
||||||
|
@ -56,13 +72,13 @@ pub enum Packet {
|
||||||
// Downconn packet
|
// Downconn packet
|
||||||
CtrlAck {
|
CtrlAck {
|
||||||
ackcode: u8,
|
ackcode: u8,
|
||||||
length: u8,
|
length: u32,
|
||||||
data: [u8; DATA_MAXSIZE],
|
data: [u8; DATA_MAXSIZE],
|
||||||
},
|
},
|
||||||
CtrlAckWithTag {
|
CtrlAckWithTag {
|
||||||
tag: u8,
|
tag: u8,
|
||||||
ackcode: u8,
|
ackcode: u8,
|
||||||
length: u8,
|
length: u32,
|
||||||
data: [u8; DATA_MAXSIZE],
|
data: [u8; DATA_MAXSIZE],
|
||||||
},
|
},
|
||||||
CtrlAckNoData {
|
CtrlAckNoData {
|
||||||
|
@ -88,18 +104,26 @@ fn read_word(reader: &mut Cursor<&mut [u8]>) -> Result<u32, Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Packet {
|
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 {
|
match packet_type {
|
||||||
0x03 => {
|
0x03 => {
|
||||||
let ackcode4x = read_word(reader);
|
let ackcode: u8 = (read_word(reader)? & 0xFF) as u8;
|
||||||
println!("ackcode4x = {:#010X}", ackcode4x.unwrap());
|
let length = read_word(reader)?;
|
||||||
let len = read_word(reader);
|
|
||||||
println!("len = {:#010X}", len.unwrap());
|
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> {
|
pub fn write_to(&self, writer: &mut Cursor<&mut [u8]>) -> Result<(), Error> {
|
||||||
// CoaXpress use big endian
|
// CoaXpress use big endian
|
||||||
|
@ -146,9 +170,12 @@ impl Packet {
|
||||||
if ackcode == 0x00 || ackcode == 0x04 {
|
if ackcode == 0x00 || ackcode == 0x04 {
|
||||||
writer.write(&[0x00, 0x00, 0x00, length])?;
|
writer.write(&[0x00, 0x00, 0x00, length])?;
|
||||||
writer.write(&data[0..length as usize])?;
|
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)),
|
_ => 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 mut reader = Cursor::new(slice::from_raw_parts_mut(ptr as *mut u8, MEM_LEN));
|
||||||
let packet_type = (CXP[channel].downconn_packet_type_read)();
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue