eth: model rx/tx state with type parameters
This commit is contained in:
parent
74bd81f87f
commit
f07a541c99
|
@ -3,15 +3,16 @@ use crate::slcr;
|
||||||
|
|
||||||
pub mod phy;
|
pub mod phy;
|
||||||
mod regs;
|
mod regs;
|
||||||
mod rx;
|
pub mod rx;
|
||||||
mod tx;
|
pub mod tx;
|
||||||
|
|
||||||
pub struct Eth<'rx> {
|
pub struct Eth<RX, TX> {
|
||||||
regs: &'static mut regs::RegisterBlock,
|
regs: &'static mut regs::RegisterBlock,
|
||||||
rx: Option<rx::DescList<'rx>>,
|
rx: RX,
|
||||||
|
tx: TX,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'rx> Eth<'rx> {
|
impl Eth<(), ()> {
|
||||||
pub fn default(macaddr: [u8; 6]) -> Self {
|
pub fn default(macaddr: [u8; 6]) -> Self {
|
||||||
slcr::RegisterBlock::unlocked(|slcr| {
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
// MDIO
|
// MDIO
|
||||||
|
@ -140,20 +141,42 @@ impl<'rx> Eth<'rx> {
|
||||||
});
|
});
|
||||||
|
|
||||||
let regs = regs::RegisterBlock::gem0();
|
let regs = regs::RegisterBlock::gem0();
|
||||||
let rx = None;
|
Self::from_regs(regs, macaddr)
|
||||||
let mut eth = Eth { regs, rx }.init();
|
|
||||||
eth.configure(macaddr);
|
|
||||||
eth
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gem1(macaddr: [u8; 6]) -> Self {
|
pub fn gem1(macaddr: [u8; 6]) -> Self {
|
||||||
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
|
// Enable gem1 ref clock
|
||||||
|
slcr.gem1_rclk_ctrl.write(
|
||||||
|
slcr::RclkCtrl::zeroed()
|
||||||
|
.clkact(true)
|
||||||
|
);
|
||||||
|
// 0x0050_0801: 8, 5: 100 Mb/s
|
||||||
|
slcr.gem1_clk_ctrl.write(
|
||||||
|
slcr::ClkCtrl::zeroed()
|
||||||
|
.clkact(true)
|
||||||
|
.srcsel(slcr::PllSource::IoPll)
|
||||||
|
.divisor(8)
|
||||||
|
.divisor1(5)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
let regs = regs::RegisterBlock::gem1();
|
let regs = regs::RegisterBlock::gem1();
|
||||||
let rx = None;
|
Self::from_regs(regs, macaddr)
|
||||||
let mut eth = Eth { regs, rx }.init();
|
}
|
||||||
|
|
||||||
|
fn from_regs(regs: &'static mut regs::RegisterBlock, macaddr: [u8; 6]) -> Self {
|
||||||
|
let mut eth = Eth {
|
||||||
|
regs,
|
||||||
|
rx: (),
|
||||||
|
tx: (),
|
||||||
|
}.init();
|
||||||
eth.configure(macaddr);
|
eth.configure(macaddr);
|
||||||
eth
|
eth
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<RX, TX> Eth<RX, TX> {
|
||||||
fn init(mut self) -> Self {
|
fn init(mut self) -> Self {
|
||||||
// Clear the Network Control register.
|
// Clear the Network Control register.
|
||||||
self.regs.net_ctrl.write(regs::NetCtrl::zeroed());
|
self.regs.net_ctrl.write(regs::NetCtrl::zeroed());
|
||||||
|
@ -274,14 +297,19 @@ impl<'rx> Eth<'rx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_rx(&mut self, rx_buffers: [&'rx mut [u8]; rx::DESCS]) {
|
pub fn start_rx<'rx>(self, rx_buffers: [&'rx mut [u8]; rx::DESCS]) -> Eth<rx::DescList<'rx>, TX> {
|
||||||
self.rx = Some(rx::DescList::new(rx_buffers));
|
let new_self = Eth {
|
||||||
let list_addr = self.rx.as_ref().unwrap() as *const _ as u32;
|
regs: self.regs,
|
||||||
|
rx: rx::DescList::new(rx_buffers),
|
||||||
|
tx: self.tx,
|
||||||
|
};
|
||||||
|
let list_addr = &new_self.rx as *const _ as u32;
|
||||||
assert!(list_addr & 0b11 == 0);
|
assert!(list_addr & 0b11 == 0);
|
||||||
self.regs.rx_qbar.write(
|
new_self.regs.rx_qbar.write(
|
||||||
regs::RxQbar::zeroed()
|
regs::RxQbar::zeroed()
|
||||||
.rx_q_baseaddr(list_addr >> 2)
|
.rx_q_baseaddr(list_addr >> 2)
|
||||||
);
|
);
|
||||||
|
new_self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wait_phy_idle(&self) {
|
fn wait_phy_idle(&self) {
|
||||||
|
@ -289,7 +317,7 @@ impl<'rx> Eth<'rx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'rx> phy::PhyAccess for Eth<'rx> {
|
impl<RX, TX> phy::PhyAccess for Eth<RX, TX> {
|
||||||
fn read_phy(&mut self, addr: u8, reg: u8) -> u16 {
|
fn read_phy(&mut self, addr: u8, reg: u8) -> u16 {
|
||||||
self.wait_phy_idle();
|
self.wait_phy_idle();
|
||||||
self.regs.phy_maint.write(
|
self.regs.phy_maint.write(
|
||||||
|
|
10
src/main.rs
10
src/main.rs
|
@ -6,6 +6,7 @@
|
||||||
#![feature(compiler_builtins_lib)]
|
#![feature(compiler_builtins_lib)]
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
|
use core::mem::uninitialized;
|
||||||
|
|
||||||
use r0::zero_bss;
|
use r0::zero_bss;
|
||||||
use compiler_builtins as _;
|
use compiler_builtins as _;
|
||||||
|
@ -92,6 +93,15 @@ fn main() {
|
||||||
}
|
}
|
||||||
while !uart.tx_fifo_empty() {}
|
while !uart.tx_fifo_empty() {}
|
||||||
|
|
||||||
|
let mut rx_buffers = [[0u8; 1536]; eth::rx::DESCS];
|
||||||
|
let mut rx_buffer_ptrs: [&mut [u8]; eth::rx::DESCS] = unsafe {
|
||||||
|
uninitialized()
|
||||||
|
};
|
||||||
|
for (i, (ptr, buf)) in rx_buffer_ptrs.iter_mut().zip(rx_buffers.iter_mut()).enumerate() {
|
||||||
|
*ptr = buf;
|
||||||
|
}
|
||||||
|
let mut eth = eth.start_rx(rx_buffer_ptrs);
|
||||||
|
|
||||||
loop {}
|
loop {}
|
||||||
panic!("End");
|
panic!("End");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue