start adding smoltcp/ethernet support
This commit is contained in:
parent
61ffe06343
commit
b8fdf1008b
@ -10,13 +10,13 @@ use embedded_hal::{delay::DelayNs, digital::StatefulOutputPin};
|
|||||||
use embedded_io::Write;
|
use embedded_io::Write;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use zynq7000_hal::{
|
use zynq7000_hal::{
|
||||||
|
BootMode,
|
||||||
clocks::Clocks,
|
clocks::Clocks,
|
||||||
gic::{GicConfigurator, GicInterruptHelper, Interrupt},
|
gic::{GicConfigurator, GicInterruptHelper, Interrupt},
|
||||||
gpio::{mio, Flex, Output, PinState},
|
gpio::{Flex, Output, PinState, mio},
|
||||||
gtc::Gtc,
|
gtc::Gtc,
|
||||||
time::Hertz,
|
time::Hertz,
|
||||||
uart::{ClkConfigRaw, Uart, UartConfig},
|
uart::{ClkConfigRaw, Uart, UartConfig},
|
||||||
BootMode,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use zynq7000::PsPeripherals;
|
use zynq7000::PsPeripherals;
|
||||||
|
@ -14,6 +14,7 @@ categories = ["embedded", "no-std", "hardware-support"]
|
|||||||
cortex-ar = { git = "https://github.com/rust-embedded/cortex-ar", branch = "main" }
|
cortex-ar = { git = "https://github.com/rust-embedded/cortex-ar", branch = "main" }
|
||||||
zynq7000 = { path = "../zynq7000" }
|
zynq7000 = { path = "../zynq7000" }
|
||||||
|
|
||||||
|
bitbybit = "1.3"
|
||||||
arbitrary-int = "1.3"
|
arbitrary-int = "1.3"
|
||||||
thiserror = { version = "2", default-features = false }
|
thiserror = { version = "2", default-features = false }
|
||||||
num_enum = { version = "0.7", default-features = false }
|
num_enum = { version = "0.7", default-features = false }
|
||||||
|
72
zynq7000-hal/src/eth/mod.rs
Normal file
72
zynq7000-hal/src/eth/mod.rs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
use arbitrary_int::{u2, u3, u13, u30};
|
||||||
|
|
||||||
|
/// RX buffer descriptor.
|
||||||
|
///
|
||||||
|
/// The user should declare an array of this structure inside uncached memory.
|
||||||
|
///
|
||||||
|
/// These descriptors are shared between software and hardware and contain information
|
||||||
|
/// related to frame reception.
|
||||||
|
pub struct RxBufDescr {
|
||||||
|
/// The first word of the descriptor.
|
||||||
|
pub word0: RxBufDescrWord0,
|
||||||
|
/// The second word of the descriptor.
|
||||||
|
pub word1: RxBufDescrWord1,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub enum Ownership {
|
||||||
|
Hardware = 0,
|
||||||
|
Software = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub struct RxBufDescrWord0 {
|
||||||
|
/// The full reception address with the last two bits cleared.
|
||||||
|
#[bits(2..=31, rw)]
|
||||||
|
addr: u30,
|
||||||
|
#[bit(1, rw)]
|
||||||
|
wrap: bool,
|
||||||
|
#[bit(1, rw)]
|
||||||
|
ownership: Ownership,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub struct RxBufDescrWord1 {
|
||||||
|
#[bit(31, r)]
|
||||||
|
broadcast_detect: bool,
|
||||||
|
#[bit(30, r)]
|
||||||
|
multicast_hash: bool,
|
||||||
|
#[bit(29, r)]
|
||||||
|
unicast_hash: bool,
|
||||||
|
#[bit(27, r)]
|
||||||
|
specific_addr_match: bool,
|
||||||
|
/// Specifies which of the 4 specific address registers was matched.
|
||||||
|
#[bits(25..=26, r)]
|
||||||
|
specific_addr_match_info: u2,
|
||||||
|
#[bit(24, r)]
|
||||||
|
type_id_match_or_snap_info: bool,
|
||||||
|
#[bits(22..=23, r)]
|
||||||
|
type_id_match_info_or_chksum_status: u2,
|
||||||
|
#[bit(21, r)]
|
||||||
|
vlan_tag_detected: bool,
|
||||||
|
#[bit(20, r)]
|
||||||
|
priority_tag_detected: bool,
|
||||||
|
#[bits(17..=19, r)]
|
||||||
|
vlan_prio: u3,
|
||||||
|
#[bit(16, r)]
|
||||||
|
cfi_bit: bool,
|
||||||
|
#[bit(15, r)]
|
||||||
|
end_of_frame: bool,
|
||||||
|
#[bit(14, r)]
|
||||||
|
start_of_frame: bool,
|
||||||
|
/// Relevant when FCS errors are not ignored.
|
||||||
|
/// 0: Frame has good FCS, 1: Frame has bad FCS, but was copied to memory as the ignore FCS
|
||||||
|
/// functionality was enabled.
|
||||||
|
#[bit(13, r)]
|
||||||
|
fcs_status: bool,
|
||||||
|
#[bits(0..=12, r)]
|
||||||
|
rx_len: u13,
|
||||||
|
}
|
@ -4,7 +4,7 @@ use zynq7000::gpio::{Gpio, MaskedOutput, MmioGpio};
|
|||||||
|
|
||||||
use crate::slcr::Slcr;
|
use crate::slcr::Slcr;
|
||||||
|
|
||||||
use super::{mio::MuxConf, PinIsOutputOnly};
|
use super::{PinIsOutputOnly, mio::MuxConf};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum PinOffset {
|
pub enum PinOffset {
|
||||||
|
@ -172,7 +172,8 @@ impl Flex {
|
|||||||
|
|
||||||
pub fn configure_as_output_open_drain(&mut self, level: PinState, with_internal_pullup: bool) {
|
pub fn configure_as_output_open_drain(&mut self, level: PinState, with_internal_pullup: bool) {
|
||||||
self.mode = PinMode::OutputOpenDrain;
|
self.mode = PinMode::OutputOpenDrain;
|
||||||
self.ll.configure_as_output_open_drain(level, with_internal_pullup);
|
self.ll
|
||||||
|
.configure_as_output_open_drain(level, with_internal_pullup);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the pin is configured as an input pin, this function does nothing.
|
/// If the pin is configured as an input pin, this function does nothing.
|
||||||
|
@ -13,6 +13,7 @@ use slcr::Slcr;
|
|||||||
use zynq7000::slcr::LevelShifterReg;
|
use zynq7000::slcr::LevelShifterReg;
|
||||||
|
|
||||||
pub mod clocks;
|
pub mod clocks;
|
||||||
|
pub mod eth;
|
||||||
pub mod gic;
|
pub mod gic;
|
||||||
pub mod gpio;
|
pub mod gpio;
|
||||||
pub mod gtc;
|
pub mod gtc;
|
||||||
|
580
zynq7000/src/eth.rs
Normal file
580
zynq7000/src/eth.rs
Normal file
@ -0,0 +1,580 @@
|
|||||||
|
use arbitrary_int::{u2, u5};
|
||||||
|
|
||||||
|
pub const GEM_0_BASE_ADDR: usize = 0xE000_B000;
|
||||||
|
pub const GEM_1_BASE_ADDR: usize = 0xE000_C000;
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NetworkControl {
|
||||||
|
#[bit(18, w)]
|
||||||
|
flush_next_rx_dpram_pkt: bool,
|
||||||
|
#[bit(17, w)]
|
||||||
|
tx_pfc_pri_pause_frame: bool,
|
||||||
|
#[bit(16, w)]
|
||||||
|
enable_pfc_pri_pause_rx: bool,
|
||||||
|
#[bit(12, w)]
|
||||||
|
zero_pause_tx: bool,
|
||||||
|
#[bit(11, w)]
|
||||||
|
pause_tx: bool,
|
||||||
|
#[bit(10, w)]
|
||||||
|
stop_tx: bool,
|
||||||
|
#[bit(9, w)]
|
||||||
|
start_tx: bool,
|
||||||
|
#[bit(8, rw)]
|
||||||
|
back_pressure: bool,
|
||||||
|
#[bit(7, rw)]
|
||||||
|
statistics_write_enable: bool,
|
||||||
|
#[bit(6, w)]
|
||||||
|
increment_statistics: bool,
|
||||||
|
#[bit(5, w)]
|
||||||
|
clear_statistics: bool,
|
||||||
|
#[bit(4, rw)]
|
||||||
|
management_port_enable: bool,
|
||||||
|
#[bit(3, rw)]
|
||||||
|
tx_enable: bool,
|
||||||
|
#[bit(2, rw)]
|
||||||
|
rx_enable: bool,
|
||||||
|
#[bit(1, rw)]
|
||||||
|
loopback_local: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub enum SpeedMode {
|
||||||
|
Low10Mbps = 0,
|
||||||
|
High100Mbps = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub enum PcsSelect {
|
||||||
|
GmiiMii = 0,
|
||||||
|
Tbi = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitenum(u3, exhaustive = true)]
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub enum MdcClkDiv {
|
||||||
|
Div8 = 0,
|
||||||
|
Div16 = 1,
|
||||||
|
Div32 = 2,
|
||||||
|
Div48 = 3,
|
||||||
|
Div64 = 4,
|
||||||
|
Div96 = 5,
|
||||||
|
Div128 = 6,
|
||||||
|
Div224 = 7,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MdcClkDiv {
|
||||||
|
pub fn divisor(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
MdcClkDiv::Div8 => 8,
|
||||||
|
MdcClkDiv::Div16 => 16,
|
||||||
|
MdcClkDiv::Div32 => 32,
|
||||||
|
MdcClkDiv::Div48 => 48,
|
||||||
|
MdcClkDiv::Div64 => 64,
|
||||||
|
MdcClkDiv::Div96 => 96,
|
||||||
|
MdcClkDiv::Div128 => 128,
|
||||||
|
MdcClkDiv::Div224 => 224,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NetworkConfig {
|
||||||
|
#[bit(30, rw)]
|
||||||
|
ignore_ipg_rx_error: bool,
|
||||||
|
#[bit(29, rw)]
|
||||||
|
allow_bad_preamble: bool,
|
||||||
|
#[bit(28, rw)]
|
||||||
|
ipg_stretch_enable: bool,
|
||||||
|
#[bit(27, rw)]
|
||||||
|
sgmii_enable: bool,
|
||||||
|
#[bit(26, rw)]
|
||||||
|
ignore_rx_fcs: bool,
|
||||||
|
#[bit(25, rw)]
|
||||||
|
half_duplex_rx_enable: bool,
|
||||||
|
#[bit(24, rw)]
|
||||||
|
rx_checksum_enable: bool,
|
||||||
|
#[bit(23, rw)]
|
||||||
|
disable_copy_pause_frames: bool,
|
||||||
|
/// Zynq defines this as 0b00 for 32-bit AMBA AHB data bus width.
|
||||||
|
#[bits(21..=22, r)]
|
||||||
|
dbus_width: u2,
|
||||||
|
#[bits(18..=20, rw)]
|
||||||
|
mdc_clk_div: MdcClkDiv,
|
||||||
|
#[bit(17, rw)]
|
||||||
|
fcs_removal: bool,
|
||||||
|
#[bit(16, rw)]
|
||||||
|
length_field_error_discard: bool,
|
||||||
|
#[bits(14..=15, rw)]
|
||||||
|
rx_buf_offset: u2,
|
||||||
|
#[bit(13, rw)]
|
||||||
|
pause_enable: bool,
|
||||||
|
#[bit(12, rw)]
|
||||||
|
retry_test_enable: bool,
|
||||||
|
#[bit(11, rw)]
|
||||||
|
pcs_select: PcsSelect,
|
||||||
|
#[bit(10, rw)]
|
||||||
|
gigabit_enable: bool,
|
||||||
|
#[bit(9, rw)]
|
||||||
|
ext_addr_match_enable: bool,
|
||||||
|
#[bit(8, rw)]
|
||||||
|
rx_enable_1536: bool,
|
||||||
|
#[bit(7, rw)]
|
||||||
|
unicast_hash_enable: bool,
|
||||||
|
#[bit(6, rw)]
|
||||||
|
multicast_hash_enable: bool,
|
||||||
|
#[bit(5, rw)]
|
||||||
|
no_broadcast: bool,
|
||||||
|
#[bit(4, rw)]
|
||||||
|
copy_all_frames: bool,
|
||||||
|
#[bit(2, rw)]
|
||||||
|
discard_non_vlan: bool,
|
||||||
|
#[bit(1, rw)]
|
||||||
|
full_duplex: bool,
|
||||||
|
#[bit(0, rw)]
|
||||||
|
speed_mode: SpeedMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// PHY management status information.
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NetworkStatus {
|
||||||
|
#[bit(6, r)]
|
||||||
|
pfc_pri_pause_neg: bool,
|
||||||
|
#[bit(5, r)]
|
||||||
|
pcs_autoneg_pause_tx_res: bool,
|
||||||
|
#[bit(4, r)]
|
||||||
|
pcs_autoneg_pause_rx_res: bool,
|
||||||
|
#[bit(3, r)]
|
||||||
|
pcs_autoneg_dup_res: bool,
|
||||||
|
#[bit(2, r)]
|
||||||
|
phy_mgmt_idle: bool,
|
||||||
|
#[bit(1, r)]
|
||||||
|
mdio_in: bool,
|
||||||
|
#[bit(0, r)]
|
||||||
|
pcs_link_state: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum BurstLength {
|
||||||
|
Single,
|
||||||
|
#[default]
|
||||||
|
Incr4,
|
||||||
|
Incr8,
|
||||||
|
Incr16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BurstLength {
|
||||||
|
pub const fn reg_value(&self) -> u5 {
|
||||||
|
u5::new(match self {
|
||||||
|
BurstLength::Single => 0b1,
|
||||||
|
BurstLength::Incr4 => 0b100,
|
||||||
|
BurstLength::Incr8 => 0b1000,
|
||||||
|
BurstLength::Incr16 => 0b10000,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub enum AhbEndianess {
|
||||||
|
Little = 0,
|
||||||
|
Big = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub struct DmaRxBufSize(u8);
|
||||||
|
|
||||||
|
impl DmaRxBufSize {
|
||||||
|
pub const fn new_with_raw_value(size: u8) -> Self {
|
||||||
|
Self(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn new(size: u8) -> Option<Self> {
|
||||||
|
if size == 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(Self(size))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn raw_value(&self) -> u8 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn size_in_bytes(&self) -> usize {
|
||||||
|
self.0 as usize * 64
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn reg_value(&self) -> u8 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DmaConfig {
|
||||||
|
#[bit(24, rw)]
|
||||||
|
discard_when_ahb_full: bool,
|
||||||
|
/// DMA receive buffer size in AHB system memory.
|
||||||
|
#[bits(16..=23, rw)]
|
||||||
|
dma_rx_ahb_buf_size_sel: DmaRxBufSize,
|
||||||
|
#[bit(11, rw)]
|
||||||
|
chksum_offload_enable: bool,
|
||||||
|
/// Select size for packet buffer SRAM. Should be set to 1 to use the full configurable address
|
||||||
|
/// space of 4 kB for the packet buffer.
|
||||||
|
#[bit(10, rw)]
|
||||||
|
tx_packet_buf_size_sel: bool,
|
||||||
|
/// Select size for packet buffer SRAM. Should be set to 0b11 to use the full configurable
|
||||||
|
/// address space of 8 kB for the packet buffer.
|
||||||
|
#[bits(8..=9, rw)]
|
||||||
|
rx_packet_buf_size_sel: u2,
|
||||||
|
/// Default value is 0x1 (big endian)
|
||||||
|
#[bit(7, rw)]
|
||||||
|
endian_swap_packet_data: AhbEndianess,
|
||||||
|
#[bit(6, rw)]
|
||||||
|
endian_swap_mgmt_descriptor: AhbEndianess,
|
||||||
|
#[bits(0..=4, rw)]
|
||||||
|
burst_length: u5,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TxStatus {
|
||||||
|
#[bit(8, rw)]
|
||||||
|
hresp_not_ok: bool,
|
||||||
|
#[bit(7, rw)]
|
||||||
|
late_collision: bool,
|
||||||
|
#[bit(6, rw)]
|
||||||
|
tx_underrun: bool,
|
||||||
|
#[bit(5, rw)]
|
||||||
|
tx_complete: bool,
|
||||||
|
#[bit(4, rw)]
|
||||||
|
tx_frame_corruption_ahb_error: bool,
|
||||||
|
#[bit(3, r)]
|
||||||
|
tx_go: bool,
|
||||||
|
#[bit(2, rw)]
|
||||||
|
retry_limit_reached: bool,
|
||||||
|
#[bit(1, rw)]
|
||||||
|
collision: bool,
|
||||||
|
#[bit(0, rw)]
|
||||||
|
read_when_used: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RxStatus {
|
||||||
|
#[bit(3, rw)]
|
||||||
|
hresp_not_ok: bool,
|
||||||
|
#[bit(2, rw)]
|
||||||
|
rx_overrun: bool,
|
||||||
|
#[bit(1, rw)]
|
||||||
|
frame_received: bool,
|
||||||
|
#[bit(0, rw)]
|
||||||
|
buf_not_available: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct InterruptStatus {
|
||||||
|
#[bit(26, rw)]
|
||||||
|
tsu_sec_incr: bool,
|
||||||
|
/// Marked N/A in datasheet.
|
||||||
|
#[bit(17, rw)]
|
||||||
|
partner_pg_rx: bool,
|
||||||
|
/// Marked N/A in datasheet.
|
||||||
|
#[bit(16, rw)]
|
||||||
|
auto_negotiation_complete: bool,
|
||||||
|
#[bit(15, rw)]
|
||||||
|
external_interrupt: bool,
|
||||||
|
#[bit(14, rw)]
|
||||||
|
pause_transmitted: bool,
|
||||||
|
#[bit(13, rw)]
|
||||||
|
pause_time_zero: bool,
|
||||||
|
#[bit(12, rw)]
|
||||||
|
pause_with_non_zero_quantum: bool,
|
||||||
|
#[bit(11, rw)]
|
||||||
|
hresp_not_ok: bool,
|
||||||
|
#[bit(10, rw)]
|
||||||
|
rx_overrun: bool,
|
||||||
|
/// Marked N/A in datasheet.
|
||||||
|
#[bit(9, rw)]
|
||||||
|
link_changed: bool,
|
||||||
|
#[bit(7, r)]
|
||||||
|
tx_complete: bool,
|
||||||
|
/// Cleared on read.
|
||||||
|
#[bit(6, r)]
|
||||||
|
tx_frame_corruption_ahb_error: bool,
|
||||||
|
#[bit(5, rw)]
|
||||||
|
retry_limit_reached: bool,
|
||||||
|
#[bit(3, rw)]
|
||||||
|
tx_descr_read_when_used: bool,
|
||||||
|
#[bit(2, rw)]
|
||||||
|
rx_descr_read_when_used: bool,
|
||||||
|
#[bit(1, rw)]
|
||||||
|
frame_received: bool,
|
||||||
|
#[bit(0, rw)]
|
||||||
|
mgmt_frame_sent: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct InterruptControl {
|
||||||
|
#[bit(26, w)]
|
||||||
|
tsu_sec_incr: bool,
|
||||||
|
/// Marked N/A in datasheet.
|
||||||
|
#[bit(17, w)]
|
||||||
|
partner_pg_rx: bool,
|
||||||
|
/// Marked N/A in datasheet.
|
||||||
|
#[bit(16, w)]
|
||||||
|
auto_negotiation_complete: bool,
|
||||||
|
#[bit(15, w)]
|
||||||
|
external_interrupt: bool,
|
||||||
|
#[bit(14, w)]
|
||||||
|
pause_transmitted: bool,
|
||||||
|
#[bit(13, w)]
|
||||||
|
pause_time_zero: bool,
|
||||||
|
#[bit(12, w)]
|
||||||
|
pause_with_non_zero_quantum: bool,
|
||||||
|
#[bit(11, w)]
|
||||||
|
hresp_not_ok: bool,
|
||||||
|
#[bit(10, w)]
|
||||||
|
rx_overrun: bool,
|
||||||
|
/// Marked N/A in datasheet.
|
||||||
|
#[bit(9, w)]
|
||||||
|
link_changed: bool,
|
||||||
|
#[bit(7, w)]
|
||||||
|
tx_complete: bool,
|
||||||
|
/// Cleared on read.
|
||||||
|
#[bit(6, w)]
|
||||||
|
tx_frame_corruption_ahb_error: bool,
|
||||||
|
#[bit(5, w)]
|
||||||
|
retry_limit_reached: bool,
|
||||||
|
#[bit(3, w)]
|
||||||
|
tx_descr_read_when_used: bool,
|
||||||
|
#[bit(2, w)]
|
||||||
|
rx_descr_read_when_used: bool,
|
||||||
|
#[bit(1, w)]
|
||||||
|
frame_received: bool,
|
||||||
|
#[bit(0, w)]
|
||||||
|
mgmt_frame_sent: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitenum(u2, exhaustive = false)]
|
||||||
|
pub enum PhyOperation {
|
||||||
|
Read = 0b10,
|
||||||
|
Write = 0b01,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PhyMaintenance {
|
||||||
|
/// Must be 1 for Clause 22 operations.
|
||||||
|
#[bit(30, rw)]
|
||||||
|
clause_22: bool,
|
||||||
|
#[bits(28..=29, rw)]
|
||||||
|
op: Option<PhyOperation>,
|
||||||
|
#[bits(23..=27, rw)]
|
||||||
|
phy_addr: u5,
|
||||||
|
#[bits(18..=22, rw)]
|
||||||
|
reg_addr: u5,
|
||||||
|
#[bits(16..=17, rw)]
|
||||||
|
must_be_10: u2,
|
||||||
|
#[bits(0..=15, rw)]
|
||||||
|
data_mask: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PauseQuantum {
|
||||||
|
#[bits(0..=15, rw)]
|
||||||
|
value: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct MatchRegister {
|
||||||
|
#[bit(31, rw)]
|
||||||
|
copy_enable: bool,
|
||||||
|
#[bits(0..=15, rw)]
|
||||||
|
type_id: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gigabit Ethernet Controller (GEM) registers for Zynq-7000
|
||||||
|
#[derive(derive_mmio::Mmio)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Ethernet {
|
||||||
|
net_ctrl: NetworkControl,
|
||||||
|
net_cfg: NetworkConfig,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
net_status: NetworkStatus,
|
||||||
|
_reserved0: u32,
|
||||||
|
dma_cfg: DmaConfig,
|
||||||
|
tx_status: TxStatus,
|
||||||
|
rx_buf_queue_base_addr: u32,
|
||||||
|
tx_buf_queue_base_addr: u32,
|
||||||
|
rx_status: RxStatus,
|
||||||
|
interrupt_status: InterruptStatus,
|
||||||
|
interrupt_enable: InterruptControl,
|
||||||
|
interrupt_disable: InterruptControl,
|
||||||
|
interrupt_mask: InterruptStatus,
|
||||||
|
phy_maintenance: PhyMaintenance,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_pause_quantum: PauseQuantum,
|
||||||
|
tx_pause_quantum: PauseQuantum,
|
||||||
|
_reserved1: [u32; 0x10],
|
||||||
|
hash_low: u32,
|
||||||
|
hash_high: u32,
|
||||||
|
addr1_low: u32,
|
||||||
|
addr1_high: u32,
|
||||||
|
addr2_low: u32,
|
||||||
|
addr2_high: u32,
|
||||||
|
addr3_low: u32,
|
||||||
|
addr3_high: u32,
|
||||||
|
addr4_low: u32,
|
||||||
|
addr4_high: u32,
|
||||||
|
match_reg: [MatchRegister; 4],
|
||||||
|
wake_on_lan: u32,
|
||||||
|
ipg_stretch: u32,
|
||||||
|
stacked_vlan: u32,
|
||||||
|
tx_pfc: u32,
|
||||||
|
addr1_mask_low: u32,
|
||||||
|
addr1_mask_high: u32,
|
||||||
|
_reserved2: [u32; 0x0B],
|
||||||
|
/// Should be 0x20118.
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
module_id: u32,
|
||||||
|
#[mmio(inner)]
|
||||||
|
statistics: Statistics,
|
||||||
|
_reserved3: [u32; 0x34],
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
design_cfg_2: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
design_cfg_3: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
design_cfg_4: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
design_cfg_5: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assertions::const_assert_eq!(core::mem::size_of::<Ethernet>(), 0x294);
|
||||||
|
|
||||||
|
/// GEM statistics registers
|
||||||
|
#[derive(derive_mmio::Mmio)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Statistics {
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
tx_octets_low: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
tx_octets_high: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
tx_count: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
tx_broadcast: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
tx_multicast: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
tx_pause: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
tx_64_bits: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
tx_65_to_127_bits: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
tx_128_to_255_bits: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
tx_256_to_511_bits: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
tx_512_to_1023_bits: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
tx_1024_to_1518_bits: u32,
|
||||||
|
_reserved0: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
tx_underruns: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
single_collision_frames: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
multi_collision_frames: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
excessive_collisions: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
late_collisions: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
deferred_tx: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
carrier_sense_errors: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_octets_low: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_octets_high: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_count: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_broadcast: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_multicast: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_pause: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_64_bits: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_65_to_127_bits: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_128_to_255_bits: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_256_to_511_bits: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_512_to_1023_bits: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_1024_to_1518_bits: u32,
|
||||||
|
_reserved1: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_undersize: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_oversize: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_jabber: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_frame_check_sequence_errors: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_length_field_errors: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_symbol_errors: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_alignment_errors: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_resource_errors: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_overrun_errors: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_ip_header_checksum_errors: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_tcp_checksum_errors: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
rx_udp_checksum_errors: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ethernet {
|
||||||
|
/// Create a new Gigabit Ethernet MMIO instance for GEM 0 at address [GEM_0_BASE_ADDR].
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||||
|
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||||
|
/// interfere with each other.
|
||||||
|
pub const unsafe fn new_mmio_fixed_0() -> MmioEthernet<'static> {
|
||||||
|
unsafe { Self::new_mmio_at(GEM_0_BASE_ADDR) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new Gigabit Ethernet MMIO instance for GEM 1 at address [GEM_1_BASE_ADDR].
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||||
|
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||||
|
/// interfere with each other.
|
||||||
|
pub const unsafe fn new_mmio_fixed_1() -> MmioEthernet<'static> {
|
||||||
|
unsafe { Self::new_mmio_at(GEM_1_BASE_ADDR) }
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ extern crate std;
|
|||||||
|
|
||||||
pub const MPCORE_BASE_ADDR: usize = 0xF8F0_0000;
|
pub const MPCORE_BASE_ADDR: usize = 0xF8F0_0000;
|
||||||
|
|
||||||
|
pub mod eth;
|
||||||
pub mod gic;
|
pub mod gic;
|
||||||
pub mod gpio;
|
pub mod gpio;
|
||||||
pub mod gtc;
|
pub mod gtc;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user