ethernet peripheral ownership, cs
This commit is contained in:
parent
bdb6955aa1
commit
ef18eb38ca
464
src/eth.rs
464
src/eth.rs
@ -1,5 +1,4 @@
|
|||||||
use core::{slice, cmp};
|
use core::{slice, cmp};
|
||||||
use cortex_m;
|
|
||||||
use stm32h7::stm32h7x3 as stm32;
|
use stm32h7::stm32h7x3 as stm32;
|
||||||
use smoltcp::Result;
|
use smoltcp::Result;
|
||||||
use smoltcp::time::Instant;
|
use smoltcp::time::Instant;
|
||||||
@ -141,48 +140,40 @@ pub fn setup_pins(gpioa: &stm32::GPIOA, gpiob: &stm32::GPIOB,
|
|||||||
|
|
||||||
const PHY_ADDR: u8 = 0;
|
const PHY_ADDR: u8 = 0;
|
||||||
|
|
||||||
fn phy_read(reg_addr: u8) -> u16 {
|
fn phy_read(reg_addr: u8, mac: &stm32::ETHERNET_MAC) -> u16 {
|
||||||
cortex_m::interrupt::free(|_cs| {
|
while mac.macmdioar.read().mb().bit_is_set() {}
|
||||||
let mac = unsafe { &*stm32::ETHERNET_MAC::ptr() };
|
mac.macmdioar.modify(|_, w| unsafe {
|
||||||
|
w
|
||||||
while mac.macmdioar.read().mb().bit_is_set() {}
|
.pa().bits(PHY_ADDR)
|
||||||
mac.macmdioar.modify(|_, w| unsafe {
|
.rda().bits(reg_addr)
|
||||||
w
|
.goc().bits(0b11) // read
|
||||||
.pa().bits(PHY_ADDR)
|
.cr().bits(CLOCK_RANGE)
|
||||||
.rda().bits(reg_addr)
|
.mb().set_bit()
|
||||||
.goc().bits(0b11) // read
|
});
|
||||||
.cr().bits(CLOCK_RANGE)
|
while mac.macmdioar.read().mb().bit_is_set() {}
|
||||||
.mb().set_bit()
|
mac.macmdiodr.read().md().bits()
|
||||||
});
|
|
||||||
while mac.macmdioar.read().mb().bit_is_set() {}
|
|
||||||
mac.macmdiodr.read().md().bits()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn phy_write(reg_addr: u8, reg_data: u16) {
|
fn phy_write(reg_addr: u8, reg_data: u16, mac: &stm32::ETHERNET_MAC) {
|
||||||
cortex_m::interrupt::free(|_cs| {
|
while mac.macmdioar.read().mb().bit_is_set() {}
|
||||||
let mac = unsafe { &*stm32::ETHERNET_MAC::ptr() };
|
mac.macmdiodr.write(|w| unsafe { w.md().bits(reg_data) });
|
||||||
|
mac.macmdioar.modify(|_, w| unsafe {
|
||||||
while mac.macmdioar.read().mb().bit_is_set() {}
|
w
|
||||||
mac.macmdiodr.write(|w| unsafe { w.md().bits(reg_data) });
|
.pa().bits(PHY_ADDR)
|
||||||
mac.macmdioar.modify(|_, w| unsafe {
|
.rda().bits(reg_addr)
|
||||||
w
|
.goc().bits(0b01) // write
|
||||||
.pa().bits(PHY_ADDR)
|
.cr().bits(CLOCK_RANGE)
|
||||||
.rda().bits(reg_addr)
|
.mb().set_bit()
|
||||||
.goc().bits(0b01) // write
|
});
|
||||||
.cr().bits(CLOCK_RANGE)
|
while mac.macmdioar.read().mb().bit_is_set() {}
|
||||||
.mb().set_bit()
|
|
||||||
});
|
|
||||||
while mac.macmdioar.read().mb().bit_is_set() {}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes a value to an extended PHY register in MMD address space
|
// Writes a value to an extended PHY register in MMD address space
|
||||||
fn phy_write_ext(reg_addr: u16, reg_data: u16) {
|
fn phy_write_ext(reg_addr: u16, reg_data: u16, mac: &stm32::ETHERNET_MAC) {
|
||||||
phy_write(PHY_REG_CTL, 0x0003); // set address
|
phy_write(PHY_REG_CTL, 0x0003, mac); // set address
|
||||||
phy_write(PHY_REG_ADDAR, reg_addr);
|
phy_write(PHY_REG_ADDAR, reg_addr, mac);
|
||||||
phy_write(PHY_REG_CTL, 0x4003); // set data
|
phy_write(PHY_REG_CTL, 0x4003, mac); // set data
|
||||||
phy_write(PHY_REG_ADDAR, reg_data);
|
phy_write(PHY_REG_ADDAR, reg_data, mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(align(4))]
|
#[repr(align(4))]
|
||||||
@ -201,7 +192,7 @@ impl RxRing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(&mut self) {
|
unsafe fn init(&mut self, dma: &stm32::ETHERNET_DMA) {
|
||||||
assert_eq!(self.desc_buf[0].len() % 4, 0);
|
assert_eq!(self.desc_buf[0].len() % 4, 0);
|
||||||
assert_eq!(self.pkt_buf[0].len() % 4, 0);
|
assert_eq!(self.pkt_buf[0].len() % 4, 0);
|
||||||
|
|
||||||
@ -214,17 +205,10 @@ impl RxRing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cortex_m::interrupt::free(|_cs| unsafe {
|
let addr = &self.desc_buf as *const _ as u32;
|
||||||
let dma = &*stm32::ETHERNET_DMA::ptr();
|
assert_eq!(addr & 0x3, 0);
|
||||||
|
dma.dmacrx_dlar.write(|w| w.bits(addr));
|
||||||
dma.dmacrx_dlar.write(|w| {
|
dma.dmacrx_rlr.write(|w| w.rdrl().bits(self.desc_buf.len() as u16 - 1));
|
||||||
w.bits(&self.desc_buf as *const _ as u32)
|
|
||||||
});
|
|
||||||
|
|
||||||
dma.dmacrx_rlr.write(|w| {
|
|
||||||
w.rdrl().bits(self.desc_buf.len() as u16 - 1)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
self.cur_desc = 0;
|
self.cur_desc = 0;
|
||||||
for _ in 0..self.desc_buf.len() {
|
for _ in 0..self.desc_buf.len() {
|
||||||
@ -259,11 +243,10 @@ impl RxRing {
|
|||||||
self.desc_buf[self.cur_desc][0] = addr as u32 & EMAC_DES0_BUF1AP;
|
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;
|
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 _;
|
let addr = &self.desc_buf[self.cur_desc] as *const _ as u32;
|
||||||
cortex_m::interrupt::free(|_cs| {
|
assert_eq!(addr & 0x3, 0);
|
||||||
let dma = unsafe { &*stm32::ETHERNET_DMA::ptr() };
|
let dma = unsafe { stm32::Peripherals::steal().ETHERNET_DMA };
|
||||||
dma.dmacrx_dtpr.write(|w| unsafe { w.bits(addr as u32) });
|
dma.dmacrx_dtpr.write(|w| unsafe { w.bits(addr) });
|
||||||
});
|
|
||||||
|
|
||||||
self.cur_desc = self.next_desc();
|
self.cur_desc = self.next_desc();
|
||||||
}
|
}
|
||||||
@ -285,7 +268,7 @@ impl TxRing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(&mut self) {
|
unsafe fn init(&mut self, dma: &stm32::ETHERNET_DMA) {
|
||||||
assert_eq!(self.desc_buf[0].len() % 4, 0);
|
assert_eq!(self.desc_buf[0].len() % 4, 0);
|
||||||
assert_eq!(self.pkt_buf[0].len() % 4, 0);
|
assert_eq!(self.pkt_buf[0].len() % 4, 0);
|
||||||
|
|
||||||
@ -299,21 +282,13 @@ impl TxRing {
|
|||||||
}
|
}
|
||||||
self.cur_desc = 0;
|
self.cur_desc = 0;
|
||||||
|
|
||||||
cortex_m::interrupt::free(|_cs| unsafe {
|
let addr = &self.desc_buf as *const _ as u32;
|
||||||
let dma = &*stm32::ETHERNET_DMA::ptr();
|
assert_eq!(addr & 0x3, 0);
|
||||||
|
dma.dmactx_dlar.write(|w| w.bits(addr));
|
||||||
dma.dmactx_dlar.write(|w| {
|
dma.dmactx_rlr.write(|w| w.tdrl().bits(self.desc_buf.len() as u16 - 1));
|
||||||
w.bits(&self.desc_buf as *const _ as u32)
|
let addr = &self.desc_buf[0] as *const _ as u32;
|
||||||
});
|
assert_eq!(addr & 0x3, 0);
|
||||||
|
dma.dmactx_dtpr.write(|w| w.bits(addr));
|
||||||
dma.dmactx_rlr.write(|w| {
|
|
||||||
w.tdrl().bits(self.desc_buf.len() as u16 - 1)
|
|
||||||
});
|
|
||||||
|
|
||||||
dma.dmactx_dtpr.write(|w| {
|
|
||||||
w.bits(&self.desc_buf[0] as *const _ as u32)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_desc(&self) -> usize {
|
fn next_desc(&self) -> usize {
|
||||||
@ -337,11 +312,10 @@ impl TxRing {
|
|||||||
self.desc_buf[self.cur_desc][3] = EMAC_DES3_OWN | EMAC_DES3_FD | EMAC_DES3_LD;
|
self.desc_buf[self.cur_desc][3] = EMAC_DES3_OWN | EMAC_DES3_FD | EMAC_DES3_LD;
|
||||||
self.cur_desc = self.next_desc();
|
self.cur_desc = self.next_desc();
|
||||||
|
|
||||||
let addr = &self.desc_buf[self.cur_desc] as *const _;
|
let addr = &self.desc_buf[self.cur_desc] as *const _ as u32;
|
||||||
cortex_m::interrupt::free(|_cs| {
|
assert_eq!(addr & 0x3, 0);
|
||||||
let dma = unsafe { &*stm32::ETHERNET_DMA::ptr() };
|
let dma = unsafe { stm32::Peripherals::steal().ETHERNET_DMA };
|
||||||
dma.dmactx_dtpr.write(|w| unsafe { w.bits(addr as u32) });
|
dma.dmactx_dtpr.write(|w| unsafe { w.bits(addr) });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,176 +330,174 @@ impl Device {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// After `init` is called, `Device` shall not be moved.
|
// After `init` is called, `Device` shall not be moved.
|
||||||
pub unsafe fn init(&mut self, mac: EthernetAddress) {
|
pub unsafe fn init(&mut self, mac: EthernetAddress,
|
||||||
cortex_m::interrupt::free(|_cs| {
|
eth_mac: &stm32::ETHERNET_MAC,
|
||||||
let eth_mac = &*stm32::ETHERNET_MAC::ptr();
|
eth_dma: &stm32::ETHERNET_DMA,
|
||||||
let eth_dma = &*stm32::ETHERNET_DMA::ptr();
|
eth_mtl: &stm32::ETHERNET_MTL,
|
||||||
let eth_mtl = &*stm32::ETHERNET_MTL::ptr();
|
) {
|
||||||
|
eth_dma.dmamr.modify(|_, w| w.swr().set_bit());
|
||||||
|
while eth_dma.dmamr.read().swr().bit_is_set() {}
|
||||||
|
|
||||||
eth_dma.dmamr.modify(|_, w| w.swr().set_bit());
|
// 200 MHz
|
||||||
while eth_dma.dmamr.read().swr().bit_is_set() {}
|
eth_mac.mac1ustcr.modify(|_, w| w.tic_1us_cntr().bits(200 - 1));
|
||||||
|
|
||||||
// 200 MHz
|
// Configuration Register
|
||||||
eth_mac.mac1ustcr.modify(|_, w| w.tic_1us_cntr().bits(200 - 1));
|
eth_mac.maccr.modify(|_, w| {
|
||||||
|
w
|
||||||
// Configuration Register
|
.arpen().clear_bit()
|
||||||
eth_mac.maccr.modify(|_, w| {
|
.ipc().set_bit()
|
||||||
w
|
.ipg().bits(0b000) // 96 bit
|
||||||
.arpen().clear_bit()
|
.ecrsfd().clear_bit()
|
||||||
.ipc().set_bit()
|
.dcrs().clear_bit()
|
||||||
.ipg().bits(0b000) // 96 bit
|
.bl().bits(0b00) // 19
|
||||||
.ecrsfd().clear_bit()
|
.prelen().bits(0b00) // 7
|
||||||
.dcrs().clear_bit()
|
// CRC stripping for Type frames
|
||||||
.bl().bits(0b00) // 19
|
.cst().set_bit()
|
||||||
.prelen().bits(0b00) // 7
|
// Fast Ethernet speed
|
||||||
// CRC stripping for Type frames
|
.fes().set_bit()
|
||||||
.cst().set_bit()
|
// Duplex mode
|
||||||
// Fast Ethernet speed
|
.dm().set_bit()
|
||||||
.fes().set_bit()
|
// Automatic pad/CRC stripping
|
||||||
// Duplex mode
|
.acs().set_bit()
|
||||||
.dm().set_bit()
|
// Retry disable in half-duplex mode
|
||||||
// Automatic pad/CRC stripping
|
.dr().set_bit()
|
||||||
.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) != 0x0007) | (phy_read(PHY_REG_ID2) != 0xC131) {
|
|
||||||
error!("PHY ID error!");
|
|
||||||
}
|
|
||||||
|
|
||||||
phy_write(PHY_REG_BCR, PHY_REG_BCR_RESET);
|
|
||||||
while phy_read(PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {};
|
|
||||||
phy_write_ext(PHY_REG_WUCSR, 0);
|
|
||||||
phy_write(PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M);
|
|
||||||
/*
|
|
||||||
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();
|
|
||||||
self.tx.init();
|
|
||||||
|
|
||||||
// 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());
|
|
||||||
|
|
||||||
// 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()
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
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());
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,8 +558,7 @@ impl<'a> phy::TxToken for TxToken<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn interrupt_handler() {
|
pub unsafe fn interrupt_handler(eth_dma: &stm32::ETHERNET_DMA) {
|
||||||
let eth_dma = &*stm32::ETHERNET_DMA::ptr();
|
|
||||||
eth_dma.dmacsr.write(|w|
|
eth_dma.dmacsr.write(|w|
|
||||||
w
|
w
|
||||||
.nis().set_bit()
|
.nis().set_bit()
|
||||||
@ -596,8 +567,7 @@ pub unsafe fn interrupt_handler() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn enable_interrupt() {
|
pub unsafe fn enable_interrupt(eth_dma: &stm32::ETHERNET_DMA) {
|
||||||
let eth_dma = &*stm32::ETHERNET_DMA::ptr();
|
|
||||||
eth_dma.dmacier.modify(|_, w|
|
eth_dma.dmacier.modify(|_, w|
|
||||||
w
|
w
|
||||||
.nie().set_bit()
|
.nie().set_bit()
|
||||||
|
@ -612,7 +612,7 @@ fn main() -> ! {
|
|||||||
|
|
||||||
let device = unsafe { &mut ETHERNET };
|
let device = unsafe { &mut ETHERNET };
|
||||||
let hardware_addr = net::wire::EthernetAddress([0x10, 0xE2, 0xD5, 0x00, 0x03, 0x00]);
|
let hardware_addr = net::wire::EthernetAddress([0x10, 0xE2, 0xD5, 0x00, 0x03, 0x00]);
|
||||||
unsafe { device.init(hardware_addr) };
|
unsafe { device.init(hardware_addr, &dp.ETHERNET_MAC, &dp.ETHERNET_DMA, &dp.ETHERNET_MTL) };
|
||||||
let mut neighbor_cache_storage = [None; 8];
|
let mut neighbor_cache_storage = [None; 8];
|
||||||
let neighbor_cache = net::iface::NeighborCache::new(&mut neighbor_cache_storage[..]);
|
let neighbor_cache = net::iface::NeighborCache::new(&mut neighbor_cache_storage[..]);
|
||||||
let local_addr = net::wire::IpAddress::v4(10, 0, 16, 99);
|
let local_addr = net::wire::IpAddress::v4(10, 0, 16, 99);
|
||||||
@ -626,7 +626,7 @@ fn main() -> ! {
|
|||||||
let mut sockets = net::socket::SocketSet::new(&mut socket_set_entries[..]);
|
let mut sockets = net::socket::SocketSet::new(&mut socket_set_entries[..]);
|
||||||
create_socket!(sockets, tcp_rx_storage0, tcp_tx_storage0, tcp_handle0);
|
create_socket!(sockets, tcp_rx_storage0, tcp_tx_storage0, tcp_handle0);
|
||||||
|
|
||||||
unsafe { eth::enable_interrupt(); }
|
unsafe { eth::enable_interrupt(&dp.ETHERNET_DMA); }
|
||||||
unsafe { cp.NVIC.set_priority(stm32::Interrupt::ETH, 196); } // mid prio
|
unsafe { cp.NVIC.set_priority(stm32::Interrupt::ETH, 196); } // mid prio
|
||||||
cp.NVIC.enable(stm32::Interrupt::ETH);
|
cp.NVIC.enable(stm32::Interrupt::ETH);
|
||||||
|
|
||||||
@ -715,8 +715,9 @@ fn SPI1() {
|
|||||||
|
|
||||||
#[interrupt]
|
#[interrupt]
|
||||||
fn ETH() {
|
fn ETH() {
|
||||||
|
let dma = unsafe { &stm32::Peripherals::steal().ETHERNET_DMA };
|
||||||
ETHERNET_PENDING.store(true, Ordering::Relaxed);
|
ETHERNET_PENDING.store(true, Ordering::Relaxed);
|
||||||
unsafe { eth::interrupt_handler() }
|
unsafe { eth::interrupt_handler(dma) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[exception]
|
#[exception]
|
||||||
|
Loading…
Reference in New Issue
Block a user