forked from M-Labs/ionpak-thermostat
Update to newer smoltcp.
This also fixes a bug where RX descriptors would be first advanced and then released.
This commit is contained in:
parent
fe088d7bba
commit
8491394a50
|
@ -1,14 +1,3 @@
|
||||||
[root]
|
|
||||||
name = "ionpak-firmware"
|
|
||||||
version = "1.0.0"
|
|
||||||
dependencies = [
|
|
||||||
"cortex-m 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m-rt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"smoltcp 0.4.0-pre (git+https://github.com/m-labs/smoltcp?rev=14355e1)",
|
|
||||||
"tm4c129x 0.5.0 (git+https://github.com/m-labs/dslite2svd?rev=d527f3f)",
|
|
||||||
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aligned"
|
name = "aligned"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -43,6 +32,17 @@ dependencies = [
|
||||||
"r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ionpak-firmware"
|
||||||
|
version = "1.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"cortex-m 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"cortex-m-rt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=cb5be48)",
|
||||||
|
"tm4c129x 0.5.0 (git+https://github.com/m-labs/dslite2svd?rev=d527f3f)",
|
||||||
|
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kernel32-sys"
|
name = "kernel32-sys"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
@ -54,7 +54,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "managed"
|
name = "managed"
|
||||||
version = "0.3.0"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -73,11 +73,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smoltcp"
|
name = "smoltcp"
|
||||||
version = "0.4.0-pre"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/m-labs/smoltcp?rev=14355e1#14355e15d0b0bbc47b79cbb47ea74dda475a6f1b"
|
source = "git+https://github.com/m-labs/smoltcp?rev=cb5be48#cb5be4886864ca4c89952945b08b66db90e61d49"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"managed 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"managed 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -131,10 +131,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum cortex-m 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d553ca1f23403c81e6d3d28a64ef6e8eadd7f395195aacda65cbc0dc987738e"
|
"checksum cortex-m 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d553ca1f23403c81e6d3d28a64ef6e8eadd7f395195aacda65cbc0dc987738e"
|
||||||
"checksum cortex-m-rt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ec28308ef272803380c9c4e6708bf1d794ddcc8c9d511b9976b31ac3322452e5"
|
"checksum cortex-m-rt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ec28308ef272803380c9c4e6708bf1d794ddcc8c9d511b9976b31ac3322452e5"
|
||||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||||
"checksum managed 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61eb783b4fa77e8fa4d27ec400f97ed9168546b8b30341a120b7ba9cc6571aaf"
|
"checksum managed 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43e2737ecabe4ae36a68061398bf27d2bfd0763f4c3c837a398478459494c4b7"
|
||||||
"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
|
"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
|
||||||
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
|
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
|
||||||
"checksum smoltcp 0.4.0-pre (git+https://github.com/m-labs/smoltcp?rev=14355e1)" = "<none>"
|
"checksum smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=cb5be48)" = "<none>"
|
||||||
"checksum tm4c129x 0.5.0 (git+https://github.com/m-labs/dslite2svd?rev=d527f3f)" = "<none>"
|
"checksum tm4c129x 0.5.0 (git+https://github.com/m-labs/dslite2svd?rev=d527f3f)" = "<none>"
|
||||||
"checksum vcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "45c297f0afb6928cd08ab1ff9d95e99392595ea25ae1b5ecf822ff8764e57a0d"
|
"checksum vcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "45c297f0afb6928cd08ab1ff9d95e99392595ea25ae1b5ecf822ff8764e57a0d"
|
||||||
"checksum volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286"
|
"checksum volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286"
|
||||||
|
|
|
@ -17,8 +17,8 @@ features = ["rt"]
|
||||||
|
|
||||||
[dependencies.smoltcp]
|
[dependencies.smoltcp]
|
||||||
git = "https://github.com/m-labs/smoltcp"
|
git = "https://github.com/m-labs/smoltcp"
|
||||||
rev = "14355e1"
|
rev = "cb5be48"
|
||||||
features = []
|
features = ["proto-ipv4", "socket-tcp"]
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use eeprom;
|
use eeprom;
|
||||||
use crc32;
|
use crc32;
|
||||||
use smoltcp::wire::IpAddress;
|
use smoltcp::wire::{IpCidr, IpAddress};
|
||||||
|
|
||||||
const MAGIC: u8 = 0x54;
|
const MAGIC: u8 = 0x54;
|
||||||
|
|
||||||
|
@ -58,13 +58,13 @@ fn write_eeprom_payload(payload: &[u8]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub ip: IpAddress,
|
pub ip: IpCidr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn new() -> Config {
|
pub fn new() -> Config {
|
||||||
Config {
|
Config {
|
||||||
ip: IpAddress::v4(192, 168, 69, 1)
|
ip: IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,17 +73,21 @@ impl Config {
|
||||||
let payload = reader.read_payload();
|
let payload = reader.read_payload();
|
||||||
if payload.is_ok() {
|
if payload.is_ok() {
|
||||||
let payload = payload.unwrap();
|
let payload = payload.unwrap();
|
||||||
self.ip = IpAddress::v4(payload[0], payload[1], payload[2], payload[3]);
|
self.ip = IpCidr::new(
|
||||||
|
IpAddress::v4(payload[0], payload[1], payload[2], payload[3]),
|
||||||
|
payload[4])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save(&self) {
|
pub fn save(&self) {
|
||||||
let mut payload: [u8; 4] = [0; 4];
|
match self.ip {
|
||||||
let ip4 = match self.ip {
|
IpCidr::Ipv4(ipv4) => {
|
||||||
IpAddress::Ipv4(x) => x.0,
|
let mut payload: [u8; 5] = [0; 5];
|
||||||
|
payload[0..4].copy_from_slice(&ipv4.address().0);
|
||||||
|
payload[4] = ipv4.prefix_len();
|
||||||
|
write_eeprom_payload(&payload);
|
||||||
|
}
|
||||||
_ => panic!("unsupported network address")
|
_ => panic!("unsupported network address")
|
||||||
};
|
};
|
||||||
payload[0..4].copy_from_slice(&ip4);
|
|
||||||
write_eeprom_payload(&payload);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use core::slice;
|
use core::{slice, cmp};
|
||||||
|
use core::cell::RefCell;
|
||||||
use cortex_m;
|
use cortex_m;
|
||||||
use tm4c129x;
|
use tm4c129x;
|
||||||
use smoltcp::Error;
|
use smoltcp::Result;
|
||||||
use smoltcp::wire::EthernetAddress;
|
use smoltcp::wire::EthernetAddress;
|
||||||
use smoltcp::phy::{DeviceLimits, Device};
|
use smoltcp::phy;
|
||||||
|
|
||||||
use board;
|
use board;
|
||||||
|
|
||||||
|
@ -23,16 +24,17 @@ const EMAC_TDES0_OWN: u32 = 0x80000000; // Indicates that the descriptor is
|
||||||
const EMAC_TDES0_LS: u32 = 0x20000000; // Last Segment
|
const EMAC_TDES0_LS: u32 = 0x20000000; // Last Segment
|
||||||
const EMAC_TDES0_FS: u32 = 0x10000000; // First Segment
|
const EMAC_TDES0_FS: u32 = 0x10000000; // First Segment
|
||||||
const EMAC_TDES0_TCH: u32 = 0x00100000; // Second Address Chained
|
const EMAC_TDES0_TCH: u32 = 0x00100000; // Second Address Chained
|
||||||
|
#[allow(dead_code)]
|
||||||
const EMAC_TDES1_TBS1: u32 = 0x00001FFF; // Transmit Buffer 1 Size
|
const EMAC_TDES1_TBS1: u32 = 0x00001FFF; // Transmit Buffer 1 Size
|
||||||
|
|
||||||
// Receive DMA descriptor flags
|
// Receive DMA descriptor flags
|
||||||
const EMAC_RDES0_OWN: u32 = 0x80000000; // indicates that the descriptor is owned by the DMA
|
const EMAC_RDES0_OWN: u32 = 0x80000000; // indicates that the descriptor is owned by the DMA
|
||||||
const EMAC_RDES0_FL: u32 = 0x3FFF0000; // Frame Length
|
const EMAC_RDES0_FL: u32 = 0x3FFF0000; // Frame Length
|
||||||
const EMAC_RDES0_ES: u32 = 0x00008000; // Error Summary
|
const EMAC_RDES0_ES: u32 = 0x00008000; // Error Summary
|
||||||
const EMAC_RDES1_RCH: u32 = 0x00004000; // Second Address Chained
|
|
||||||
const EMAC_RDES1_RBS1: u32 = 0x00001FFF; // Receive Buffer 1 Size
|
|
||||||
const EMAC_RDES0_FS: u32 = 0x00000200; // First Descriptor
|
const EMAC_RDES0_FS: u32 = 0x00000200; // First Descriptor
|
||||||
const EMAC_RDES0_LS: u32 = 0x00000100; // Last Descriptor
|
const EMAC_RDES0_LS: u32 = 0x00000100; // Last Descriptor
|
||||||
|
const EMAC_RDES1_RCH: u32 = 0x00004000; // Second Address Chained
|
||||||
|
const EMAC_RDES1_RBS1: u32 = 0x00001FFF; // Receive Buffer 1 Size
|
||||||
|
|
||||||
const ETH_DESC_U32_SIZE: usize = 8;
|
const ETH_DESC_U32_SIZE: usize = 8;
|
||||||
const ETH_TX_BUFFER_COUNT: usize = 2;
|
const ETH_TX_BUFFER_COUNT: usize = 2;
|
||||||
|
@ -97,7 +99,7 @@ fn phy_write_ext(reg_addr: u8, reg_data: u16) {
|
||||||
phy_write(EPHY_ADDAR, reg_data);
|
phy_write(EPHY_ADDAR, reg_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EthernetDevice {
|
struct DeviceInner {
|
||||||
tx_desc_buf: [u32; ETH_TX_BUFFER_COUNT * ETH_DESC_U32_SIZE],
|
tx_desc_buf: [u32; ETH_TX_BUFFER_COUNT * ETH_DESC_U32_SIZE],
|
||||||
rx_desc_buf: [u32; ETH_RX_BUFFER_COUNT * ETH_DESC_U32_SIZE],
|
rx_desc_buf: [u32; ETH_RX_BUFFER_COUNT * ETH_DESC_U32_SIZE],
|
||||||
tx_cur_desc: usize,
|
tx_cur_desc: usize,
|
||||||
|
@ -108,9 +110,9 @@ pub struct EthernetDevice {
|
||||||
rx_pkt_buf: [u8; ETH_RX_BUFFER_COUNT * ETH_RX_BUFFER_SIZE],
|
rx_pkt_buf: [u8; ETH_RX_BUFFER_COUNT * ETH_RX_BUFFER_SIZE],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EthernetDevice {
|
impl DeviceInner {
|
||||||
pub fn new() -> EthernetDevice {
|
fn new() -> DeviceInner {
|
||||||
EthernetDevice {
|
DeviceInner {
|
||||||
tx_desc_buf: [0; ETH_TX_BUFFER_COUNT * ETH_DESC_U32_SIZE],
|
tx_desc_buf: [0; ETH_TX_BUFFER_COUNT * ETH_DESC_U32_SIZE],
|
||||||
rx_desc_buf: [0; ETH_RX_BUFFER_COUNT * ETH_DESC_U32_SIZE],
|
rx_desc_buf: [0; ETH_RX_BUFFER_COUNT * ETH_DESC_U32_SIZE],
|
||||||
tx_cur_desc: 0,
|
tx_cur_desc: 0,
|
||||||
|
@ -122,7 +124,7 @@ impl EthernetDevice {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(&mut self, mac_addr: EthernetAddress) {
|
fn init(&mut self, mac_addr: EthernetAddress) {
|
||||||
// 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;
|
||||||
|
@ -287,105 +289,51 @@ impl EthernetDevice {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn release_rx_buf(&mut self) {
|
// RX buffer functions
|
||||||
|
|
||||||
|
fn rx_buf_owned(&self) -> bool {
|
||||||
|
self.rx_desc_buf[self.rx_cur_desc + 0] & EMAC_RDES0_OWN == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rx_buf_valid(&self) -> bool {
|
||||||
|
self.rx_desc_buf[self.rx_cur_desc + 0] &
|
||||||
|
(EMAC_RDES0_FS | EMAC_RDES0_LS | EMAC_RDES0_ES) ==
|
||||||
|
(EMAC_RDES0_FS | EMAC_RDES0_LS)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn rx_buf_as_slice<'a>(&self) -> &'a [u8] {
|
||||||
|
let len = (self.rx_desc_buf[self.rx_cur_desc + 0] & EMAC_RDES0_FL) >> 16;
|
||||||
|
let len = cmp::max(len as usize, ETH_RX_BUFFER_SIZE);
|
||||||
|
let addr = self.rx_desc_buf[self.rx_cur_desc + 2] as *const u8;
|
||||||
|
slice::from_raw_parts(addr, len)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rx_buf_release(&mut self) {
|
||||||
|
self.rx_desc_buf[self.rx_cur_desc + 0] = EMAC_RDES0_OWN;
|
||||||
|
|
||||||
self.rx_cur_desc += ETH_DESC_U32_SIZE;
|
self.rx_cur_desc += ETH_DESC_U32_SIZE;
|
||||||
if self.rx_cur_desc >= (ETH_RX_BUFFER_COUNT * ETH_DESC_U32_SIZE) {
|
if self.rx_cur_desc == self.rx_desc_buf.len() {
|
||||||
self.rx_cur_desc = 0;
|
self.rx_cur_desc = 0;
|
||||||
}
|
}
|
||||||
self.rx_desc_buf[self.rx_cur_desc + 0] = EMAC_RDES0_OWN; // release descriptor
|
self.rx_counter += 1;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Device for EthernetDevice {
|
|
||||||
type RxBuffer = RxBuffer;
|
|
||||||
type TxBuffer = TxBuffer;
|
|
||||||
|
|
||||||
fn limits(&self) -> DeviceLimits {
|
|
||||||
let mut limits = DeviceLimits::default();
|
|
||||||
limits.max_transmission_unit = 1500;
|
|
||||||
limits.max_burst_size = Some(ETH_RX_BUFFER_COUNT);
|
|
||||||
limits
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn receive(&mut self, _timestamp: u64) -> Result<Self::RxBuffer, Error> {
|
// TX buffer functions
|
||||||
if (self.rx_desc_buf[self.rx_cur_desc + 0] & EMAC_RDES0_OWN) == 0 {
|
|
||||||
// check for the whole packet in the buffer and no any error
|
fn tx_buf_owned(&self) -> bool {
|
||||||
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) {
|
self.tx_desc_buf[self.tx_cur_desc + 0] & EMAC_TDES0_OWN == 0
|
||||||
// Retrieve the length of the frame
|
|
||||||
let mut n = (self.rx_desc_buf[self.rx_cur_desc + 0] & EMAC_RDES0_FL) >> 16;
|
|
||||||
// Limit the number of data to read
|
|
||||||
if n > ETH_RX_BUFFER_SIZE as u32 { n = ETH_RX_BUFFER_SIZE as u32; }
|
|
||||||
let sl = unsafe {
|
|
||||||
slice::from_raw_parts(self.rx_desc_buf[self.rx_cur_desc + 2] as * mut u8,
|
|
||||||
n as usize)
|
|
||||||
};
|
|
||||||
Ok(RxBuffer(sl, self))
|
|
||||||
} else {
|
|
||||||
// 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> {
|
unsafe fn tx_buf_as_slice<'a>(&mut self, len: usize) -> &'a mut [u8] {
|
||||||
// Check if the TX DMA buffer released
|
let len = cmp::max(len, ETH_TX_BUFFER_SIZE);
|
||||||
if (self.tx_desc_buf[self.tx_cur_desc + 0] & EMAC_TDES0_OWN) == 0 {
|
self.tx_desc_buf[self.tx_cur_desc + 1] = len as u32;
|
||||||
// Write the number of bytes to send
|
let addr = self.tx_desc_buf[self.tx_cur_desc + 2] as *mut u8;
|
||||||
self.tx_desc_buf[self.tx_cur_desc + 1] = length as u32 & EMAC_TDES1_TBS1;
|
slice::from_raw_parts_mut(addr, len)
|
||||||
|
|
||||||
let sl = unsafe {
|
|
||||||
slice::from_raw_parts_mut(self.tx_desc_buf[self.tx_cur_desc + 2] as * mut u8,
|
|
||||||
length)
|
|
||||||
};
|
|
||||||
Ok(TxBuffer(sl, self))
|
|
||||||
} else {
|
|
||||||
// to do if need: Instruct the DMA to poll the receive descriptor list
|
|
||||||
Err(Error::Exhausted)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RxBuffer(*const [u8], *mut EthernetDevice);
|
fn tx_buf_release(&mut self) {
|
||||||
|
self.tx_desc_buf[self.tx_cur_desc + 0] =
|
||||||
impl AsRef<[u8]> for RxBuffer {
|
EMAC_TDES0_OWN | EMAC_TDES0_LS | EMAC_TDES0_FS | EMAC_TDES0_TCH;
|
||||||
fn as_ref(&self) -> &[u8] {
|
|
||||||
unsafe { &*self.0 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for RxBuffer {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
let mut device = unsafe { &mut *self.1 };
|
|
||||||
device.release_rx_buf();
|
|
||||||
device.rx_counter += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TxBuffer(*mut [u8], *mut EthernetDevice);
|
|
||||||
|
|
||||||
impl AsRef<[u8]> for TxBuffer {
|
|
||||||
fn as_ref(&self) -> &[u8] {
|
|
||||||
unsafe { &*self.0 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsMut<[u8]> for TxBuffer {
|
|
||||||
fn as_mut(&mut self) -> &mut [u8] {
|
|
||||||
unsafe { &mut *self.0 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for TxBuffer {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
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
|
|
||||||
device.tx_desc_buf[device.tx_cur_desc + 0] = EMAC_TDES0_LS | EMAC_TDES0_FS | EMAC_TDES0_TCH;
|
|
||||||
device.tx_desc_buf[device.tx_cur_desc + 0] |= EMAC_TDES0_OWN; // Set ownership for DMA here
|
|
||||||
|
|
||||||
cortex_m::interrupt::free(|cs| {
|
cortex_m::interrupt::free(|cs| {
|
||||||
let emac0 = tm4c129x::EMAC0.borrow(cs);
|
let emac0 = tm4c129x::EMAC0.borrow(cs);
|
||||||
|
@ -395,13 +343,85 @@ impl Drop for TxBuffer {
|
||||||
unsafe { emac0.txpolld.write(|w| w.tpd().bits(0)); }
|
unsafe { emac0.txpolld.write(|w| w.tpd().bits(0)); }
|
||||||
});
|
});
|
||||||
|
|
||||||
// Calculate next DMA descriptor offset
|
self.tx_cur_desc += ETH_DESC_U32_SIZE;
|
||||||
let mut tx_next_desc = device.tx_cur_desc + ETH_DESC_U32_SIZE;
|
if self.tx_cur_desc == self.tx_desc_buf.len() {
|
||||||
if tx_next_desc >= (ETH_TX_BUFFER_COUNT * ETH_DESC_U32_SIZE) {
|
self.tx_cur_desc = 0;
|
||||||
tx_next_desc = 0;
|
|
||||||
}
|
}
|
||||||
device.tx_cur_desc = tx_next_desc;
|
self.tx_counter += 1;
|
||||||
|
}
|
||||||
device.tx_counter += 1;
|
}
|
||||||
|
|
||||||
|
pub struct Device(RefCell<DeviceInner>);
|
||||||
|
|
||||||
|
impl Device {
|
||||||
|
pub fn new(mac: EthernetAddress) -> Device {
|
||||||
|
let mut inner = DeviceInner::new();
|
||||||
|
inner.init(mac);
|
||||||
|
Device(RefCell::new(inner))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> phy::Device<'a> for Device {
|
||||||
|
type RxToken = RxToken<'a>;
|
||||||
|
type TxToken = TxToken<'a>;
|
||||||
|
|
||||||
|
fn capabilities(&self) -> phy::DeviceCapabilities {
|
||||||
|
let mut capabilities = phy::DeviceCapabilities::default();
|
||||||
|
capabilities.max_transmission_unit = 1500;
|
||||||
|
capabilities.max_burst_size = Some(ETH_RX_BUFFER_COUNT);
|
||||||
|
capabilities
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive(&mut self) -> Option<(RxToken, TxToken)> {
|
||||||
|
{
|
||||||
|
let mut device = self.0.borrow_mut();
|
||||||
|
|
||||||
|
// Skip all queued packets with errors.
|
||||||
|
while device.rx_buf_owned() && !device.rx_buf_valid() {
|
||||||
|
device.rx_buf_release()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !(device.rx_buf_owned() && device.tx_buf_owned()) {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some((RxToken(&self.0), TxToken(&self.0)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn transmit(&mut self) -> Option<TxToken> {
|
||||||
|
{
|
||||||
|
let device = self.0.borrow_mut();
|
||||||
|
|
||||||
|
if !device.tx_buf_owned() {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(TxToken(&self.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RxToken<'a>(&'a RefCell<DeviceInner>);
|
||||||
|
|
||||||
|
impl<'a> phy::RxToken for RxToken<'a> {
|
||||||
|
fn consume<R, F>(self, _timestamp: u64, f: F) -> Result<R>
|
||||||
|
where F: FnOnce(&[u8]) -> Result<R> {
|
||||||
|
let mut device = self.0.borrow_mut();
|
||||||
|
let result = f(unsafe { device.rx_buf_as_slice() });
|
||||||
|
device.rx_buf_release();
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TxToken<'a>(&'a RefCell<DeviceInner>);
|
||||||
|
|
||||||
|
impl<'a> phy::TxToken for TxToken<'a> {
|
||||||
|
fn consume<R, F>(self, _timestamp: u64, len: usize, f: F) -> Result<R>
|
||||||
|
where F: FnOnce(&mut [u8]) -> Result<R> {
|
||||||
|
let mut device = self.0.borrow_mut();
|
||||||
|
let result = f(unsafe { device.tx_buf_as_slice(len) });
|
||||||
|
device.tx_buf_release();
|
||||||
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,8 @@ use core::cell::{Cell, RefCell};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use cortex_m::interrupt::Mutex;
|
use cortex_m::interrupt::Mutex;
|
||||||
use smoltcp::wire::EthernetAddress;
|
use smoltcp::wire::EthernetAddress;
|
||||||
use smoltcp::iface::{ArpCache, SliceArpCache, EthernetInterface};
|
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
|
||||||
use smoltcp::socket::{AsSocket, SocketSet};
|
use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
|
||||||
use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! print {
|
macro_rules! print {
|
||||||
|
@ -160,15 +159,16 @@ fn main() {
|
||||||
println!("programmed MAC address is invalid, using default");
|
println!("programmed MAC address is invalid, using default");
|
||||||
hardware_addr = EthernetAddress([0x10, 0xE2, 0xD5, 0x00, 0x03, 0x00]);
|
hardware_addr = EthernetAddress([0x10, 0xE2, 0xD5, 0x00, 0x03, 0x00]);
|
||||||
}
|
}
|
||||||
let mut protocol_addrs = [config.ip];
|
let mut ip_addrs = [config.ip];
|
||||||
println!("MAC {} IP {}", hardware_addr, protocol_addrs[0]);
|
println!("MAC {} IP {}", hardware_addr, ip_addrs[0]);
|
||||||
let mut arp_cache_entries: [_; 8] = Default::default();
|
let mut neighbor_cache_storage = [None; 8];
|
||||||
let mut arp_cache = SliceArpCache::new(&mut arp_cache_entries[..]);
|
let neighbor_cache = NeighborCache::new(&mut neighbor_cache_storage[..]);
|
||||||
let mut device = ethmac::EthernetDevice::new();
|
let device = ethmac::Device::new(hardware_addr);
|
||||||
device.init(hardware_addr);
|
let mut iface = EthernetInterfaceBuilder::new(device)
|
||||||
let mut iface = EthernetInterface::new(
|
.ethernet_addr(hardware_addr)
|
||||||
&mut device, &mut arp_cache as &mut ArpCache,
|
.neighbor_cache(neighbor_cache)
|
||||||
hardware_addr, &mut protocol_addrs[..]);
|
.ip_addrs(&mut ip_addrs[..])
|
||||||
|
.finalize();
|
||||||
|
|
||||||
create_socket_storage!(tcp_rx_storage0, tcp_tx_storage0);
|
create_socket_storage!(tcp_rx_storage0, tcp_tx_storage0);
|
||||||
create_socket_storage!(tcp_rx_storage1, tcp_tx_storage1);
|
create_socket_storage!(tcp_rx_storage1, tcp_tx_storage1);
|
||||||
|
@ -211,18 +211,14 @@ fn main() {
|
||||||
loop {
|
loop {
|
||||||
let time = get_time_ms();
|
let time = get_time_ms();
|
||||||
|
|
||||||
for &mut(ref mut request, ref tcp_handle) in sessions.iter_mut() {
|
for &mut(ref mut request, tcp_handle) in sessions.iter_mut() {
|
||||||
let socket: &mut TcpSocket = sockets.get_mut(*tcp_handle).as_socket();
|
let socket = &mut *sockets.get::<TcpSocket>(tcp_handle);
|
||||||
if !socket.is_open() {
|
if !socket.is_open() {
|
||||||
socket.listen(80).unwrap()
|
socket.listen(80).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
if socket.may_recv() {
|
if socket.may_recv() {
|
||||||
let request_status = {
|
match socket.recv(|data| (data.len(), request.input(data))).unwrap() {
|
||||||
let data = socket.recv(TCP_RX_BUFFER_SIZE).unwrap();
|
|
||||||
request.input(data)
|
|
||||||
};
|
|
||||||
match request_status {
|
|
||||||
Ok(true) => {
|
Ok(true) => {
|
||||||
if socket.can_send() {
|
if socket.can_send() {
|
||||||
pages::serve(socket, &request, &mut config, &LOOP_ANODE, &LOOP_CATHODE, &ELECTROMETER);
|
pages::serve(socket, &request, &mut config, &LOOP_ANODE, &LOOP_CATHODE, &ELECTROMETER);
|
||||||
|
|
Loading…
Reference in New Issue