diff --git a/src/libboard_artiq/src/drtioaux.rs b/src/libboard_artiq/src/drtioaux.rs index e13bde1..c59c851 100644 --- a/src/libboard_artiq/src/drtioaux.rs +++ b/src/libboard_artiq/src/drtioaux.rs @@ -1,4 +1,3 @@ -use core::slice; use crc; use core_io::{ErrorKind as IoErrorKind, Error as IoError}; @@ -59,15 +58,35 @@ fn has_rx_error(linkno: u8) -> bool { } } +fn swap_byte_order(buf: &mut [u8]) -> () { + // for some reason, everything except checksum arrives + // with byte order swapped. and it must be sent as such too. + // call this for a slice without the checksum included. + for i in (0..buf.len()).step_by(4) { + let mut temp = buf[i]; + buf[i] = buf[i + 3]; + buf[i + 3] = temp; + temp = buf[i + 1]; + buf[i + 1] = buf[i + 2]; + buf[i + 2] = temp; + } +} + fn receive(linkno: u8, f: F) -> Result, Error> where F: FnOnce(&[u8]) -> Result { let linkidx = linkno as usize; unsafe { if (DRTIOAUX[linkidx].aux_rx_present_read)() == 1 { - let ptr = DRTIOAUX_MEM[linkidx].base + DRTIOAUX_MEM[linkidx].size / 2; - let len = (DRTIOAUX[linkidx].aux_rx_length_read)(); - let result = f(slice::from_raw_parts(ptr as *mut u8, len as usize)); + let ptr = (DRTIOAUX_MEM[linkidx].base + DRTIOAUX_MEM[linkidx].size / 2) as *mut u8; + let len = (DRTIOAUX[linkidx].aux_rx_length_read)() as usize; + // work buffer, as byte order will need to be swapped, cannot be in place + let mut buf: [u8; 1024] = [0; 1024]; + for i in 0..len { + buf[i] = *(ptr as *mut u8).offset(i as isize); + } + swap_byte_order(&mut buf[0..len-4]); + let result = f(&buf[0..len]); (DRTIOAUX[linkidx].aux_rx_present_write)(1); Ok(Some(result?)) } else { @@ -120,9 +139,14 @@ fn transmit(linkno: u8, f: F) -> Result<(), Error> let linkno = linkno as usize; unsafe { while (DRTIOAUX[linkno].aux_tx_read)() != 0 {} - let ptr = DRTIOAUX_MEM[linkno].base; + let pointer = DRTIOAUX_MEM[linkno].base as *mut u8; let len = DRTIOAUX_MEM[linkno].size / 2; - let len = f(slice::from_raw_parts_mut(ptr as *mut u8, len))?; + // work buffer, works with unaligned mem access + let mut buf: [u8; 1024] = [0; 1024]; + let len = f(&mut buf[0..len])?; + for i in 0..len { + *pointer.offset(i as isize) = buf[i]; + } (DRTIOAUX[linkno].aux_tx_length_write)(len as u16); (DRTIOAUX[linkno].aux_tx_write)(1); Ok(()) @@ -134,7 +158,7 @@ pub fn send(linkno: u8, packet: &Packet) -> Result<(), Error> { let mut writer = Cursor::new(buffer); packet.write_to(&mut writer)?; - + let padding = 4 - (writer.position() % 4); if padding != 4 { for _ in 0..padding { @@ -143,6 +167,8 @@ pub fn send(linkno: u8, packet: &Packet) -> Result<(), Error> { } let checksum = crc::crc32::checksum_ieee(&writer.get_ref()[0..writer.position()]); + let len = writer.position(); + swap_byte_order(&mut writer.get_mut()[0..len]); writer.write_u32(checksum)?; Ok(writer.position())