Merge branch 'feature/hal-conversion' into feature/pounder-support
This commit is contained in:
commit
41ebec4ebf
|
@ -1,605 +0,0 @@
|
||||||
use core::{cmp, slice};
|
|
||||||
use smoltcp::phy;
|
|
||||||
use smoltcp::time::Instant;
|
|
||||||
use smoltcp::wire::EthernetAddress;
|
|
||||||
use smoltcp::Result;
|
|
||||||
use super::{pac};
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
mod phy_consts {
|
|
||||||
pub const PHY_REG_BCR: u8 = 0x00;
|
|
||||||
pub const PHY_REG_BSR: u8 = 0x01;
|
|
||||||
pub const PHY_REG_ID1: u8 = 0x02;
|
|
||||||
pub const PHY_REG_ID2: u8 = 0x03;
|
|
||||||
pub const PHY_REG_ANTX: u8 = 0x04;
|
|
||||||
pub const PHY_REG_ANRX: u8 = 0x05;
|
|
||||||
pub const PHY_REG_ANEXP: u8 = 0x06;
|
|
||||||
pub const PHY_REG_ANNPTX: u8 = 0x07;
|
|
||||||
pub const PHY_REG_ANNPRX: u8 = 0x08;
|
|
||||||
pub const PHY_REG_SSR: u8 = 0x1F; // Special Status Register
|
|
||||||
pub const PHY_REG_CTL: u8 = 0x0D; // Ethernet PHY Register Control
|
|
||||||
pub const PHY_REG_ADDAR: u8 = 0x0E; // Ethernet PHY Address or Data
|
|
||||||
|
|
||||||
pub const PHY_REG_WUCSR: u16 = 0x8010;
|
|
||||||
|
|
||||||
pub const PHY_REG_BCR_COLTEST: u16 = 1 << 7;
|
|
||||||
pub const PHY_REG_BCR_FD: u16 = 1 << 8;
|
|
||||||
pub const PHY_REG_BCR_ANRST: u16 = 1 << 9;
|
|
||||||
pub const PHY_REG_BCR_ISOLATE: u16 = 1 << 10;
|
|
||||||
pub const PHY_REG_BCR_POWERDN: u16 = 1 << 11;
|
|
||||||
pub const PHY_REG_BCR_AN: u16 = 1 << 12;
|
|
||||||
pub const PHY_REG_BCR_100M: u16 = 1 << 13;
|
|
||||||
pub const PHY_REG_BCR_LOOPBACK: u16 = 1 << 14;
|
|
||||||
pub const PHY_REG_BCR_RESET: u16 = 1 << 15;
|
|
||||||
|
|
||||||
pub const PHY_REG_BSR_JABBER: u16 = 1 << 1;
|
|
||||||
pub const PHY_REG_BSR_UP: u16 = 1 << 2;
|
|
||||||
pub const PHY_REG_BSR_FAULT: u16 = 1 << 4;
|
|
||||||
pub const PHY_REG_BSR_ANDONE: u16 = 1 << 5;
|
|
||||||
|
|
||||||
pub const PHY_REG_SSR_ANDONE: u16 = 1 << 12;
|
|
||||||
pub const PHY_REG_SSR_SPEED: u16 = 0b111 << 2;
|
|
||||||
pub const PHY_REG_SSR_10BASE_HD: u16 = 0b001 << 2;
|
|
||||||
pub const PHY_REG_SSR_10BASE_FD: u16 = 0b101 << 2;
|
|
||||||
pub const PHY_REG_SSR_100BASE_HD: u16 = 0b010 << 2;
|
|
||||||
pub const PHY_REG_SSR_100BASE_FD: u16 = 0b110 << 2;
|
|
||||||
}
|
|
||||||
use self::phy_consts::*;
|
|
||||||
|
|
||||||
const EMAC_DES3_OWN: u32 = 0x8000_0000;
|
|
||||||
const EMAC_DES3_CTXT: u32 = 0x4000_0000;
|
|
||||||
const EMAC_DES3_FD: u32 = 0x2000_0000;
|
|
||||||
const EMAC_DES3_LD: u32 = 0x1000_0000;
|
|
||||||
const EMAC_DES3_ES: u32 = 0x0000_8000;
|
|
||||||
const EMAC_TDES2_IOC: u32 = 0x8000_0000;
|
|
||||||
const EMAC_RDES3_IOC: u32 = 0x4000_0000;
|
|
||||||
const EMAC_RDES3_PL: u32 = 0x0000_7FFF;
|
|
||||||
const EMAC_RDES3_BUF1V: u32 = 0x0100_0000;
|
|
||||||
const EMAC_TDES2_B1L: u32 = 0x0000_3FFF;
|
|
||||||
const EMAC_DES0_BUF1AP: u32 = 0xFFFF_FFFF;
|
|
||||||
|
|
||||||
// 6 DMAC, 6 SMAC, 4 q tag, 2 ethernet type II, 1500 ip MTU, 4 CRC, 2 padding
|
|
||||||
const ETH_BUFFER_SIZE: usize = 1524;
|
|
||||||
const ETH_DESC_U32_SIZE: usize = 4;
|
|
||||||
const ETH_TX_BUFFER_COUNT: usize = 4;
|
|
||||||
const ETH_RX_BUFFER_COUNT: usize = 4;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
mod cr_consts {
|
|
||||||
/* For HCLK 60-100 MHz */
|
|
||||||
pub const ETH_MACMIIAR_CR_HCLK_DIV_42: u8 = 0;
|
|
||||||
/* For HCLK 100-150 MHz */
|
|
||||||
pub const ETH_MACMIIAR_CR_HCLK_DIV_62: u8 = 1;
|
|
||||||
/* For HCLK 20-35 MHz */
|
|
||||||
pub const ETH_MACMIIAR_CR_HCLK_DIV_16: u8 = 2;
|
|
||||||
/* For HCLK 35-60 MHz */
|
|
||||||
pub const ETH_MACMIIAR_CR_HCLK_DIV_26: u8 = 3;
|
|
||||||
/* For HCLK 150-250 MHz */
|
|
||||||
pub const ETH_MACMIIAR_CR_HCLK_DIV_102: u8 = 4;
|
|
||||||
/* For HCLK 250-300 MHz */
|
|
||||||
pub const ETH_MACMIIAR_CR_HCLK_DIV_124: u8 = 5;
|
|
||||||
}
|
|
||||||
use self::cr_consts::*;
|
|
||||||
|
|
||||||
// set clock range in MAC MII address register
|
|
||||||
// 200 MHz AHB clock = eth_hclk
|
|
||||||
const CLOCK_RANGE: u8 = ETH_MACMIIAR_CR_HCLK_DIV_102;
|
|
||||||
|
|
||||||
const PHY_ADDR: u8 = 0;
|
|
||||||
|
|
||||||
fn phy_read(reg_addr: u8, mac: &pac::ETHERNET_MAC) -> u16 {
|
|
||||||
while mac.macmdioar.read().mb().bit_is_set() {}
|
|
||||||
mac.macmdioar.modify(|_, w| unsafe {
|
|
||||||
w.pa()
|
|
||||||
.bits(PHY_ADDR)
|
|
||||||
.rda()
|
|
||||||
.bits(reg_addr)
|
|
||||||
.goc()
|
|
||||||
.bits(0b11) // read
|
|
||||||
.cr()
|
|
||||||
.bits(CLOCK_RANGE)
|
|
||||||
.mb()
|
|
||||||
.set_bit()
|
|
||||||
});
|
|
||||||
while mac.macmdioar.read().mb().bit_is_set() {}
|
|
||||||
mac.macmdiodr.read().md().bits()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn phy_write(reg_addr: u8, reg_data: u16, mac: &pac::ETHERNET_MAC) {
|
|
||||||
while mac.macmdioar.read().mb().bit_is_set() {}
|
|
||||||
mac.macmdiodr.write(|w| unsafe { w.md().bits(reg_data) });
|
|
||||||
mac.macmdioar.modify(|_, w| unsafe {
|
|
||||||
w.pa()
|
|
||||||
.bits(PHY_ADDR)
|
|
||||||
.rda()
|
|
||||||
.bits(reg_addr)
|
|
||||||
.goc()
|
|
||||||
.bits(0b01) // write
|
|
||||||
.cr()
|
|
||||||
.bits(CLOCK_RANGE)
|
|
||||||
.mb()
|
|
||||||
.set_bit()
|
|
||||||
});
|
|
||||||
while mac.macmdioar.read().mb().bit_is_set() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes a value to an extended PHY register in MMD address space
|
|
||||||
fn phy_write_ext(reg_addr: u16, reg_data: u16, mac: &pac::ETHERNET_MAC) {
|
|
||||||
phy_write(PHY_REG_CTL, 0x0003, mac); // set address
|
|
||||||
phy_write(PHY_REG_ADDAR, reg_addr, mac);
|
|
||||||
phy_write(PHY_REG_CTL, 0x4003, mac); // set data
|
|
||||||
phy_write(PHY_REG_ADDAR, reg_data, mac);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(align(4))]
|
|
||||||
struct RxRing {
|
|
||||||
desc_buf: [[u32; ETH_DESC_U32_SIZE]; ETH_RX_BUFFER_COUNT],
|
|
||||||
pkt_buf: [[u8; ETH_BUFFER_SIZE]; ETH_RX_BUFFER_COUNT],
|
|
||||||
cur_desc: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RxRing {
|
|
||||||
const fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
desc_buf: [[0; ETH_DESC_U32_SIZE]; ETH_RX_BUFFER_COUNT],
|
|
||||||
pkt_buf: [[0; ETH_BUFFER_SIZE]; ETH_RX_BUFFER_COUNT],
|
|
||||||
cur_desc: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn init(&mut self, dma: &pac::ETHERNET_DMA) {
|
|
||||||
assert_eq!(self.desc_buf[0].len() % 4, 0);
|
|
||||||
assert_eq!(self.pkt_buf[0].len() % 4, 0);
|
|
||||||
|
|
||||||
for i in 0..self.desc_buf.len() {
|
|
||||||
for j in 0..self.desc_buf[0].len() {
|
|
||||||
self.desc_buf[i][j] = 0;
|
|
||||||
}
|
|
||||||
for j in 0..self.pkt_buf[0].len() {
|
|
||||||
self.pkt_buf[i][j] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let addr = &self.desc_buf as *const _ as u32;
|
|
||||||
assert_eq!(addr & 0x3, 0);
|
|
||||||
dma.dmacrx_dlar.write(|w| w.bits(addr));
|
|
||||||
dma.dmacrx_rlr
|
|
||||||
.write(|w| w.rdrl().bits(self.desc_buf.len() as u16 - 1));
|
|
||||||
|
|
||||||
self.cur_desc = 0;
|
|
||||||
for _ in 0..self.desc_buf.len() {
|
|
||||||
self.buf_release()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_desc(&self) -> usize {
|
|
||||||
(self.cur_desc + 1) % self.desc_buf.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
// not owned by DMA
|
|
||||||
fn buf_owned(&self) -> bool {
|
|
||||||
self.desc_buf[self.cur_desc][3] & EMAC_DES3_OWN == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn buf_valid(&self) -> bool {
|
|
||||||
self.desc_buf[self.cur_desc][3]
|
|
||||||
& (EMAC_DES3_FD | EMAC_DES3_LD | EMAC_DES3_ES | EMAC_DES3_CTXT)
|
|
||||||
== (EMAC_DES3_FD | EMAC_DES3_LD)
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn buf_as_slice_mut<'a>(&self) -> &'a mut [u8] {
|
|
||||||
let len = (self.desc_buf[self.cur_desc][3] & EMAC_RDES3_PL) as usize;
|
|
||||||
let len = cmp::min(len, ETH_BUFFER_SIZE);
|
|
||||||
let addr = &self.pkt_buf[self.cur_desc] as *const _ as *mut u8;
|
|
||||||
slice::from_raw_parts_mut(addr, len)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn buf_release(&mut self) {
|
|
||||||
let addr = &self.pkt_buf[self.cur_desc] as *const _;
|
|
||||||
self.desc_buf[self.cur_desc][0] = addr as u32 & EMAC_DES0_BUF1AP;
|
|
||||||
self.desc_buf[self.cur_desc][3] =
|
|
||||||
EMAC_RDES3_BUF1V | EMAC_RDES3_IOC | EMAC_DES3_OWN;
|
|
||||||
|
|
||||||
let addr = &self.desc_buf[self.cur_desc] as *const _ as u32;
|
|
||||||
assert_eq!(addr & 0x3, 0);
|
|
||||||
|
|
||||||
let dma = unsafe { pac::Peripherals::steal().ETHERNET_DMA };
|
|
||||||
|
|
||||||
// Ensure changes to the descriptor (in particular, the OWN flag) are
|
|
||||||
// committed before DMA engine sees tail pointer store.
|
|
||||||
cortex_m::asm::dsb();
|
|
||||||
|
|
||||||
dma.dmacrx_dtpr.write(|w| unsafe { w.bits(addr) });
|
|
||||||
|
|
||||||
self.cur_desc = self.next_desc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(align(4))]
|
|
||||||
struct TxRing {
|
|
||||||
desc_buf: [[u32; ETH_DESC_U32_SIZE]; ETH_TX_BUFFER_COUNT],
|
|
||||||
pkt_buf: [[u8; ETH_BUFFER_SIZE]; ETH_TX_BUFFER_COUNT],
|
|
||||||
cur_desc: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TxRing {
|
|
||||||
const fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
desc_buf: [[0; ETH_DESC_U32_SIZE]; ETH_TX_BUFFER_COUNT],
|
|
||||||
pkt_buf: [[0; ETH_BUFFER_SIZE]; ETH_TX_BUFFER_COUNT],
|
|
||||||
cur_desc: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn init(&mut self, dma: &pac::ETHERNET_DMA) {
|
|
||||||
assert_eq!(self.desc_buf[0].len() % 4, 0);
|
|
||||||
assert_eq!(self.pkt_buf[0].len() % 4, 0);
|
|
||||||
|
|
||||||
for i in 0..self.desc_buf.len() {
|
|
||||||
for j in 0..self.desc_buf[0].len() {
|
|
||||||
self.desc_buf[i][j] = 0;
|
|
||||||
}
|
|
||||||
for j in 0..self.pkt_buf[0].len() {
|
|
||||||
self.pkt_buf[i][j] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.cur_desc = 0;
|
|
||||||
|
|
||||||
let addr = &self.desc_buf as *const _ as u32;
|
|
||||||
assert_eq!(addr & 0x3, 0);
|
|
||||||
dma.dmactx_dlar.write(|w| w.bits(addr));
|
|
||||||
dma.dmactx_rlr
|
|
||||||
.write(|w| w.tdrl().bits(self.desc_buf.len() as u16 - 1));
|
|
||||||
let addr = &self.desc_buf[0] as *const _ as u32;
|
|
||||||
assert_eq!(addr & 0x3, 0);
|
|
||||||
dma.dmactx_dtpr.write(|w| w.bits(addr));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_desc(&self) -> usize {
|
|
||||||
(self.cur_desc + 1) % self.desc_buf.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
// not owned by DMA
|
|
||||||
fn buf_owned(&self) -> bool {
|
|
||||||
self.desc_buf[self.cur_desc][3] & EMAC_DES3_OWN == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn buf_as_slice_mut<'a>(&mut self, len: usize) -> &'a mut [u8] {
|
|
||||||
let len = cmp::min(len, ETH_BUFFER_SIZE);
|
|
||||||
self.desc_buf[self.cur_desc][2] =
|
|
||||||
EMAC_TDES2_IOC | (len as u32 & EMAC_TDES2_B1L);
|
|
||||||
let addr = &self.pkt_buf[self.cur_desc] as *const _ as *mut u8;
|
|
||||||
self.desc_buf[self.cur_desc][0] = addr as u32 & EMAC_DES0_BUF1AP;
|
|
||||||
slice::from_raw_parts_mut(addr, len)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn buf_release(&mut self) {
|
|
||||||
self.desc_buf[self.cur_desc][3] =
|
|
||||||
EMAC_DES3_OWN | EMAC_DES3_FD | EMAC_DES3_LD;
|
|
||||||
self.cur_desc = self.next_desc();
|
|
||||||
|
|
||||||
let addr = &self.desc_buf[self.cur_desc] as *const _ as u32;
|
|
||||||
assert_eq!(addr & 0x3, 0);
|
|
||||||
|
|
||||||
let dma = unsafe { pac::Peripherals::steal().ETHERNET_DMA };
|
|
||||||
|
|
||||||
// Ensure packet contents as well as changes to the descriptor have been
|
|
||||||
// committed before DMA engine sees the tail pointer store.
|
|
||||||
cortex_m::asm::dsb();
|
|
||||||
|
|
||||||
dma.dmactx_dtpr.write(|w| unsafe { w.bits(addr) });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Device {
|
|
||||||
rx: RxRing,
|
|
||||||
tx: TxRing,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Device {
|
|
||||||
pub const fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
rx: RxRing::new(),
|
|
||||||
tx: TxRing::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the ethernet peripherals
|
|
||||||
//
|
|
||||||
// # Safety
|
|
||||||
//
|
|
||||||
// This iis transitively unsafe since it sets potentially
|
|
||||||
// unsafe register values. Might ultimately be safe if the values
|
|
||||||
// are correct.
|
|
||||||
//
|
|
||||||
// After `init` is called, `Device` shall not be moved.
|
|
||||||
pub unsafe fn init(
|
|
||||||
&mut self,
|
|
||||||
mac: EthernetAddress,
|
|
||||||
eth_mac: &pac::ETHERNET_MAC,
|
|
||||||
eth_dma: &pac::ETHERNET_DMA,
|
|
||||||
eth_mtl: &pac::ETHERNET_MTL,
|
|
||||||
) {
|
|
||||||
eth_dma.dmamr.modify(|_, w| w.swr().set_bit());
|
|
||||||
while eth_dma.dmamr.read().swr().bit_is_set() {}
|
|
||||||
|
|
||||||
// 200 MHz
|
|
||||||
eth_mac
|
|
||||||
.mac1ustcr
|
|
||||||
.modify(|_, w| w.tic_1us_cntr().bits(200 - 1));
|
|
||||||
|
|
||||||
// Configuration Register
|
|
||||||
eth_mac.maccr.modify(|_, w| {
|
|
||||||
w.arpen()
|
|
||||||
.clear_bit()
|
|
||||||
.ipc()
|
|
||||||
.set_bit()
|
|
||||||
.ipg()
|
|
||||||
.bits(0b000) // 96 bit
|
|
||||||
.ecrsfd()
|
|
||||||
.clear_bit()
|
|
||||||
.dcrs()
|
|
||||||
.clear_bit()
|
|
||||||
.bl()
|
|
||||||
.bits(0b00) // 19
|
|
||||||
.prelen()
|
|
||||||
.bits(0b00) // 7
|
|
||||||
// CRC stripping for Type frames
|
|
||||||
.cst()
|
|
||||||
.set_bit()
|
|
||||||
// Fast Ethernet speed
|
|
||||||
.fes()
|
|
||||||
.set_bit()
|
|
||||||
// Duplex mode
|
|
||||||
.dm()
|
|
||||||
.set_bit()
|
|
||||||
// Automatic pad/CRC stripping
|
|
||||||
.acs()
|
|
||||||
.set_bit()
|
|
||||||
// Retry disable in half-duplex mode
|
|
||||||
.dr()
|
|
||||||
.set_bit()
|
|
||||||
});
|
|
||||||
eth_mac.macecr.modify(|_, w| {
|
|
||||||
w.eipgen()
|
|
||||||
.clear_bit()
|
|
||||||
.usp()
|
|
||||||
.clear_bit()
|
|
||||||
.spen()
|
|
||||||
.clear_bit()
|
|
||||||
.dcrcc()
|
|
||||||
.clear_bit()
|
|
||||||
});
|
|
||||||
// Set the MAC address
|
|
||||||
eth_mac.maca0lr.write(|w| {
|
|
||||||
w.addrlo().bits(
|
|
||||||
u32::from(mac.0[0])
|
|
||||||
| (u32::from(mac.0[1]) << 8)
|
|
||||||
| (u32::from(mac.0[2]) << 16)
|
|
||||||
| (u32::from(mac.0[3]) << 24),
|
|
||||||
)
|
|
||||||
});
|
|
||||||
eth_mac.maca0hr.write(|w| {
|
|
||||||
w.addrhi()
|
|
||||||
.bits(u16::from(mac.0[4]) | (u16::from(mac.0[5]) << 8))
|
|
||||||
});
|
|
||||||
// frame filter register
|
|
||||||
eth_mac.macpfr.modify(|_, w| {
|
|
||||||
w.dntu()
|
|
||||||
.clear_bit()
|
|
||||||
.ipfe()
|
|
||||||
.clear_bit()
|
|
||||||
.vtfe()
|
|
||||||
.clear_bit()
|
|
||||||
.hpf()
|
|
||||||
.clear_bit()
|
|
||||||
.saf()
|
|
||||||
.clear_bit()
|
|
||||||
.saif()
|
|
||||||
.clear_bit()
|
|
||||||
.pcf()
|
|
||||||
.bits(0b00)
|
|
||||||
.dbf()
|
|
||||||
.clear_bit()
|
|
||||||
.pm()
|
|
||||||
.clear_bit()
|
|
||||||
.daif()
|
|
||||||
.clear_bit()
|
|
||||||
.hmc()
|
|
||||||
.clear_bit()
|
|
||||||
.huc()
|
|
||||||
.clear_bit()
|
|
||||||
// Receive All
|
|
||||||
.ra()
|
|
||||||
.clear_bit()
|
|
||||||
// Promiscuous mode
|
|
||||||
.pr()
|
|
||||||
.clear_bit()
|
|
||||||
});
|
|
||||||
eth_mac.macwtr.write(|w| w.pwe().clear_bit());
|
|
||||||
// Flow Control Register
|
|
||||||
eth_mac.macqtx_fcr.modify(|_, w| {
|
|
||||||
// Pause time
|
|
||||||
w.pt().bits(0x100)
|
|
||||||
});
|
|
||||||
eth_mac.macrx_fcr.modify(|_, w| w);
|
|
||||||
eth_mtl.mtlrx_qomr.modify(|_, w| {
|
|
||||||
w
|
|
||||||
// Receive store and forward
|
|
||||||
.rsf()
|
|
||||||
.set_bit()
|
|
||||||
// Dropping of TCP/IP checksum error frames disable
|
|
||||||
.dis_tcp_ef()
|
|
||||||
.clear_bit()
|
|
||||||
// Forward error frames
|
|
||||||
.fep()
|
|
||||||
.clear_bit()
|
|
||||||
// Forward undersized good packets
|
|
||||||
.fup()
|
|
||||||
.clear_bit()
|
|
||||||
});
|
|
||||||
eth_mtl.mtltx_qomr.modify(|_, w| {
|
|
||||||
w
|
|
||||||
// Transmit store and forward
|
|
||||||
.tsf()
|
|
||||||
.set_bit()
|
|
||||||
});
|
|
||||||
|
|
||||||
if (phy_read(PHY_REG_ID1, eth_mac) != 0x0007)
|
|
||||||
| (phy_read(PHY_REG_ID2, eth_mac) != 0xC131)
|
|
||||||
{
|
|
||||||
error!("PHY ID error!");
|
|
||||||
}
|
|
||||||
|
|
||||||
phy_write(PHY_REG_BCR, PHY_REG_BCR_RESET, eth_mac);
|
|
||||||
while phy_read(PHY_REG_BCR, eth_mac) & PHY_REG_BCR_RESET
|
|
||||||
== PHY_REG_BCR_RESET
|
|
||||||
{}
|
|
||||||
phy_write_ext(PHY_REG_WUCSR, 0, eth_mac);
|
|
||||||
phy_write(
|
|
||||||
PHY_REG_BCR,
|
|
||||||
PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M,
|
|
||||||
eth_mac,
|
|
||||||
);
|
|
||||||
/*
|
|
||||||
while phy_read(PHY_REG_BSR) & PHY_REG_BSR_UP == 0 {};
|
|
||||||
while phy_read(PHY_REG_BSR) & PHY_REG_BSR_ANDONE == 0 {};
|
|
||||||
while phy_read(PHY_REG_SSR) & (PHY_REG_SSR_ANDONE | PHY_REG_SSR_SPEED)
|
|
||||||
!= PHY_REG_SSR_ANDONE | PHY_REG_SSR_100BASE_FD {};
|
|
||||||
*/
|
|
||||||
|
|
||||||
// operation mode register
|
|
||||||
eth_dma.dmamr.modify(|_, w| {
|
|
||||||
w.intm()
|
|
||||||
.bits(0b00)
|
|
||||||
// Rx Tx priority ratio 1:1
|
|
||||||
.pr()
|
|
||||||
.bits(0b000)
|
|
||||||
.txpr()
|
|
||||||
.clear_bit()
|
|
||||||
.da()
|
|
||||||
.clear_bit()
|
|
||||||
});
|
|
||||||
// bus mode register
|
|
||||||
eth_dma.dmasbmr.modify(|_, w| {
|
|
||||||
// Address-aligned beats
|
|
||||||
w.aal()
|
|
||||||
.set_bit()
|
|
||||||
// Fixed burst
|
|
||||||
.fb()
|
|
||||||
.set_bit()
|
|
||||||
});
|
|
||||||
eth_dma
|
|
||||||
.dmaccr
|
|
||||||
.modify(|_, w| w.dsl().bits(0).pblx8().clear_bit().mss().bits(536));
|
|
||||||
eth_dma.dmactx_cr.modify(|_, w| {
|
|
||||||
w
|
|
||||||
// Tx DMA PBL
|
|
||||||
.txpbl()
|
|
||||||
.bits(32)
|
|
||||||
.tse()
|
|
||||||
.clear_bit()
|
|
||||||
// Operate on second frame
|
|
||||||
.osf()
|
|
||||||
.clear_bit()
|
|
||||||
});
|
|
||||||
|
|
||||||
eth_dma.dmacrx_cr.modify(|_, w| {
|
|
||||||
w
|
|
||||||
// receive buffer size
|
|
||||||
.rbsz()
|
|
||||||
.bits(ETH_BUFFER_SIZE as u16)
|
|
||||||
// Rx DMA PBL
|
|
||||||
.rxpbl()
|
|
||||||
.bits(32)
|
|
||||||
// Disable flushing of received frames
|
|
||||||
.rpf()
|
|
||||||
.clear_bit()
|
|
||||||
});
|
|
||||||
|
|
||||||
self.rx.init(eth_dma);
|
|
||||||
self.tx.init(eth_dma);
|
|
||||||
|
|
||||||
// Manage MAC transmission and reception
|
|
||||||
eth_mac.maccr.modify(|_, w| {
|
|
||||||
w.re()
|
|
||||||
.bit(true) // Receiver Enable
|
|
||||||
.te()
|
|
||||||
.bit(true) // Transmiter Enable
|
|
||||||
});
|
|
||||||
eth_mtl.mtltx_qomr.modify(|_, w| w.ftq().set_bit());
|
|
||||||
|
|
||||||
// Ensure ring buffer descriptors have been set up in memory before
|
|
||||||
// enabling DMA engine.
|
|
||||||
cortex_m::asm::dsb();
|
|
||||||
|
|
||||||
// Manage DMA transmission and reception
|
|
||||||
eth_dma.dmactx_cr.modify(|_, w| w.st().set_bit());
|
|
||||||
eth_dma.dmacrx_cr.modify(|_, w| w.sr().set_bit());
|
|
||||||
|
|
||||||
eth_dma
|
|
||||||
.dmacsr
|
|
||||||
.modify(|_, w| w.tps().set_bit().rps().set_bit());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'b> phy::Device<'a> for &'b mut Device {
|
|
||||||
type RxToken = RxToken<'a>;
|
|
||||||
type TxToken = TxToken<'a>;
|
|
||||||
|
|
||||||
fn capabilities(&self) -> phy::DeviceCapabilities {
|
|
||||||
let mut capabilities = phy::DeviceCapabilities::default();
|
|
||||||
// ethernet frame type II (6 smac, 6 dmac, 2 ethertype),
|
|
||||||
// sans CRC (4), 1500 IP MTU
|
|
||||||
capabilities.max_transmission_unit = 1514;
|
|
||||||
capabilities.max_burst_size = Some(self.tx.desc_buf.len());
|
|
||||||
capabilities
|
|
||||||
}
|
|
||||||
|
|
||||||
fn receive(&mut self) -> Option<(RxToken, TxToken)> {
|
|
||||||
// Skip all queued packets with errors.
|
|
||||||
while self.rx.buf_owned() && !self.rx.buf_valid() {
|
|
||||||
self.rx.buf_release()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !(self.rx.buf_owned() && self.tx.buf_owned()) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some((RxToken(&mut self.rx), TxToken(&mut self.tx)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn transmit(&mut self) -> Option<TxToken> {
|
|
||||||
if !self.tx.buf_owned() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(TxToken(&mut self.tx))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RxToken<'a>(&'a mut RxRing);
|
|
||||||
|
|
||||||
impl<'a> phy::RxToken for RxToken<'a> {
|
|
||||||
fn consume<R, F>(self, _timestamp: Instant, f: F) -> Result<R>
|
|
||||||
where
|
|
||||||
F: FnOnce(&mut [u8]) -> Result<R>,
|
|
||||||
{
|
|
||||||
let result = f(unsafe { self.0.buf_as_slice_mut() });
|
|
||||||
self.0.buf_release();
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TxToken<'a>(&'a mut TxRing);
|
|
||||||
|
|
||||||
impl<'a> phy::TxToken for TxToken<'a> {
|
|
||||||
fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R>
|
|
||||||
where
|
|
||||||
F: FnOnce(&mut [u8]) -> Result<R>,
|
|
||||||
{
|
|
||||||
let result = f(unsafe { self.0.buf_as_slice_mut(len) });
|
|
||||||
self.0.buf_release();
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,7 +11,7 @@
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
#[cfg(all(feature = "nightly", not(feature = "semihosting")))]
|
#[cfg(all(feature = "nightly", not(feature = "semihosting")))]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
let gpiod = unsafe { &*pac::GPIOD::ptr() };
|
let gpiod = unsafe { &*hal::stm32::GPIOD::ptr() };
|
||||||
gpiod.odr.modify(|_, w| w.odr6().high().odr12().high()); // FP_LED_1, FP_LED_3
|
gpiod.odr.modify(|_, w| w.odr6().high().odr12().high()); // FP_LED_1, FP_LED_3
|
||||||
unsafe {
|
unsafe {
|
||||||
core::intrinsics::abort();
|
core::intrinsics::abort();
|
||||||
|
@ -35,7 +35,6 @@ use cortex_m;
|
||||||
use stm32h7xx_hal as hal;
|
use stm32h7xx_hal as hal;
|
||||||
use stm32h7xx_hal::{
|
use stm32h7xx_hal::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
stm32 as pac,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use embedded_hal::{
|
use embedded_hal::{
|
||||||
|
@ -48,7 +47,6 @@ use smoltcp as net;
|
||||||
#[link_section = ".sram3.eth"]
|
#[link_section = ".sram3.eth"]
|
||||||
static mut DES_RING: ethernet::DesRing = ethernet::DesRing::new();
|
static mut DES_RING: ethernet::DesRing = ethernet::DesRing::new();
|
||||||
|
|
||||||
mod eth;
|
|
||||||
mod pounder;
|
mod pounder;
|
||||||
mod server;
|
mod server;
|
||||||
mod afe;
|
mod afe;
|
||||||
|
@ -167,13 +165,13 @@ const APP: () = {
|
||||||
|
|
||||||
let mut delay = hal::delay::Delay::new(cp.SYST, clocks.clocks);
|
let mut delay = hal::delay::Delay::new(cp.SYST, clocks.clocks);
|
||||||
|
|
||||||
let gpioa = dp.GPIOA.split(&mut clocks.ahb4);
|
let gpioa = dp.GPIOA.split(&mut clocks);
|
||||||
let gpiob = dp.GPIOB.split(&mut clocks.ahb4);
|
let gpiob = dp.GPIOB.split(&mut clocks);
|
||||||
let gpioc = dp.GPIOC.split(&mut clocks.ahb4);
|
let gpioc = dp.GPIOC.split(&mut clocks);
|
||||||
let gpiod = dp.GPIOD.split(&mut clocks.ahb4);
|
let gpiod = dp.GPIOD.split(&mut clocks);
|
||||||
let gpioe = dp.GPIOE.split(&mut clocks.ahb4);
|
let gpioe = dp.GPIOE.split(&mut clocks);
|
||||||
let gpiof = dp.GPIOF.split(&mut clocks.ahb4);
|
let gpiof = dp.GPIOF.split(&mut clocks);
|
||||||
let gpiog = dp.GPIOG.split(&mut clocks.ahb4);
|
let gpiog = dp.GPIOG.split(&mut clocks);
|
||||||
|
|
||||||
let afe1 = {
|
let afe1 = {
|
||||||
let a0_pin = gpiof.pf2.into_push_pull_output();
|
let a0_pin = gpiof.pf2.into_push_pull_output();
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 2236b578b48aa195679dd65515f595f491f88513
|
Subproject commit d79cb0015a6f0cbb819907efe3a817f7dce14bab
|
Loading…
Reference in New Issue