continue, update MMU handling

This commit is contained in:
2025-05-30 11:46:13 +02:00
parent d0d0d48780
commit b8bb7e23c7
15 changed files with 4278 additions and 4222 deletions

View File

@ -13,6 +13,7 @@ categories = ["embedded", "no-std", "hardware-support"]
[dependencies]
cortex-ar = { git = "https://github.com/rust-embedded/cortex-ar", branch = "main" }
zynq7000 = { path = "../zynq7000" }
zynq-mmu = { path = "../zynq-mmu", version = "0.1.0" }
bitbybit = "1.3"
arbitrary-int = "1.3"

View File

@ -169,8 +169,11 @@ impl EthernetLowLevel {
}
#[inline]
pub fn configure_mdc_clk_div() {
// TODO:
pub fn set_promiscous_mode(&mut self, enable: bool) {
self.regs.modify_net_cfg(|mut val| {
val.set_copy_all_frames(enable);
val
});
}
/// Performs initialization according to TRM p.541.

View File

@ -1,6 +1,9 @@
use arbitrary_int::u3;
use arbitrary_int::{u2, u3};
pub use zynq7000::eth::MdcClkDiv;
use zynq7000::eth::{MmioEthernet, SpeedMode, GEM_0_BASE_ADDR, GEM_1_BASE_ADDR};
use zynq7000::eth::{
BurstLength, DmaRxBufSize, MmioEthernet, NetworkConfig, SpeedMode, GEM_0_BASE_ADDR,
GEM_1_BASE_ADDR,
};
pub use ll::{ClkConfig, EthernetLowLevel};
@ -9,6 +12,8 @@ pub mod mdio;
pub mod rx_descr;
pub mod tx_descr;
const MTU: usize = 1536;
#[cfg(not(feature = "7z010-7z007s-clg225"))]
use crate::gpio::mio::{
Mio16, Mio17, Mio18, Mio19, Mio20, Mio21, Mio22, Mio23, Mio24, Mio25, Mio26, Mio27,
@ -198,6 +203,23 @@ impl RxData3 for Pin<Mio38> {
const ETH_ID: EthernetId = EthernetId::Eth1;
}
#[derive(Debug, Clone, Copy)]
pub struct EthernetConfig {
pub clk_config: ClkConfig,
pub mdc_clk_div: MdcClkDiv,
pub mac_address: [u8; 6],
}
impl EthernetConfig {
pub fn new(clk_config: ClkConfig, mdc_clk_div: MdcClkDiv, mac_address: [u8; 6]) -> Self {
Self {
clk_config,
mdc_clk_div,
mac_address,
}
}
}
pub struct Ethernet {
ll: ll::EthernetLowLevel,
mdio: mdio::Mdio,
@ -222,8 +244,7 @@ impl Ethernet {
MdIoPin: MdIo,
>(
mut ll: ll::EthernetLowLevel,
clk_config: ll::ClkConfig,
mdc_clk_div: MdcClkDiv,
config: EthernetConfig,
tx_clk: TxClkPin,
tx_ctrl: TxCtrlPin,
tx_data: (TxData0Pin, TxData1Pin, TxData2Pin, TxData3Pin),
@ -232,7 +253,7 @@ impl Ethernet {
rx_data: (RxData0Pin, RxData1Pin, RxData2Pin, RxData3Pin),
md_pins: Option<(MdClkPin, MdIoPin)>,
) -> Self {
Self::common_init(&mut ll);
Self::common_init(&mut ll, config.mac_address);
let tx_mio_config = zynq7000::slcr::mio::Config::builder()
.with_disable_hstl_rcvr(true)
.with_pullup(true)
@ -348,30 +369,53 @@ impl Ethernet {
});
});
}
ll.configure_clock(clk_config);
ll.configure_clock(config.clk_config);
let mut mdio = mdio::Mdio::new(&ll, true);
mdio.configure_clock_div(mdc_clk_div);
mdio.configure_clock_div(config.mdc_clk_div);
Ethernet { ll, mdio }
}
pub fn new(mut ll: EthernetLowLevel, clk_config: ClkConfig, mdc_clk_div: MdcClkDiv) -> Self {
Self::common_init(&mut ll);
ll.configure_clock(clk_config);
pub fn new(mut ll: EthernetLowLevel, config: EthernetConfig) -> Self {
Self::common_init(&mut ll, config.mac_address);
ll.configure_clock(config.clk_config);
let mut mdio = mdio::Mdio::new(&ll, true);
mdio.configure_clock_div(mdc_clk_div);
mdio.configure_clock_div(config.mdc_clk_div);
Ethernet { ll, mdio }
}
fn common_init(ll: &mut EthernetLowLevel) {
fn common_init(ll: &mut EthernetLowLevel, mac_address: [u8; 6]) {
ll.enable_peripheral_clock();
ll.reset(3);
ll.initialize();
// By default, only modify critical network control bits to retain user configuration
// like the MDC clock divisor.
ll.regs.modify_net_cfg(|mut net_cfg| {
net_cfg.set_full_duplex(true);
net_cfg.set_gigabit_enable(true);
net_cfg.set_speed_mode(SpeedMode::High100Mbps);
net_cfg
});
let macaddr_msbs = (u32::from(mac_address[5]) << 8) | u32::from(mac_address[4]);
let macaddr_lsbs = (u32::from(mac_address[3]) << 24)
| (u32::from(mac_address[2]) << 16)
| (u32::from(mac_address[1]) << 8)
| u32::from(mac_address[0]);
// Writing to the lower address portion disables the address match, writing to the higher
// portion enables it again. Address matching is disabled on reset, so we do not need
// to disable the other addresses here.
ll.regs.write_addr1_low(macaddr_lsbs);
ll.regs.write_addr1_high(macaddr_msbs);
// TODO
ll.regs.modify_dma_cfg(|mut val| {
val.set_rx_packet_buf_size_sel(u2::new(0b11));
val.set_tx_packet_buf_size_sel(true);
val.set_burst_length(BurstLength::Incr16.reg_value());
// Configure 1536 bytes receive buffer size. This is sufficient for regular Ethernet
// frames.
val.set_dma_rx_ahb_buf_size_sel(DmaRxBufSize::new((MTU >> 6) as u8).unwrap());
val.set_endian_swap_mgmt_descriptor(zynq7000::eth::AhbEndianess::Little);
val
});
}
#[inline]

View File

@ -2,7 +2,7 @@ use arbitrary_int::u14;
pub use super::shared::Ownership;
/// RX buffer descriptor.
/// TX buffer descriptor.
///
/// The user should declare an array of this structure inside uncached memory.
///
@ -29,7 +29,7 @@ pub enum TransmitChecksumGenerationStatus {
PrematureEndOfFrame = 0b111,
}
#[bitbybit::bitfield(u32)]
#[bitbybit::bitfield(u32, default = 0x0)]
#[derive(Debug, PartialEq, Eq)]
pub struct Word1 {
#[bit(31, rw)]
@ -51,3 +51,28 @@ pub struct Word1 {
#[bits(0..=13, rw)]
tx_len: u14,
}
impl Descriptor {
#[inline]
pub fn set_ownership(&mut self, ownership: Ownership) {
self.word1.set_ownership(ownership);
}
/// Set the wrap bit, which should be done for the last descriptor in the descriptor list.
#[inline]
pub fn set_wrap_bit(&mut self) {
self.word1.set_wrap(true);
}
/// Set the information for a transfer.
pub fn set_tx_transfer_info(
&mut self,
tx_len: u14,
last_buffer: bool,
no_crc_generation: bool,
) {
self.word1.set_tx_len(tx_len);
self.word1.set_last_buffer(last_buffer);
self.word1.set_no_crc_generation(no_crc_generation);
}
}

View File

@ -13,6 +13,7 @@ use slcr::Slcr;
use zynq7000::slcr::LevelShifterReg;
pub mod clocks;
pub mod mmu;
pub mod eth;
pub mod gic;
pub mod gpio;

16
zynq7000-hal/src/mmu.rs Normal file
View File

@ -0,0 +1,16 @@
use zynq_mmu::L1Table;
pub struct Mmu(&'static mut L1Table);
impl Mmu {
#[inline]
pub const fn new(table: &'static mut L1Table) -> Self {
Mmu(table)
}
pub fn update_l1_table(&mut self, f: impl FnOnce(&mut L1Table)) {
// TODO: Disable MMU
f(self.0);
// DSB, ISB? enable MMU again.
}
}