continue, update MMU handling
This commit is contained in:
@ -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"
|
||||
|
@ -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.
|
||||
|
@ -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]
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
16
zynq7000-hal/src/mmu.rs
Normal 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.
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user