1
0
Fork 0

cxp protocol: init

protocol: uncomment error
This commit is contained in:
morgan 2024-09-12 12:20:21 +08:00
parent 12bf931614
commit 98095664ce
2 changed files with 195 additions and 0 deletions

View File

@ -0,0 +1,193 @@
use core_io::{Error as IoError, Write};
use crc::crc32;
use embedded_hal::prelude::_embedded_hal_blocking_delay_DelayUs;
use io::Cursor;
use libboard_zynq::{println, timer::GlobalTimer};
use crate::pl::csr;
const MAX_PACKET: usize = 128;
const DATA_MAXSIZE: usize = /*max size*/MAX_PACKET - /*Tag*/4 - /*Op code & length*/4 - /*addr*/4 - /*CRC*/4 ;
#[derive(Debug)]
pub enum Error {
BufferError,
LinkDown,
}
impl From<IoError> for Error {
fn from(_: IoError) -> Error {
Error::BufferError
}
}
pub enum Packet {
CtrlRead {
addr: u32,
length: u8,
},
CtrlWrite {
addr: u32,
length: u8,
data: [u8; DATA_MAXSIZE],
}, // max register size is 8 bytes
CtrlReadWithTag {
tag: u8,
addr: u32,
length: u8,
},
CtrlWriteWithTag {
tag: u8,
addr: u32,
length: u8,
data: [u8; DATA_MAXSIZE],
}, // max register size is 8 bytes
EventAck {
packet_tag: u8,
},
TestPacket,
}
impl Packet {
pub fn write_to(&self, writer: &mut Cursor<&mut [u8]>) -> Result<(), Error> {
// CoaXpress use big endian
match *self {
Packet::CtrlRead { addr, length } => {
writer.write(&[0x02; 4])?;
writer.write(&[0x00, 0x00, 0x00, length])?;
writer.write(&addr.to_be_bytes())?;
}
Packet::CtrlWrite { addr, length, data } => {
writer.write(&[0x02; 4])?;
writer.write(&[0x01, 0x00, 0x00, length])?;
writer.write(&addr.to_be_bytes())?;
writer.write(&data[0..length as usize])?;
}
Packet::CtrlReadWithTag { tag, addr, length } => {
writer.write(&[0x05; 4])?;
writer.write(&[tag; 4])?;
writer.write(&[0x00, 0x00, 0x00, length])?;
writer.write(&addr.to_be_bytes())?;
}
Packet::CtrlWriteWithTag {
tag,
addr,
length,
data,
} => {
writer.write(&[0x05; 4])?;
writer.write(&[tag; 4])?;
writer.write(&[0x01, 0x00, 0x00, length])?;
writer.write(&addr.to_be_bytes())?;
writer.write(&data[0..length as usize])?;
}
Packet::EventAck { packet_tag } => {
writer.write(&[0x08; 4])?;
writer.write(&[packet_tag; 4])?;
}
_ => {}
}
// 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
match *self {
Packet::CtrlRead { .. }
| Packet::CtrlWrite { .. }
| Packet::CtrlReadWithTag { .. }
| Packet::CtrlWriteWithTag { .. } => {
let checksum = crc32::checksum_ieee(&writer.get_ref()[4..writer.position()]);
writer.write(&(!checksum).to_le_bytes())?;
}
_ => {}
}
Ok(())
}
}
pub fn send(packet: &Packet) -> Result<(), Error> {
if unsafe { csr::cxp::upconn_tx_enable_read() } == 0 {
Err(Error::LinkDown)?
}
match *packet {
Packet::TestPacket => send_test_packet(),
_ => send_data_packet(packet),
}
}
fn send_data_packet(packet: &Packet) -> Result<(), Error> {
let mut buffer: [u8; MAX_PACKET] = [0; MAX_PACKET];
let mut writer = Cursor::new(&mut buffer[..]);
packet.write_to(&mut writer)?;
unsafe {
let len = writer.position();
csr::cxp::upconn_command_len_write(len as u8);
for data in writer.get_ref()[..len].iter() {
while csr::cxp::upconn_command_writeable_read() == 0 {}
csr::cxp::upconn_command_data_write(*data);
}
}
Ok(())
}
fn send_test_packet() -> Result<(), Error> {
unsafe {
while csr::cxp::upconn_tx_busy_read() == 1 {}
csr::cxp::upconn_tx_testmode_en_write(1);
// timer.delay_us(2);
csr::cxp::upconn_testseq_stb_write(1);
while csr::cxp::upconn_testseq_busy_read() == 1 {}
csr::cxp::upconn_tx_testmode_en_write(0);
}
Ok(())
}
pub fn write_u32(addr: u32, data: u32) -> Result<(), Error> {
let mut data_slice: [u8; DATA_MAXSIZE] = [0; DATA_MAXSIZE];
data_slice[..4].clone_from_slice(&data.to_be_bytes());
send(&Packet::CtrlWrite {
addr,
length: 4,
data: data_slice,
})?;
Ok(())
}
pub fn read_u32(addr: u32) -> Result<(), Error> {
send(&Packet::CtrlRead { addr, length: 4 })?;
Ok(())
}
pub fn write_u64(addr: u32, data: u64) -> Result<(), Error> {
let mut data_slice: [u8; DATA_MAXSIZE] = [0; DATA_MAXSIZE];
data_slice[..8].clone_from_slice(&data.to_be_bytes());
send(&Packet::CtrlWrite {
addr,
length: 8,
data: data_slice,
})?;
Ok(())
}
// DEBUG: use only
pub fn print_packet(pak: &[u8]) {
println!("pak = [");
for i in 0..(pak.len() / 4) {
println!(
"{:#03} {:#04X} {:#04X} {:#04X} {:#04X},",
i + 1,
pak[i * 4],
pak[i * 4 + 1],
pak[i * 4 + 2],
pak[i * 4 + 3]
)
}
println!("]");
println!("============================================");
}

View File

@ -47,6 +47,8 @@ pub mod cxp_downconn;
#[cfg(has_cxp)] #[cfg(has_cxp)]
pub mod cxp_upconn; pub mod cxp_upconn;
pub mod cxp_proto;
pub fn identifier_read(buf: &mut [u8]) -> &str { pub fn identifier_read(buf: &mut [u8]) -> &str {
unsafe { unsafe {
pl::csr::identifier::address_write(0); pl::csr::identifier::address_write(0);