ethernet peripheral ownership, cs

This commit is contained in:
Robert Jördens 2019-05-06 17:33:42 +00:00
parent bdb6955aa1
commit ef18eb38ca
2 changed files with 221 additions and 250 deletions

View File

@ -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,10 +140,7 @@ 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| {
let mac = unsafe { &*stm32::ETHERNET_MAC::ptr() };
while mac.macmdioar.read().mb().bit_is_set() {} while mac.macmdioar.read().mb().bit_is_set() {}
mac.macmdioar.modify(|_, w| unsafe { mac.macmdioar.modify(|_, w| unsafe {
w w
@ -156,13 +152,9 @@ fn phy_read(reg_addr: u8) -> u16 {
}); });
while mac.macmdioar.read().mb().bit_is_set() {} while mac.macmdioar.read().mb().bit_is_set() {}
mac.macmdiodr.read().md().bits() 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| {
let mac = unsafe { &*stm32::ETHERNET_MAC::ptr() };
while mac.macmdioar.read().mb().bit_is_set() {} while mac.macmdioar.read().mb().bit_is_set() {}
mac.macmdiodr.write(|w| unsafe { w.md().bits(reg_data) }); mac.macmdiodr.write(|w| unsafe { w.md().bits(reg_data) });
mac.macmdioar.modify(|_, w| unsafe { mac.macmdioar.modify(|_, w| unsafe {
@ -174,15 +166,14 @@ fn phy_write(reg_addr: u8, reg_data: u16) {
.mb().set_bit() .mb().set_bit()
}); });
while mac.macmdioar.read().mb().bit_is_set() {} 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,12 +330,11 @@ 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()); eth_dma.dmamr.modify(|_, w| w.swr().set_bit());
while eth_dma.dmamr.read().swr().bit_is_set() {} while eth_dma.dmamr.read().swr().bit_is_set() {}
@ -451,14 +424,14 @@ impl Device {
.tsf().set_bit() .tsf().set_bit()
}); });
if (phy_read(PHY_REG_ID1) != 0x0007) | (phy_read(PHY_REG_ID2) != 0xC131) { if (phy_read(PHY_REG_ID1, eth_mac) != 0x0007) | (phy_read(PHY_REG_ID2, eth_mac) != 0xC131) {
error!("PHY ID error!"); error!("PHY ID error!");
} }
phy_write(PHY_REG_BCR, PHY_REG_BCR_RESET); phy_write(PHY_REG_BCR, PHY_REG_BCR_RESET, eth_mac);
while phy_read(PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {}; while phy_read(PHY_REG_BCR, eth_mac) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {};
phy_write_ext(PHY_REG_WUCSR, 0); 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); 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_UP == 0 {};
while phy_read(PHY_REG_BSR) & PHY_REG_BSR_ANDONE == 0 {}; while phy_read(PHY_REG_BSR) & PHY_REG_BSR_ANDONE == 0 {};
@ -507,8 +480,8 @@ impl Device {
.rpf().clear_bit() .rpf().clear_bit()
}); });
self.rx.init(); self.rx.init(eth_dma);
self.tx.init(); self.tx.init(eth_dma);
// Manage MAC transmission and reception // Manage MAC transmission and reception
eth_mac.maccr.modify(|_, w| { eth_mac.maccr.modify(|_, w| {
@ -525,7 +498,6 @@ impl Device {
w.tps().set_bit() w.tps().set_bit()
.rps().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()

View File

@ -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]