eth rx: error handling
This commit is contained in:
parent
98947961c6
commit
6757ceb76c
@ -265,8 +265,12 @@ impl<RX, TX> Eth<RX, TX> {
|
||||
.speed(true)
|
||||
.no_broadcast(false)
|
||||
.multi_hash_en(true)
|
||||
// Promiscuous mode
|
||||
// Promiscuous mode (TODO?)
|
||||
.copy_all(true)
|
||||
// Remove 4-byte Frame CheckSum
|
||||
.fcs_remove(true)
|
||||
// One of the slower speeds
|
||||
// TODO: calculate properly
|
||||
.mdc_clk_div(0b110)
|
||||
);
|
||||
|
||||
@ -327,14 +331,73 @@ impl<RX, TX> Eth<RX, TX> {
|
||||
new_self
|
||||
}
|
||||
|
||||
// pub fn start_tx<'tx>(self, tx_buffers: [&'tx [u8]; tx::DESCS]) -> Eth<RX, tx::DescList<'tx>> {
|
||||
// let new_self = Eth {
|
||||
// regs: self.regs,
|
||||
// rx: self.rx,
|
||||
// tx: tx::DescList::new(tx_buffers),
|
||||
// };
|
||||
// let list_addr = &new_self.tx as *const _ as u32;
|
||||
// assert!(list_addr & 0b11 == 0);
|
||||
// new_self.regs.tx_qbar.write(
|
||||
// regs::TxQbar::zeroed()
|
||||
// .tx_q_baseaddr(list_addr >> 2)
|
||||
// );
|
||||
// new_self.regs.net_ctrl.modify(|_, w|
|
||||
// w.tx_en(true)
|
||||
// );
|
||||
// new_self
|
||||
// }
|
||||
|
||||
fn wait_phy_idle(&self) {
|
||||
while !self.regs.net_status.read().phy_mgmt_idle() {}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'rx, TX> Eth<rx::DescList<'rx>, TX> {
|
||||
pub fn recv_next(&mut self) -> Option<rx::PktRef> {
|
||||
self.rx.recv_next()
|
||||
pub fn recv_next(&mut self) -> Result<Option<rx::PktRef>, rx::Error> {
|
||||
let status = self.regs.rx_status.read();
|
||||
if status.hresp_not_ok() {
|
||||
// Clear
|
||||
self.regs.rx_status.write(
|
||||
regs::RxStatus::zeroed()
|
||||
.hresp_not_ok(true)
|
||||
);
|
||||
return Err(rx::Error::HrespNotOk);
|
||||
}
|
||||
if status.rx_overrun() {
|
||||
// Clear
|
||||
self.regs.rx_status.write(
|
||||
regs::RxStatus::zeroed()
|
||||
.rx_overrun(true)
|
||||
);
|
||||
return Err(rx::Error::RxOverrun);
|
||||
}
|
||||
if status.buffer_not_avail() {
|
||||
// Clear
|
||||
self.regs.rx_status.write(
|
||||
regs::RxStatus::zeroed()
|
||||
.buffer_not_avail(true)
|
||||
);
|
||||
return Err(rx::Error::BufferNotAvail);
|
||||
}
|
||||
|
||||
if status.frame_recd() {
|
||||
let result = self.rx.recv_next();
|
||||
match result {
|
||||
Ok(None) => {
|
||||
// No packet, clear status bit
|
||||
self.regs.rx_status.write(
|
||||
regs::RxStatus::zeroed()
|
||||
.frame_recd(true)
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
result
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,14 @@
|
||||
use core::ops::Deref;
|
||||
use crate::{register, register_bit, register_bits, register_bits_typed, regs::*};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
HrespNotOk,
|
||||
RxOverrun,
|
||||
BufferNotAvail,
|
||||
Truncated,
|
||||
}
|
||||
|
||||
/// Descriptor entry
|
||||
#[repr(C)]
|
||||
pub struct DescEntry {
|
||||
@ -44,7 +52,6 @@ impl<'a> DescList<'a> {
|
||||
let last = list.len().min(buffers.len()) - 1;
|
||||
for (i, (entry, buffer)) in list.iter_mut().zip(buffers.iter_mut()).enumerate() {
|
||||
let is_last = i == last;
|
||||
assert!(buffer.len() >= 1536);
|
||||
let buffer_addr = &mut buffer[0] as *mut _ as u32;
|
||||
assert!(buffer_addr & 0b11 == 0);
|
||||
entry.word0.write(
|
||||
@ -69,13 +76,12 @@ impl<'a> DescList<'a> {
|
||||
&self.list[0] as *const _ as u32
|
||||
}
|
||||
|
||||
pub fn recv_next<'s: 'p, 'p>(&'s mut self) -> Option<PktRef<'p>> {
|
||||
pub fn recv_next<'s: 'p, 'p>(&'s mut self) -> Result<Option<PktRef<'p>>, Error> {
|
||||
let list_len = self.list.len();
|
||||
let entry = &mut self.list[self.next];
|
||||
if entry.word0.read().used() {
|
||||
let len = entry.word1.read()
|
||||
.frame_length_lsbs().into();
|
||||
// TODO: check no split pkt across multiple buffers
|
||||
let word1 = entry.word1.read();
|
||||
let len = word1.frame_length_lsbs().into();
|
||||
let buffer = &self.buffers[self.next][0..len];
|
||||
|
||||
self.next += 1;
|
||||
@ -83,9 +89,14 @@ impl<'a> DescList<'a> {
|
||||
self.next = 0;
|
||||
}
|
||||
|
||||
Some(PktRef { entry, buffer })
|
||||
let pkt = PktRef { entry, buffer };
|
||||
if word1.start_of_frame() && word1.end_of_frame() {
|
||||
Ok(Some(pkt))
|
||||
} else {
|
||||
Err(Error::Truncated)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
13
src/main.rs
13
src/main.rs
@ -98,9 +98,16 @@ fn main() {
|
||||
|
||||
loop {
|
||||
match eth.recv_next() {
|
||||
None => {}
|
||||
Some(pkt) => {
|
||||
println!("eth: received {} bytes", pkt.len());
|
||||
Ok(Some(pkt)) => {
|
||||
print!("eth: rx {} bytes", pkt.len());
|
||||
for b in pkt.iter() {
|
||||
print!(" {:02X}", b);
|
||||
}
|
||||
println!("");
|
||||
}
|
||||
Ok(None) => {}
|
||||
Err(e) => {
|
||||
println!("eth rx error: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user