refactor ethmac
This commit is contained in:
parent
e8d6d84ac5
commit
8247c8f5a5
@ -3,6 +3,7 @@ use tm4c129x;
|
|||||||
|
|
||||||
use core::slice;
|
use core::slice;
|
||||||
use smoltcp::Error;
|
use smoltcp::Error;
|
||||||
|
use smoltcp::wire::EthernetAddress;
|
||||||
use smoltcp::phy::{DeviceLimits, Device};
|
use smoltcp::phy::{DeviceLimits, Device};
|
||||||
|
|
||||||
const EPHY_BMCR: u8 = 0x00; // Ethernet PHY Basic Mode Control
|
const EPHY_BMCR: u8 = 0x00; // Ethernet PHY Basic Mode Control
|
||||||
@ -38,28 +39,6 @@ const ETH_TX_BUFFER_SIZE: usize = 1536;
|
|||||||
const ETH_RX_BUFFER_COUNT: usize = 3;
|
const ETH_RX_BUFFER_COUNT: usize = 3;
|
||||||
const ETH_RX_BUFFER_SIZE: usize = 1536;
|
const ETH_RX_BUFFER_SIZE: usize = 1536;
|
||||||
|
|
||||||
pub struct EmacData {
|
|
||||||
pub tx_desc_buf: [u32; ETH_TX_BUFFER_COUNT * ETH_DESC_U32_SIZE],
|
|
||||||
pub rx_desc_buf: [u32; ETH_RX_BUFFER_COUNT * ETH_DESC_U32_SIZE],
|
|
||||||
pub tx_cur_desc: usize,
|
|
||||||
pub rx_cur_desc: usize,
|
|
||||||
pub tx_counter: u32,
|
|
||||||
pub rx_counter: u32,
|
|
||||||
pub tx_pkt_buf: [u8; ETH_TX_BUFFER_COUNT * ETH_TX_BUFFER_SIZE],
|
|
||||||
pub rx_pkt_buf: [u8; ETH_RX_BUFFER_COUNT * ETH_RX_BUFFER_SIZE],
|
|
||||||
}
|
|
||||||
|
|
||||||
static mut EMAC_DATA: EmacData = EmacData {
|
|
||||||
tx_desc_buf: [0; ETH_TX_BUFFER_COUNT * ETH_DESC_U32_SIZE],
|
|
||||||
rx_desc_buf: [0; ETH_RX_BUFFER_COUNT * ETH_DESC_U32_SIZE],
|
|
||||||
tx_cur_desc: 0,
|
|
||||||
rx_cur_desc: 0,
|
|
||||||
tx_counter: 0,
|
|
||||||
rx_counter: 0,
|
|
||||||
tx_pkt_buf: [0; ETH_TX_BUFFER_COUNT * ETH_TX_BUFFER_SIZE],
|
|
||||||
rx_pkt_buf: [0; ETH_RX_BUFFER_COUNT * ETH_RX_BUFFER_SIZE],
|
|
||||||
};
|
|
||||||
|
|
||||||
fn delay(d: u32) {
|
fn delay(d: u32) {
|
||||||
for _ in 0..d {
|
for _ in 0..d {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -105,7 +84,7 @@ fn phy_write(reg_addr: u8, reg_data: u16) {
|
|||||||
w.data().bits(reg_data)
|
w.data().bits(reg_data)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Tell the MAC to write the given PHY register
|
// Tell the MAC to write the given PHY register
|
||||||
emac0.miiaddr.write(|w| {
|
emac0.miiaddr.write(|w| {
|
||||||
w.cr()._100_150()
|
w.cr()._100_150()
|
||||||
.mii().bits(reg_addr & 0x1F)
|
.mii().bits(reg_addr & 0x1F)
|
||||||
@ -127,193 +106,204 @@ fn phy_write_ext(reg_addr: u8, reg_data: u16) {
|
|||||||
phy_write(EPHY_ADDAR, reg_data);
|
phy_write(EPHY_ADDAR, reg_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(mac_addr: [u8; 6]) {
|
pub struct EthernetDevice {
|
||||||
cortex_m::interrupt::free(|cs| {
|
tx_desc_buf: [u32; ETH_TX_BUFFER_COUNT * ETH_DESC_U32_SIZE],
|
||||||
let sysctl = tm4c129x::SYSCTL.borrow(cs);
|
rx_desc_buf: [u32; ETH_RX_BUFFER_COUNT * ETH_DESC_U32_SIZE],
|
||||||
let emac0 = tm4c129x::EMAC0.borrow(cs);
|
tx_cur_desc: usize,
|
||||||
|
rx_cur_desc: usize,
|
||||||
|
tx_counter: u32,
|
||||||
|
rx_counter: u32,
|
||||||
|
tx_pkt_buf: [u8; ETH_TX_BUFFER_COUNT * ETH_TX_BUFFER_SIZE],
|
||||||
|
rx_pkt_buf: [u8; ETH_RX_BUFFER_COUNT * ETH_RX_BUFFER_SIZE],
|
||||||
|
}
|
||||||
|
|
||||||
sysctl.rcgcemac.modify(|_, w| w.r0().bit(true)); // Bring up MAC
|
impl EthernetDevice {
|
||||||
sysctl.sremac.modify(|_, w| w.r0().bit(true)); // Activate MAC reset
|
pub fn new(mac_addr: EthernetAddress) -> EthernetDevice {
|
||||||
delay(16);
|
let mut device = EthernetDevice {
|
||||||
sysctl.sremac.modify(|_, w| w.r0().bit(false)); // Dectivate MAC reset
|
tx_desc_buf: [0; ETH_TX_BUFFER_COUNT * ETH_DESC_U32_SIZE],
|
||||||
|
rx_desc_buf: [0; ETH_RX_BUFFER_COUNT * ETH_DESC_U32_SIZE],
|
||||||
sysctl.rcgcephy.modify(|_, w| w.r0().bit(true)); // Bring up PHY
|
tx_cur_desc: 0,
|
||||||
sysctl.srephy.modify(|_, w| w.r0().bit(true)); // Activate PHY reset
|
rx_cur_desc: 0,
|
||||||
delay(16);
|
tx_counter: 0,
|
||||||
sysctl.srephy.modify(|_, w| w.r0().bit(false)); // Dectivate PHY reset
|
rx_counter: 0,
|
||||||
|
tx_pkt_buf: [0; ETH_TX_BUFFER_COUNT * ETH_TX_BUFFER_SIZE],
|
||||||
while !sysctl.premac.read().r0().bit() {} // Wait for the MAC to come out of reset
|
rx_pkt_buf: [0; ETH_RX_BUFFER_COUNT * ETH_RX_BUFFER_SIZE],
|
||||||
while !sysctl.prephy.read().r0().bit() {} // Wait for the PHY to come out of reset
|
};
|
||||||
delay(10000);
|
|
||||||
|
|
||||||
emac0.dmabusmod.modify(|_, w| w.swr().bit(true)); // Reset MAC DMA
|
|
||||||
while emac0.dmabusmod.read().swr().bit() {} // Wait for the MAC DMA to come out of reset
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
emac0.miiaddr.write(|w| w.cr()._100_150()); // Set the MII CSR clock speed.
|
|
||||||
|
|
||||||
// Checking PHY
|
|
||||||
if (phy_read(EPHY_ID1) != 0x2000) | (phy_read(EPHY_ID2) != 0xA221) {
|
|
||||||
panic!("PHY ID error!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset PHY transceiver
|
|
||||||
phy_write(EPHY_BMCR, 1); // Initiate MII reset
|
|
||||||
while 1 == (phy_read(EPHY_BMCR) & 1) {}; // Wait for the reset to be completed
|
|
||||||
|
|
||||||
// Configure PHY LEDs
|
|
||||||
phy_write_ext(EPHY_LEDCFG, 0x0008); // LED0 Link OK/Blink on TX/RX Activity
|
|
||||||
|
|
||||||
// Tell the PHY to start an auto-negotiation cycle
|
|
||||||
phy_write(EPHY_BMCR, 0b00010010_00000000); // ANEN and RESTARTAN
|
|
||||||
|
|
||||||
// Set the DMA operation mode
|
|
||||||
emac0.dmaopmode.write(|w|
|
|
||||||
w.rsf().bit(true) // Receive Store and Forward
|
|
||||||
.tsf().bit(true) // Transmit Store and Forward
|
|
||||||
.ttc()._64() // Transmit Threshold Control
|
|
||||||
.rtc()._64() // Receive Threshold Control
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set the bus mode register.
|
|
||||||
emac0.dmabusmod.write(|w| unsafe {
|
|
||||||
w.atds().bit(true)
|
|
||||||
.aal().bit(true) // Address Aligned Beats
|
|
||||||
.usp().bit(true) // Use Separate Programmable Burst Length ???
|
|
||||||
.rpbl().bits(1) // RX DMA Programmable Burst Length
|
|
||||||
.pbl().bits(1) // Programmable Burst Length
|
|
||||||
.pr().bits(0) // Priority Ratio 1:1
|
|
||||||
});
|
|
||||||
|
|
||||||
// Disable all the MMC interrupts as these are enabled by default at reset.
|
|
||||||
emac0.mmcrxim.write(|w| unsafe { w.bits(0xFFFFFFFF)});
|
|
||||||
emac0.mmctxim.write(|w| unsafe { w.bits(0xFFFFFFFF)});
|
|
||||||
|
|
||||||
// Set MAC configuration options
|
|
||||||
emac0.cfg.write(|w|
|
|
||||||
w.dupm().bit(true) // MAC operates in full-duplex mode
|
|
||||||
.ipc().bit(true) // Checksum Offload Enable
|
|
||||||
.prelen()._7() // 7 bytes of preamble
|
|
||||||
.ifg()._96() // 96 bit times
|
|
||||||
.bl()._1024() // Back-Off Limit 1024
|
|
||||||
.ps().bit(true) // ?
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set the maximum receive frame size
|
|
||||||
emac0.wdogto.write(|w| unsafe {
|
|
||||||
w.bits(0) // ??? no use watchdog
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set the high 2 bytes of the MAC address
|
|
||||||
emac0.addr0h.write(|w| unsafe { w.addrhi().bits(mac_addr[4] as u16 | ((mac_addr[5] as u16) << 8)) });
|
|
||||||
|
|
||||||
// Set the low 4 bytes of the MAC address
|
|
||||||
emac0.addr0l.write(|w| unsafe {
|
|
||||||
w.addrlo().bits(mac_addr[0] as u32 | ((mac_addr[1] as u32) << 8) | ((mac_addr[2] as u32) << 16) | ((mac_addr[3] as u32) << 24))
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set MAC filtering options (?)
|
|
||||||
emac0.framefltr.write(|w|
|
|
||||||
w.hpf().bit(true) // Hash or Perfect Filter
|
|
||||||
// .hmc().bit(true) // Hash Multicast ???
|
|
||||||
.pm().bit(true) // Pass All Multicast
|
|
||||||
);
|
|
||||||
|
|
||||||
// Initialize hash table
|
|
||||||
emac0.hashtbll.write(|w| unsafe { w.htl().bits(0)});
|
|
||||||
emac0.hashtblh.write(|w| unsafe { w.hth().bits(0)});
|
|
||||||
|
|
||||||
emac0.flowctl.write(|w| unsafe { w.bits(0)}); // Disable flow control ???
|
|
||||||
|
|
||||||
// Initialize TX DMA descriptors
|
// Initialize TX DMA descriptors
|
||||||
for x in 0..ETH_TX_BUFFER_COUNT {
|
for x in 0..ETH_TX_BUFFER_COUNT {
|
||||||
let p = x * ETH_DESC_U32_SIZE;
|
let p = x * ETH_DESC_U32_SIZE;
|
||||||
let r = x * ETH_TX_BUFFER_SIZE;
|
let r = x * ETH_TX_BUFFER_SIZE;
|
||||||
unsafe {
|
|
||||||
// Initialize transmit flags
|
// Initialize transmit flags
|
||||||
EMAC_DATA.tx_desc_buf[p + 0] = 0;
|
device.tx_desc_buf[p + 0] = 0;
|
||||||
// Initialize transmit buffer size
|
// Initialize transmit buffer size
|
||||||
EMAC_DATA.tx_desc_buf[p + 1] = 0;
|
device.tx_desc_buf[p + 1] = 0;
|
||||||
// Transmit buffer address
|
// Transmit buffer address
|
||||||
EMAC_DATA.tx_desc_buf[p + 2] = (&EMAC_DATA.tx_pkt_buf[r] as *const u8) as u32;
|
device.tx_desc_buf[p + 2] = (&device.tx_pkt_buf[r] as *const u8) as u32;
|
||||||
// Next descriptor address
|
// Next descriptor address
|
||||||
if x != ETH_TX_BUFFER_COUNT - 1 {
|
if x != ETH_TX_BUFFER_COUNT - 1 {
|
||||||
EMAC_DATA.tx_desc_buf[p + 3] = (&EMAC_DATA.tx_desc_buf[p + ETH_DESC_U32_SIZE] as *const u32) as u32;
|
device.tx_desc_buf[p + 3] = (&device.tx_desc_buf[p + ETH_DESC_U32_SIZE] as *const u32) as u32;
|
||||||
} else {
|
} else {
|
||||||
EMAC_DATA.tx_desc_buf[p + 3] = (&EMAC_DATA.tx_desc_buf[0] as *const u32) as u32;
|
device.tx_desc_buf[p + 3] = (&device.tx_desc_buf[0] as *const u32) as u32;
|
||||||
}
|
|
||||||
// Reserved fields
|
|
||||||
EMAC_DATA.tx_desc_buf[p + 4] = 0;
|
|
||||||
EMAC_DATA.tx_desc_buf[p + 5] = 0;
|
|
||||||
// Transmit frame time stamp
|
|
||||||
EMAC_DATA.tx_desc_buf[p + 6] = 0;
|
|
||||||
EMAC_DATA.tx_desc_buf[p + 7] = 0;
|
|
||||||
}
|
}
|
||||||
|
// Reserved fields
|
||||||
|
device.tx_desc_buf[p + 4] = 0;
|
||||||
|
device.tx_desc_buf[p + 5] = 0;
|
||||||
|
// Transmit frame time stamp
|
||||||
|
device.tx_desc_buf[p + 6] = 0;
|
||||||
|
device.tx_desc_buf[p + 7] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize RX DMA descriptors
|
// Initialize RX DMA descriptors
|
||||||
for x in 0..ETH_RX_BUFFER_COUNT {
|
for x in 0..ETH_RX_BUFFER_COUNT {
|
||||||
let p = x * ETH_DESC_U32_SIZE;
|
let p = x * ETH_DESC_U32_SIZE;
|
||||||
let r = x * ETH_RX_BUFFER_SIZE;
|
let r = x * ETH_RX_BUFFER_SIZE;
|
||||||
unsafe {
|
|
||||||
// The descriptor is initially owned by the DMA
|
// The descriptor is initially owned by the DMA
|
||||||
EMAC_DATA.rx_desc_buf[p + 0] = EMAC_RDES0_OWN;
|
device.rx_desc_buf[p + 0] = EMAC_RDES0_OWN;
|
||||||
// Use chain structure rather than ring structure
|
// Use chain structure rather than ring structure
|
||||||
EMAC_DATA.rx_desc_buf[p + 1] = EMAC_RDES1_RCH | ((ETH_RX_BUFFER_SIZE as u32) & EMAC_RDES1_RBS1);
|
device.rx_desc_buf[p + 1] = EMAC_RDES1_RCH | ((ETH_RX_BUFFER_SIZE as u32) & EMAC_RDES1_RBS1);
|
||||||
// Receive buffer address
|
// Receive buffer address
|
||||||
EMAC_DATA.rx_desc_buf[p + 2] = (&EMAC_DATA.rx_pkt_buf[r] as *const u8) as u32;
|
device.rx_desc_buf[p + 2] = (&device.rx_pkt_buf[r] as *const u8) as u32;
|
||||||
// Next descriptor address
|
// Next descriptor address
|
||||||
if x != ETH_RX_BUFFER_COUNT - 1 {
|
if x != ETH_RX_BUFFER_COUNT - 1 {
|
||||||
EMAC_DATA.rx_desc_buf[p + 3] = (&EMAC_DATA.rx_desc_buf[p + ETH_DESC_U32_SIZE] as *const u32) as u32;
|
device.rx_desc_buf[p + 3] = (&device.rx_desc_buf[p + ETH_DESC_U32_SIZE] as *const u32) as u32;
|
||||||
} else {
|
} else {
|
||||||
EMAC_DATA.rx_desc_buf[p + 3] = (&EMAC_DATA.rx_desc_buf[0] as *const u32) as u32;
|
device.rx_desc_buf[p + 3] = (&device.rx_desc_buf[0] as *const u32) as u32;
|
||||||
}
|
|
||||||
// Extended status
|
|
||||||
EMAC_DATA.rx_desc_buf[p + 4] = 0;
|
|
||||||
// Reserved field
|
|
||||||
EMAC_DATA.rx_desc_buf[p + 5] = 0;
|
|
||||||
// Transmit frame time stamp
|
|
||||||
EMAC_DATA.rx_desc_buf[p + 6] = 0;
|
|
||||||
EMAC_DATA.rx_desc_buf[p + 7] = 0;
|
|
||||||
}
|
}
|
||||||
|
// Extended status
|
||||||
|
device.rx_desc_buf[p + 4] = 0;
|
||||||
|
// Reserved field
|
||||||
|
device.rx_desc_buf[p + 5] = 0;
|
||||||
|
// Transmit frame time stamp
|
||||||
|
device.rx_desc_buf[p + 6] = 0;
|
||||||
|
device.rx_desc_buf[p + 7] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
cortex_m::interrupt::free(|cs| {
|
||||||
EMAC_DATA.tx_cur_desc = 0;
|
let sysctl = tm4c129x::SYSCTL.borrow(cs);
|
||||||
EMAC_DATA.rx_cur_desc = 0;
|
let emac0 = tm4c129x::EMAC0.borrow(cs);
|
||||||
|
|
||||||
|
sysctl.rcgcemac.modify(|_, w| w.r0().bit(true)); // Bring up MAC
|
||||||
|
sysctl.sremac.modify(|_, w| w.r0().bit(true)); // Activate MAC reset
|
||||||
|
delay(16);
|
||||||
|
sysctl.sremac.modify(|_, w| w.r0().bit(false)); // Dectivate MAC reset
|
||||||
|
|
||||||
|
sysctl.rcgcephy.modify(|_, w| w.r0().bit(true)); // Bring up PHY
|
||||||
|
sysctl.srephy.modify(|_, w| w.r0().bit(true)); // Activate PHY reset
|
||||||
|
delay(16);
|
||||||
|
sysctl.srephy.modify(|_, w| w.r0().bit(false)); // Dectivate PHY reset
|
||||||
|
|
||||||
|
while !sysctl.premac.read().r0().bit() {} // Wait for the MAC to come out of reset
|
||||||
|
while !sysctl.prephy.read().r0().bit() {} // Wait for the PHY to come out of reset
|
||||||
|
delay(10000);
|
||||||
|
|
||||||
|
emac0.dmabusmod.modify(|_, w| w.swr().bit(true)); // Reset MAC DMA
|
||||||
|
while emac0.dmabusmod.read().swr().bit() {} // Wait for the MAC DMA to come out of reset
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
emac0.miiaddr.write(|w| w.cr()._100_150()); // Set the MII CSR clock speed.
|
||||||
|
|
||||||
|
// Checking PHY
|
||||||
|
if (phy_read(EPHY_ID1) != 0x2000) | (phy_read(EPHY_ID2) != 0xA221) {
|
||||||
|
panic!("PHY ID error!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset PHY transceiver
|
||||||
|
phy_write(EPHY_BMCR, 1); // Initiate MII reset
|
||||||
|
while (phy_read(EPHY_BMCR) & 1) == 1 {}; // Wait for the reset to be completed
|
||||||
|
|
||||||
|
// Configure PHY LEDs
|
||||||
|
phy_write_ext(EPHY_LEDCFG, 0x0008); // LED0 Link OK/Blink on TX/RX Activity
|
||||||
|
|
||||||
|
// Tell the PHY to start an auto-negotiation cycle
|
||||||
|
phy_write(EPHY_BMCR, 0b00010010_00000000); // ANEN and RESTARTAN
|
||||||
|
|
||||||
|
// Set the DMA operation mode
|
||||||
|
emac0.dmaopmode.write(|w|
|
||||||
|
w.rsf().bit(true) // Receive Store and Forward
|
||||||
|
.tsf().bit(true) // Transmit Store and Forward
|
||||||
|
.ttc()._64() // Transmit Threshold Control
|
||||||
|
.rtc()._64() // Receive Threshold Control
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set the bus mode register.
|
||||||
|
emac0.dmabusmod.write(|w| unsafe {
|
||||||
|
w.atds().bit(true)
|
||||||
|
.aal().bit(true) // Address Aligned Beats
|
||||||
|
.usp().bit(true) // Use Separate Programmable Burst Length ???
|
||||||
|
.rpbl().bits(1) // RX DMA Programmable Burst Length
|
||||||
|
.pbl().bits(1) // Programmable Burst Length
|
||||||
|
.pr().bits(0) // Priority Ratio 1:1
|
||||||
|
});
|
||||||
|
|
||||||
|
// Disable all the MMC interrupts as these are enabled by default at reset.
|
||||||
|
emac0.mmcrxim.write(|w| unsafe { w.bits(0xFFFFFFFF)});
|
||||||
|
emac0.mmctxim.write(|w| unsafe { w.bits(0xFFFFFFFF)});
|
||||||
|
|
||||||
|
// Set MAC configuration options
|
||||||
|
emac0.cfg.write(|w|
|
||||||
|
w.dupm().bit(true) // MAC operates in full-duplex mode
|
||||||
|
.ipc().bit(true) // Checksum Offload Enable
|
||||||
|
.prelen()._7() // 7 bytes of preamble
|
||||||
|
.ifg()._96() // 96 bit times
|
||||||
|
.bl()._1024() // Back-Off Limit 1024
|
||||||
|
.ps().bit(true) // ?
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set the maximum receive frame size
|
||||||
|
emac0.wdogto.write(|w| unsafe {
|
||||||
|
w.bits(0) // ??? no use watchdog
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set the MAC address
|
||||||
|
let mac_addr = mac_addr.0;
|
||||||
|
emac0.addr0h.write(|w| unsafe { w.addrhi().bits(mac_addr[4] as u16 | ((mac_addr[5] as u16) << 8)) });
|
||||||
|
emac0.addr0l.write(|w| unsafe {
|
||||||
|
w.addrlo().bits(mac_addr[0] as u32 | ((mac_addr[1] as u32) << 8) | ((mac_addr[2] as u32) << 16) | ((mac_addr[3] as u32) << 24))
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set MAC filtering options (?)
|
||||||
|
emac0.framefltr.write(|w|
|
||||||
|
w.hpf().bit(true) // Hash or Perfect Filter
|
||||||
|
//.hmc().bit(true) // Hash Multicast ???
|
||||||
|
.pm().bit(true) // Pass All Multicast
|
||||||
|
);
|
||||||
|
|
||||||
|
// Initialize hash table
|
||||||
|
emac0.hashtbll.write(|w| unsafe { w.htl().bits(0)});
|
||||||
|
emac0.hashtblh.write(|w| unsafe { w.hth().bits(0)});
|
||||||
|
|
||||||
|
emac0.flowctl.write(|w| unsafe { w.bits(0)}); // Disable flow control ???
|
||||||
|
|
||||||
|
emac0.txdladdr.write(|w| unsafe { w.bits((&device.tx_desc_buf[0] as *const u32) as u32)});
|
||||||
|
emac0.rxdladdr.write(|w| unsafe { w.bits((&device.rx_desc_buf[0] as *const u32) as u32)});
|
||||||
|
|
||||||
|
// Manage MAC transmission and reception
|
||||||
|
emac0.cfg.modify(|_, w|
|
||||||
|
w.re().bit(true) // Receiver Enable
|
||||||
|
.te().bit(true) // Transmiter Enable
|
||||||
|
);
|
||||||
|
|
||||||
|
// Manage DMA transmission and reception
|
||||||
|
emac0.dmaopmode.modify(|_, w|
|
||||||
|
w.sr().bit(true) // Start Receive
|
||||||
|
.st().bit(true) // Start Transmit
|
||||||
|
);
|
||||||
|
});
|
||||||
|
device
|
||||||
|
}
|
||||||
|
|
||||||
|
fn release_rx_buf(&mut self) {
|
||||||
|
self.rx_cur_desc += ETH_DESC_U32_SIZE;
|
||||||
|
if self.rx_cur_desc >= (ETH_RX_BUFFER_COUNT * ETH_DESC_U32_SIZE) {
|
||||||
|
self.rx_cur_desc = 0;
|
||||||
}
|
}
|
||||||
|
self.rx_desc_buf[self.rx_cur_desc + 0] = EMAC_RDES0_OWN; // release descriptor
|
||||||
emac0.txdladdr.write(|w| unsafe { w.bits((&EMAC_DATA.tx_desc_buf[0] as *const u32) as u32)});
|
|
||||||
emac0.rxdladdr.write(|w| unsafe { w.bits((&EMAC_DATA.rx_desc_buf[0] as *const u32) as u32)});
|
|
||||||
|
|
||||||
// Manage MAC transmission and reception
|
|
||||||
emac0.cfg.modify(|_, w|
|
|
||||||
w.re().bit(true) // Receiver Enable
|
|
||||||
.te().bit(true) // Transmiter Enable
|
|
||||||
);
|
|
||||||
|
|
||||||
// Manage DMA transmission and reception
|
|
||||||
emac0.dmaopmode.modify(|_, w|
|
|
||||||
w.sr().bit(true) // Start Receive
|
|
||||||
.st().bit(true) // Start Transmit
|
|
||||||
);
|
|
||||||
|
|
||||||
println!("EMAC init done");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn release_rx_buf() {
|
|
||||||
unsafe {
|
|
||||||
EMAC_DATA.rx_cur_desc += ETH_DESC_U32_SIZE;
|
|
||||||
if EMAC_DATA.rx_cur_desc >= (ETH_RX_BUFFER_COUNT * ETH_DESC_U32_SIZE) {
|
|
||||||
EMAC_DATA.rx_cur_desc = 0;
|
|
||||||
}
|
|
||||||
EMAC_DATA.rx_desc_buf[EMAC_DATA.rx_cur_desc + 0] = EMAC_RDES0_OWN; // release descriptor
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EthernetDevice;
|
|
||||||
|
|
||||||
impl Device for EthernetDevice {
|
impl Device for EthernetDevice {
|
||||||
type RxBuffer = RxBuffer;
|
type RxBuffer = RxBuffer;
|
||||||
type TxBuffer = TxBuffer;
|
type TxBuffer = TxBuffer;
|
||||||
@ -326,92 +316,100 @@ impl Device for EthernetDevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn receive(&mut self, _timestamp: u64) -> Result<Self::RxBuffer, Error> {
|
fn receive(&mut self, _timestamp: u64) -> Result<Self::RxBuffer, Error> {
|
||||||
unsafe {
|
if (self.rx_desc_buf[self.rx_cur_desc + 0] & EMAC_RDES0_OWN) == 0 {
|
||||||
if (EMAC_DATA.rx_desc_buf[EMAC_DATA.rx_cur_desc + 0] & EMAC_RDES0_OWN) == 0 {
|
// check for the whole packet in the buffer and no any error
|
||||||
// check for the whole packet in the buffer and no any error
|
if (EMAC_RDES0_FS | EMAC_RDES0_LS) == self.rx_desc_buf[self.rx_cur_desc + 0] & (EMAC_RDES0_FS | EMAC_RDES0_LS | EMAC_RDES0_ES) {
|
||||||
if (EMAC_RDES0_FS | EMAC_RDES0_LS) == EMAC_DATA.rx_desc_buf[EMAC_DATA.rx_cur_desc + 0] & (EMAC_RDES0_FS | EMAC_RDES0_LS | EMAC_RDES0_ES) {
|
// Retrieve the length of the frame
|
||||||
// Retrieve the length of the frame
|
let mut n = (self.rx_desc_buf[self.rx_cur_desc + 0] & EMAC_RDES0_FL) >> 16;
|
||||||
let mut n = (EMAC_DATA.rx_desc_buf[EMAC_DATA.rx_cur_desc + 0] & EMAC_RDES0_FL) >> 16;
|
// Limit the number of data to read
|
||||||
// Limit the number of data to read
|
if n > ETH_RX_BUFFER_SIZE as u32 { n = ETH_RX_BUFFER_SIZE as u32; }
|
||||||
if n > ETH_RX_BUFFER_SIZE as u32 { n = ETH_RX_BUFFER_SIZE as u32; }
|
let sl = unsafe {
|
||||||
Ok(RxBuffer(slice::from_raw_parts(EMAC_DATA.rx_desc_buf[EMAC_DATA.rx_cur_desc + 2] as * mut u8,
|
slice::from_raw_parts(self.rx_desc_buf[self.rx_cur_desc + 2] as * mut u8,
|
||||||
n as usize)))
|
n as usize)
|
||||||
} else {
|
};
|
||||||
// Ignore invalid frame
|
Ok(RxBuffer(sl, self))
|
||||||
release_rx_buf();
|
|
||||||
Err(Error::Exhausted)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Err(Error::Exhausted) // currently no buffers to process
|
// Ignore invalid frame
|
||||||
|
self.release_rx_buf();
|
||||||
|
Err(Error::Exhausted)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Err(Error::Exhausted) // currently no buffers to process
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transmit(&mut self, _timestamp: u64, length: usize) -> Result<Self::TxBuffer, Error> {
|
fn transmit(&mut self, _timestamp: u64, length: usize) -> Result<Self::TxBuffer, Error> {
|
||||||
unsafe {
|
// Check if the TX DMA buffer released
|
||||||
// Check if the TX DMA buffer released
|
if (self.tx_desc_buf[self.tx_cur_desc + 0] & EMAC_TDES0_OWN) == 0 {
|
||||||
if (EMAC_DATA.tx_desc_buf[EMAC_DATA.tx_cur_desc + 0] & EMAC_TDES0_OWN) == 0 {
|
// Write the number of bytes to send
|
||||||
// Write the number of bytes to send
|
self.tx_desc_buf[self.tx_cur_desc + 1] = length as u32 & EMAC_TDES1_TBS1;
|
||||||
EMAC_DATA.tx_desc_buf[EMAC_DATA.tx_cur_desc + 1] = length as u32 & EMAC_TDES1_TBS1;
|
|
||||||
|
|
||||||
Ok(TxBuffer(slice::from_raw_parts_mut(EMAC_DATA.tx_desc_buf[EMAC_DATA.tx_cur_desc + 2] as * mut u8,
|
let sl = unsafe {
|
||||||
ETH_TX_BUFFER_SIZE)))
|
slice::from_raw_parts_mut(self.tx_desc_buf[self.tx_cur_desc + 2] as * mut u8,
|
||||||
} else {
|
ETH_TX_BUFFER_SIZE)
|
||||||
// to do if need: Instruct the DMA to poll the receive descriptor list
|
};
|
||||||
Err(Error::Exhausted)
|
Ok(TxBuffer(sl, self))
|
||||||
}
|
} else {
|
||||||
|
// to do if need: Instruct the DMA to poll the receive descriptor list
|
||||||
|
Err(Error::Exhausted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RxBuffer(&'static [u8]);
|
pub struct RxBuffer(*const [u8], *mut EthernetDevice);
|
||||||
|
|
||||||
impl AsRef<[u8]> for RxBuffer {
|
impl AsRef<[u8]> for RxBuffer {
|
||||||
fn as_ref(&self) -> &[u8] { self.0 }
|
fn as_ref(&self) -> &[u8] {
|
||||||
|
unsafe { &*self.0 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for RxBuffer {
|
impl Drop for RxBuffer {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
release_rx_buf();
|
let mut device = unsafe { &mut *self.1 };
|
||||||
|
device.release_rx_buf();
|
||||||
unsafe { EMAC_DATA.rx_counter += 1 }; // Increment RX statistics
|
device.rx_counter += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TxBuffer(&'static mut [u8]);
|
pub struct TxBuffer(*mut [u8], *mut EthernetDevice);
|
||||||
|
|
||||||
impl AsRef<[u8]> for TxBuffer {
|
impl AsRef<[u8]> for TxBuffer {
|
||||||
fn as_ref(&self) -> &[u8] { self.0 }
|
fn as_ref(&self) -> &[u8] {
|
||||||
|
unsafe { &*self.0 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsMut<[u8]> for TxBuffer {
|
impl AsMut<[u8]> for TxBuffer {
|
||||||
fn as_mut(&mut self) -> &mut [u8] { self.0 }
|
fn as_mut(&mut self) -> &mut [u8] {
|
||||||
|
unsafe { &mut *self.0 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for TxBuffer {
|
impl Drop for TxBuffer {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
let mut device = unsafe { &mut *self.1 };
|
||||||
// Use chain structure rather than ring structure
|
|
||||||
// Set LS and FS flags as the data fits in a single buffer and give the ownership of the descriptor to the DMA
|
|
||||||
EMAC_DATA.tx_desc_buf[EMAC_DATA.tx_cur_desc + 0] = EMAC_TDES0_LS | EMAC_TDES0_FS | EMAC_TDES0_TCH;
|
|
||||||
EMAC_DATA.tx_desc_buf[EMAC_DATA.tx_cur_desc + 0] |= EMAC_TDES0_OWN; // Set ownersip for DMA here
|
|
||||||
|
|
||||||
cortex_m::interrupt::free(|cs| {
|
// Use chain structure rather than ring structure
|
||||||
let emac0 = tm4c129x::EMAC0.borrow(cs);
|
// Set LS and FS flags as the data fits in a single buffer and give the ownership of the descriptor to the DMA
|
||||||
// Clear TU flag to resume processing
|
device.tx_desc_buf[device.tx_cur_desc + 0] = EMAC_TDES0_LS | EMAC_TDES0_FS | EMAC_TDES0_TCH;
|
||||||
emac0.dmaris.write(|w| w.tu().bit(true));
|
device.tx_desc_buf[device.tx_cur_desc + 0] |= EMAC_TDES0_OWN; // Set ownership for DMA here
|
||||||
// Instruct the DMA to poll the transmit descriptor list
|
|
||||||
emac0.txpolld.write(|w| w.tpd().bits(0));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Calculate next DMA descriptor offset
|
cortex_m::interrupt::free(|cs| {
|
||||||
let mut tx_next_desc = EMAC_DATA.tx_cur_desc + ETH_DESC_U32_SIZE;
|
let emac0 = tm4c129x::EMAC0.borrow(cs);
|
||||||
if tx_next_desc >= (ETH_TX_BUFFER_COUNT * ETH_DESC_U32_SIZE) {
|
// Clear TU flag to resume processing
|
||||||
tx_next_desc = 0;
|
emac0.dmaris.write(|w| w.tu().bit(true));
|
||||||
}
|
// Instruct the DMA to poll the transmit descriptor list
|
||||||
EMAC_DATA.tx_cur_desc = tx_next_desc;
|
unsafe { emac0.txpolld.write(|w| w.tpd().bits(0)); }
|
||||||
|
});
|
||||||
|
|
||||||
EMAC_DATA.tx_counter += 1;
|
// Calculate next DMA descriptor offset
|
||||||
|
let mut tx_next_desc = device.tx_cur_desc + ETH_DESC_U32_SIZE;
|
||||||
|
if tx_next_desc >= (ETH_TX_BUFFER_COUNT * ETH_DESC_U32_SIZE) {
|
||||||
|
tx_next_desc = 0;
|
||||||
}
|
}
|
||||||
|
device.tx_cur_desc = tx_next_desc;
|
||||||
|
|
||||||
|
device.tx_counter += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,8 +166,7 @@ fn main_with_fpu() {
|
|||||||
println!("MAC {} IP {}", hardware_addr, protocol_addrs[0]);
|
println!("MAC {} IP {}", hardware_addr, protocol_addrs[0]);
|
||||||
let mut arp_cache_entries: [_; 8] = Default::default();
|
let mut arp_cache_entries: [_; 8] = Default::default();
|
||||||
let mut arp_cache = SliceArpCache::new(&mut arp_cache_entries[..]);
|
let mut arp_cache = SliceArpCache::new(&mut arp_cache_entries[..]);
|
||||||
ethmac::init(hardware_addr.0);
|
let mut device = ethmac::EthernetDevice::new(hardware_addr);
|
||||||
let mut device = ethmac::EthernetDevice;
|
|
||||||
let mut iface = EthernetInterface::new(
|
let mut iface = EthernetInterface::new(
|
||||||
&mut device, &mut arp_cache as &mut ArpCache,
|
&mut device, &mut arp_cache as &mut ArpCache,
|
||||||
hardware_addr, &mut protocol_addrs[..]);
|
hardware_addr, &mut protocol_addrs[..]);
|
||||||
|
Loading…
Reference in New Issue
Block a user