From 3f432fbdc3b41f9d67f248fa96fc37d8638273a4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Jul 2025 12:11:26 +0200 Subject: [PATCH] continue driver impl --- zynq7000-hal/Cargo.toml | 1 + zynq7000-hal/src/eth/embassy_net.rs | 106 ++++++++++++++++++++++++++++ zynq7000-hal/src/eth/mod.rs | 4 +- zynq7000-hal/src/eth/rx_descr.rs | 38 +++++++--- 4 files changed, 136 insertions(+), 13 deletions(-) create mode 100644 zynq7000-hal/src/eth/embassy_net.rs diff --git a/zynq7000-hal/Cargo.toml b/zynq7000-hal/Cargo.toml index abcf44f..b18f943 100644 --- a/zynq7000-hal/Cargo.toml +++ b/zynq7000-hal/Cargo.toml @@ -35,6 +35,7 @@ critical-section = "1" libm = "0.2" log = "0.4" embassy-sync = "0.6" +embassy-net = { path = "../../../Rust/embassy/embassy-net", version = "0.7" } raw-slicee = "0.1" embedded-io-async = "0.6" diff --git a/zynq7000-hal/src/eth/embassy_net.rs b/zynq7000-hal/src/eth/embassy_net.rs new file mode 100644 index 0000000..cf25a7f --- /dev/null +++ b/zynq7000-hal/src/eth/embassy_net.rs @@ -0,0 +1,106 @@ +use embassy_sync::waitqueue::AtomicWaker; + +pub use super::rx_descr; +pub use super::tx_descr; + +static TX_WAKER: AtomicWaker = AtomicWaker::new(); +static RX_WAKER: AtomicWaker = AtomicWaker::new(); + +pub struct EthernetEmbassyNet { + pub eth: super::Ethernet, + pub burst_size: usize, + pub mac_addr: [u8; 6], + pub rx_descr: &'static [rx_descr::Descriptor], + pub rx_index: usize, + pub tx_descr: &'static [tx_descr::Descriptor], + pub tx_index: usize, + pub link_state: embassy_net::driver::LinkState, +} + +pub struct EmbassyNetRxToken { + rx_descr_ref: rx_descr::DescriptorList<'static>, + rx_index: usize, +} + +impl embassy_net::driver::RxToken for EmbassyNetRxToken { + fn consume(self, f: F) -> R + where + F: FnOnce(&mut [u8]) -> R, + { + } +} + +pub struct EmbassyNetTxToken { + tx_descr_ref: tx_descr::DescriptorListRef<'static>, + tx_index: usize, +} + +impl embassy_net::driver::TxToken for EmbassyNetRxToken { + fn consume(self, len: usize, f: F) -> R + where + F: FnOnce(&mut [u8]) -> R, + { + } +} + +impl EthernetEmbassyNet { + #[inline] + pub fn update_link_state(&mut self, link_state: embassy_net::driver::LinkState) { + self.link_state = link_state; + } + + #[inline] + pub fn set_link_state_up(&mut self) { + self.update_link_state(embassy_net::driver::LinkState::Up); + } + + #[inline] + pub fn set_link_state_down(&mut self) { + self.update_link_state(embassy_net::driver::LinkState::Down); + } +} + +impl embassy_net::Driver for EthernetEmbassyNet { + type RxToken<'a> + where + Self: 'a, + = EmbassyNetRxToken; + + type TxToken<'a> + where + Self: 'a, + = EmbassyNetTxToken; + + fn receive( + &mut self, + cx: &mut core::task::Context, + ) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { + RX_WAKER.register(cx.waker()); + } + + fn transmit(&mut self, cx: &mut core::task::Context) -> Option> { + TX_WAKER.register(cx.waker()); + } + + fn link_state(&mut self, cx: &mut core::task::Context) -> embassy_net::driver::LinkState { + self.link_state + } + + fn capabilities(&self) -> embassy_net::driver::Capabilities { + embassy_net::driver::Capabilities { + max_transmission_unit: super::MTU, + max_burst_size: Some(self.burst_size), + checksum: embassy_net::driver::ChecksumCapabilities { + ipv4: true, + udp: true, + tcp: true, + icmpv4: true, + icmpv6: true, + }, + } + } + + fn hardware_address(&self) -> embassy_net::driver::HardwareAddress { + embassy_net::driver::HardwareAddress::Ethernet(self.mac_addr) + } +} diff --git a/zynq7000-hal/src/eth/mod.rs b/zynq7000-hal/src/eth/mod.rs index fa9e795..98ebbcd 100644 --- a/zynq7000-hal/src/eth/mod.rs +++ b/zynq7000-hal/src/eth/mod.rs @@ -1,8 +1,7 @@ use arbitrary_int::{u2, u3}; pub use zynq7000::eth::MdcClkDiv; use zynq7000::eth::{ - BurstLength, DmaRxBufSize, MmioEthernet, SpeedMode, GEM_0_BASE_ADDR, - GEM_1_BASE_ADDR, + BurstLength, DmaRxBufSize, MmioEthernet, SpeedMode, GEM_0_BASE_ADDR, GEM_1_BASE_ADDR, }; pub use ll::{ClkConfig, EthernetLowLevel, Speed}; @@ -11,6 +10,7 @@ pub mod ll; pub mod mdio; pub mod rx_descr; pub mod tx_descr; +pub mod embassy_net; pub const MTU: usize = 1536; pub const MAX_MDC_SPEED: Hertz = Hertz::from_raw(2_500_000); diff --git a/zynq7000-hal/src/eth/rx_descr.rs b/zynq7000-hal/src/eth/rx_descr.rs index 2f2d688..b137f54 100644 --- a/zynq7000-hal/src/eth/rx_descr.rs +++ b/zynq7000-hal/src/eth/rx_descr.rs @@ -1,6 +1,6 @@ //! RX buffer descriptor module. pub use super::shared::Ownership; -use arbitrary_int::{u2, u3, u13, u30}; +use arbitrary_int::{u13, u2, u3, u30}; /// RX buffer descriptor. /// @@ -86,6 +86,11 @@ impl Descriptor { self.word0.set_ownership(ownership); } + #[inline] + pub fn ownership(&self) -> Ownership { + self.word0.ownership() + } + #[inline] pub fn set_wrap_bit(&mut self) { self.word0.set_wrap(true); @@ -104,19 +109,28 @@ impl Default for Descriptor { } } -pub struct DescriptorListRef<'a>(&'a mut [Descriptor]); +pub struct DescriptorList<'a> { + list: &'a mut [Descriptor], + idx: usize, +} -impl<'a> DescriptorListRef<'a> { +impl<'a> DescriptorList<'a> { #[inline] - pub fn new(descriptor: &'a mut [Descriptor]) -> Self { - Self(descriptor) + pub fn new(descr_list: &'a mut [Descriptor]) -> Option { + if descr_list.len() == 0 { + return None; + } + Some(Self { + list: descr_list, + idx: 0, + }) } } -impl DescriptorListRef<'_> { +impl DescriptorList<'_> { #[inline] pub fn base_ptr(&self) -> *const Descriptor { - self.0.as_ptr() + self.list.as_ptr() } #[inline] @@ -125,13 +139,15 @@ impl DescriptorListRef<'_> { } pub fn init(&mut self) { - for desc in self.0.iter_mut() { + self.idx = 0; + for desc in self.list.iter_mut() { desc.set_ownership(Ownership::Hardware); } - self.0.last_mut().unwrap().set_wrap_bit(); + self.list.last_mut().unwrap().set_wrap_bit(); } - pub fn set_rx_buf_address(&mut self, index: usize, addr: u32) { - self.0[index].write_rx_addr(addr); + #[inline] + pub fn set_rx_buf_address(&mut self, index: usize, buf: &[u8]) { + self.list[index].write_rx_addr(addr); } }