Add smoltcp Phy impls
This commit is contained in:
parent
5deab5db9b
commit
dd062723a3
|
@ -108,9 +108,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embedded-hal"
|
name = "embedded-hal"
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ee4908a155094da7723c2d60d617b820061e3b4efcc3d9e293d206a5a76c170b"
|
checksum = "fa998ce59ec9765d15216393af37a58961ddcefb14c753b4816ba2191d865fcb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nb",
|
"nb",
|
||||||
"void",
|
"void",
|
||||||
|
@ -281,9 +281,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.31"
|
version = "1.0.33"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5304cfdf27365b7585c25d4af91b35016ed21ef88f17ced89c7093b43dba8b6"
|
checksum = "e8d5d96e8cbb005d6959f119f773bfaebb5684296108fb32600c00cde305b2cd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -298,9 +298,9 @@ checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vcell"
|
name = "vcell"
|
||||||
|
|
10
Cargo.toml
10
Cargo.toml
|
@ -13,10 +13,14 @@ volatile-register = "0.2"
|
||||||
aligned = "0.3"
|
aligned = "0.3"
|
||||||
stm32f4xx-hal = { version = "0.8" , optional = true }
|
stm32f4xx-hal = { version = "0.8" , optional = true }
|
||||||
smoltcp = { version = "0.6.0", default-features = false, features = ["proto-ipv4", "proto-ipv6", "socket-icmp", "socket-udp", "socket-tcp", "log", "verbose", "ethernet"], optional = true }
|
smoltcp = { version = "0.6.0", default-features = false, features = ["proto-ipv4", "proto-ipv6", "socket-icmp", "socket-udp", "socket-tcp", "log", "verbose", "ethernet"], optional = true }
|
||||||
log = { version = "0.4" }
|
log = "0.4"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
smoltcp-phy = ["smoltcp"]
|
smoltcp-phy = ["smoltcp"]
|
||||||
|
smoltcp-phy-all = [
|
||||||
|
"smoltcp/socket-raw", "smoltcp/socket-udp", "smoltcp/socket-tcp",
|
||||||
|
"smoltcp/proto-ipv4", "smoltcp/proto-ipv6"
|
||||||
|
]
|
||||||
stm32f407 = ["stm32f4xx-hal/stm32f407"]
|
stm32f407 = ["stm32f4xx-hal/stm32f407"]
|
||||||
default = []
|
default = []
|
||||||
|
|
||||||
|
@ -30,6 +34,10 @@ panic-itm = "0.4"
|
||||||
name = "tx_stm32f407"
|
name = "tx_stm32f407"
|
||||||
required-features = ["stm32f407"]
|
required-features = ["stm32f407"]
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "tcp_stm32f407"
|
||||||
|
required-features = ["stm32f407", "smoltcp-phy-all", "smoltcp/log"]
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
incremental = false
|
incremental = false
|
||||||
|
|
51
src/lib.rs
51
src/lib.rs
|
@ -1,7 +1,5 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
use core::fmt;
|
|
||||||
|
|
||||||
/// STM32F4xx-HAL specific implementations
|
/// STM32F4xx-HAL specific implementations
|
||||||
pub mod spi;
|
pub mod spi;
|
||||||
use stm32f4xx_hal::{
|
use stm32f4xx_hal::{
|
||||||
|
@ -17,14 +15,12 @@ pub mod tx;
|
||||||
#[cfg(feature="smoltcp")]
|
#[cfg(feature="smoltcp")]
|
||||||
pub mod smoltcp_phy;
|
pub mod smoltcp_phy;
|
||||||
|
|
||||||
pub trait EthController {
|
pub trait EthController<'c> {
|
||||||
fn init_dev(&mut self) -> Result<(), EthControllerError>;
|
fn init_dev(&mut self) -> Result<(), EthControllerError>;
|
||||||
fn init_rxbuf(&mut self) -> Result<(), EthControllerError>;
|
fn init_rxbuf(&mut self) -> Result<(), EthControllerError>;
|
||||||
// TODO:
|
|
||||||
fn init_txbuf(&mut self) -> Result<(), EthControllerError>;
|
fn init_txbuf(&mut self) -> Result<(), EthControllerError>;
|
||||||
fn receive_next(&mut self) -> Result<rx::RxPacket, EthControllerError>;
|
fn receive_next(&mut self, is_poll: bool) -> Result<rx::RxPacket, EthControllerError>;
|
||||||
// TODO: send_packet() is not using TxBuffer, but it should later on
|
fn send_raw_packet(&mut self, packet: &tx::TxPacket) -> Result<(), EthControllerError>;
|
||||||
fn send_raw_packet(&mut self, packet: tx::TxPacket) -> Result<(), EthControllerError>;
|
|
||||||
fn set_promiscuous(&mut self) -> Result<(), EthControllerError>;
|
fn set_promiscuous(&mut self) -> Result<(), EthControllerError>;
|
||||||
fn read_from_mac(&mut self, mac: &mut [u8]) -> Result<(), EthControllerError>;
|
fn read_from_mac(&mut self, mac: &mut [u8]) -> Result<(), EthControllerError>;
|
||||||
}
|
}
|
||||||
|
@ -32,11 +28,13 @@ pub trait EthController {
|
||||||
/// TODO: Improve these error types
|
/// TODO: Improve these error types
|
||||||
pub enum EthControllerError {
|
pub enum EthControllerError {
|
||||||
SpiPortError,
|
SpiPortError,
|
||||||
GeneralError
|
GeneralError,
|
||||||
|
// TODO: Better name?
|
||||||
|
NoRxPacketError
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<spi::SpiPortError> for EthControllerError {
|
impl From<spi::SpiPortError> for EthControllerError {
|
||||||
fn from(e: spi::SpiPortError) -> EthControllerError {
|
fn from(_: spi::SpiPortError) -> EthControllerError {
|
||||||
EthControllerError::SpiPortError
|
EthControllerError::SpiPortError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,18 +49,17 @@ pub struct SpiEth<SPI: Transfer<u8>,
|
||||||
|
|
||||||
impl <SPI: Transfer<u8>,
|
impl <SPI: Transfer<u8>,
|
||||||
NSS: OutputPin> SpiEth<SPI, NSS> {
|
NSS: OutputPin> SpiEth<SPI, NSS> {
|
||||||
pub fn new(spi: SPI, mut nss: NSS) -> Self {
|
pub fn new(spi: SPI, nss: NSS) -> Self {
|
||||||
SpiEth {
|
SpiEth {
|
||||||
spi_port: spi::SpiPort::new(spi, nss),
|
spi_port: spi::SpiPort::new(spi, nss),
|
||||||
rx_buf: rx::RxBuffer::new(),
|
rx_buf: rx::RxBuffer::new(),
|
||||||
// TODO: tx_buf
|
|
||||||
tx_buf: tx::TxBuffer::new()
|
tx_buf: tx::TxBuffer::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <SPI: Transfer<u8>,
|
impl <'c, SPI: Transfer<u8>,
|
||||||
NSS: OutputPin> EthController for SpiEth<SPI, NSS> {
|
NSS: OutputPin> EthController<'c> for SpiEth<SPI, NSS> {
|
||||||
fn init_dev(&mut self) -> Result<(), EthControllerError> {
|
fn init_dev(&mut self) -> Result<(), EthControllerError> {
|
||||||
// Write 0x1234 to EUDAST
|
// Write 0x1234 to EUDAST
|
||||||
self.spi_port.write_reg_16b(spi::EUDAST, 0x1234)?;
|
self.spi_port.write_reg_16b(spi::EUDAST, 0x1234)?;
|
||||||
|
@ -96,23 +93,27 @@ impl <SPI: Transfer<u8>,
|
||||||
self.spi_port.write_reg_16b(spi::MAMXFL, rx::RAW_FRAME_LENGTH_MAX as u16)?;
|
self.spi_port.write_reg_16b(spi::MAMXFL, rx::RAW_FRAME_LENGTH_MAX as u16)?;
|
||||||
// Enable RXEN (ECON1<0>)
|
// Enable RXEN (ECON1<0>)
|
||||||
let econ1 = self.spi_port.read_reg_16b(spi::ECON1)?;
|
let econ1 = self.spi_port.read_reg_16b(spi::ECON1)?;
|
||||||
self.spi_port.write_reg_16b(spi::ECON1, 0x1 | (econ1 & 0xfffe));
|
self.spi_port.write_reg_16b(spi::ECON1, 0x1 | (econ1 & 0xfffe))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO:
|
|
||||||
fn init_txbuf(&mut self) -> Result<(), EthControllerError> {
|
fn init_txbuf(&mut self) -> Result<(), EthControllerError> {
|
||||||
// Set EGPWRPT pointer
|
// Set EGPWRPT pointer
|
||||||
self.spi_port.write_reg_16b(spi::EGPWRPT, 0x0000)?;
|
self.spi_port.write_reg_16b(spi::EGPWRPT, 0x0000)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Receive the next packet
|
/// Receive the next packet and copy it to rx_packet_buf
|
||||||
fn receive_next(&mut self) -> Result<rx::RxPacket, EthControllerError> {
|
/// Set is_poll to true for returning until PKTIF is set;
|
||||||
|
/// Set is_poll to false for returning Err when PKTIF is not set
|
||||||
|
fn receive_next(&mut self, is_poll: bool) -> Result<rx::RxPacket, EthControllerError> {
|
||||||
// Poll PKTIF (EIR<4>) to check if it is set
|
// Poll PKTIF (EIR<4>) to check if it is set
|
||||||
loop {
|
loop {
|
||||||
let eir = self.spi_port.read_reg_16b(spi::EIR)?;
|
let eir = self.spi_port.read_reg_16b(spi::EIR)?;
|
||||||
if eir & 0x40 == 0x40 { break }
|
if eir & 0x40 == 0x40 { break }
|
||||||
|
if !is_poll {
|
||||||
|
return Err(EthControllerError::NoRxPacketError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Set ERXRDPT pointer to next_addr
|
// Set ERXRDPT pointer to next_addr
|
||||||
self.spi_port.write_reg_16b(spi::ERXRDPT, self.rx_buf.get_next_addr())?;
|
self.spi_port.write_reg_16b(spi::ERXRDPT, self.rx_buf.get_next_addr())?;
|
||||||
|
@ -132,7 +133,7 @@ impl <SPI: Transfer<u8>,
|
||||||
// Read frame bytes
|
// Read frame bytes
|
||||||
let mut frame_buf = [0; rx::RAW_FRAME_LENGTH_MAX];
|
let mut frame_buf = [0; rx::RAW_FRAME_LENGTH_MAX];
|
||||||
self.spi_port.read_rxdat(&mut frame_buf, rx_packet.get_frame_length() as u32)?;
|
self.spi_port.read_rxdat(&mut frame_buf, rx_packet.get_frame_length() as u32)?;
|
||||||
rx_packet.write_to_frame(&frame_buf[1..]);
|
rx_packet.copy_frame_from(&frame_buf[1..]);
|
||||||
// Set ERXTAIL pointer to (next_addr - 2)
|
// Set ERXTAIL pointer to (next_addr - 2)
|
||||||
if self.rx_buf.get_next_addr() > rx::ERXST_DEFAULT {
|
if self.rx_buf.get_next_addr() > rx::ERXST_DEFAULT {
|
||||||
self.spi_port.write_reg_16b(spi::ERXTAIL, self.rx_buf.get_next_addr() - 2)?;
|
self.spi_port.write_reg_16b(spi::ERXTAIL, self.rx_buf.get_next_addr() - 2)?;
|
||||||
|
@ -147,14 +148,13 @@ impl <SPI: Transfer<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send an established packet
|
/// Send an established packet
|
||||||
/// TODO: Should be eliminated when TxBuffer is used instead later on
|
fn send_raw_packet(&mut self, packet: &tx::TxPacket) -> Result<(), EthControllerError> {
|
||||||
fn send_raw_packet(&mut self, packet: tx::TxPacket) -> Result<(), EthControllerError> {
|
|
||||||
// Set EGPWRPT pointer to next_addr
|
// Set EGPWRPT pointer to next_addr
|
||||||
self.spi_port.write_reg_16b(spi::EGPWRPT, self.tx_buf.get_next_addr())?;
|
self.spi_port.write_reg_16b(spi::EGPWRPT, self.tx_buf.get_next_addr())?;
|
||||||
// Copy packet data to SRAM Buffer
|
// Copy packet data to SRAM Buffer
|
||||||
// 1-byte Opcode is included
|
// 1-byte Opcode is included
|
||||||
let mut txdat_buf: [u8; tx::RAW_FRAME_LENGTH_MAX + 1] = [0; tx::RAW_FRAME_LENGTH_MAX + 1];
|
let mut txdat_buf: [u8; tx::RAW_FRAME_LENGTH_MAX + 1] = [0; tx::RAW_FRAME_LENGTH_MAX + 1];
|
||||||
packet.copy_from_frame(&mut txdat_buf[1..]);
|
packet.write_frame_to(&mut txdat_buf[1..]);
|
||||||
self.spi_port.write_txdat(&mut txdat_buf, packet.get_frame_length() as u32)?;
|
self.spi_port.write_txdat(&mut txdat_buf, packet.get_frame_length() as u32)?;
|
||||||
// Set ETXST to packet start address
|
// Set ETXST to packet start address
|
||||||
self.spi_port.write_reg_16b(spi::ETXST, self.tx_buf.get_next_addr())?;
|
self.spi_port.write_reg_16b(spi::ETXST, self.tx_buf.get_next_addr())?;
|
||||||
|
@ -168,7 +168,8 @@ impl <SPI: Transfer<u8>,
|
||||||
econ1_lo = self.spi_port.read_reg_8b(spi::ECON1)?;
|
econ1_lo = self.spi_port.read_reg_8b(spi::ECON1)?;
|
||||||
if econ1_lo & 0x02 == 0x02 { break }
|
if econ1_lo & 0x02 == 0x02 { break }
|
||||||
}
|
}
|
||||||
// TODO: Read ETXSTAT
|
// TODO: Read ETXSTAT to understand Ethernet transmission status
|
||||||
|
// (See: Register 9-2, ENC424J600 Data Sheet)
|
||||||
// Update TX buffer start address
|
// Update TX buffer start address
|
||||||
self.tx_buf.set_next_addr((self.tx_buf.get_next_addr() + packet.get_frame_length() as u16) %
|
self.tx_buf.set_next_addr((self.tx_buf.get_next_addr() + packet.get_frame_length() as u16) %
|
||||||
tx::GPBUFEN_DEFAULT);
|
tx::GPBUFEN_DEFAULT);
|
||||||
|
@ -177,11 +178,11 @@ impl <SPI: Transfer<u8>,
|
||||||
|
|
||||||
/// Set controller to Promiscuous Mode
|
/// Set controller to Promiscuous Mode
|
||||||
fn set_promiscuous(&mut self) -> Result<(), EthControllerError> {
|
fn set_promiscuous(&mut self) -> Result<(), EthControllerError> {
|
||||||
// From ENC424J600 Data Sheet Section 10.12:
|
// From Section 10.12, ENC424J600 Data Sheet:
|
||||||
// "To accept all incoming frames regardless of content (Promiscuous mode),
|
// "To accept all incoming frames regardless of content (Promiscuous mode),
|
||||||
// set the CRCEN, RUNTEN, UCEN, NOTMEEN and MCEN bits."
|
// set the CRCEN, RUNTEN, UCEN, NOTMEEN and MCEN bits."
|
||||||
let mut erxfcon_lo = self.spi_port.read_reg_8b(spi::ERXFCON)?;
|
let erxfcon_lo = self.spi_port.read_reg_8b(spi::ERXFCON)?;
|
||||||
self.spi_port.write_reg_8b(spi::ERXFCON, 0b0101_1110 | (erxfcon_lo & 0b1010_0001));
|
self.spi_port.write_reg_8b(spi::ERXFCON, 0b0101_1110 | (erxfcon_lo & 0b1010_0001))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
src/rx.rs
13
src/rx.rs
|
@ -8,7 +8,7 @@ pub const RAW_FRAME_LENGTH_MAX: usize = 0x1000;
|
||||||
/// Receive Status Vector Length
|
/// Receive Status Vector Length
|
||||||
pub const RSV_LENGTH: usize = 6;
|
pub const RSV_LENGTH: usize = 6;
|
||||||
|
|
||||||
/// Struct for RX Buffer
|
/// Struct for RX Buffer on the hardware
|
||||||
/// TODO: Should be a singleton
|
/// TODO: Should be a singleton
|
||||||
pub struct RxBuffer {
|
pub struct RxBuffer {
|
||||||
wrap_addr: u16,
|
wrap_addr: u16,
|
||||||
|
@ -80,11 +80,20 @@ impl RxPacket {
|
||||||
self.frame_length
|
self.frame_length
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_to_frame(&mut self, raw_frame: &[u8]) {
|
pub fn copy_frame_from(&mut self, raw_frame: &[u8]) {
|
||||||
for i in 0..self.frame_length {
|
for i in 0..self.frame_length {
|
||||||
self.frame[i] = raw_frame[i];
|
self.frame[i] = raw_frame[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn write_frame_to(&self, frame: &mut [u8]) {
|
||||||
|
for i in 0..self.frame_length {
|
||||||
|
frame[i] = self.frame[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_mut_frame(&mut self) -> &mut [u8] {
|
||||||
|
&mut self.frame
|
||||||
|
}
|
||||||
|
|
||||||
/// TODO: Mostly for debugging only?
|
/// TODO: Mostly for debugging only?
|
||||||
pub fn get_frame_byte(&self, i: usize) -> u8 {
|
pub fn get_frame_byte(&self, i: usize) -> u8 {
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
use crate::{
|
||||||
|
EthController, rx, tx
|
||||||
|
};
|
||||||
|
use core::intrinsics::transmute;
|
||||||
|
use smoltcp::{
|
||||||
|
phy::{Device, DeviceCapabilities, RxToken, TxToken},
|
||||||
|
time::Instant,
|
||||||
|
Error
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct SmoltcpDevice<'c> {
|
||||||
|
eth_controller: &'c mut dyn EthController<'c>,
|
||||||
|
rx_packet_buf: [u8; rx::RAW_FRAME_LENGTH_MAX],
|
||||||
|
tx_packet_buf: [u8; tx::RAW_FRAME_LENGTH_MAX]
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'c> SmoltcpDevice<'c> {
|
||||||
|
pub fn new(eth_controller: &'c mut dyn EthController<'c>) -> Self {
|
||||||
|
SmoltcpDevice {
|
||||||
|
eth_controller,
|
||||||
|
rx_packet_buf: [0; rx::RAW_FRAME_LENGTH_MAX],
|
||||||
|
tx_packet_buf: [0; tx::RAW_FRAME_LENGTH_MAX]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'c> Device<'a> for SmoltcpDevice<'c> {
|
||||||
|
type RxToken = EthRxToken<'a>;
|
||||||
|
type TxToken = EthTxToken<'a>;
|
||||||
|
|
||||||
|
fn capabilities(&self) -> DeviceCapabilities {
|
||||||
|
DeviceCapabilities::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
|
||||||
|
// Extend self lifetime from 'c to 'a for tokens' access to EthController
|
||||||
|
let self_trans = unsafe {
|
||||||
|
transmute::<&mut SmoltcpDevice<'c>, &mut SmoltcpDevice<'a>>(&mut *self)
|
||||||
|
};
|
||||||
|
// Make self_a point to *self that has a lifetime of 'a (extended)
|
||||||
|
let self_a = self_trans as *mut SmoltcpDevice<'a>;
|
||||||
|
match self_trans.eth_controller.receive_next(false) {
|
||||||
|
Ok(rx_packet) => {
|
||||||
|
// Write received packet to RX packet buffer
|
||||||
|
rx_packet.write_frame_to(&mut self.rx_packet_buf);
|
||||||
|
// Construct a RxToken
|
||||||
|
let rx_token = EthRxToken {
|
||||||
|
buf: &mut self.rx_packet_buf,
|
||||||
|
len: rx_packet.get_frame_length()
|
||||||
|
};
|
||||||
|
// Construct a blank TxToken
|
||||||
|
let tx_token = EthTxToken {
|
||||||
|
buf: &mut self.tx_packet_buf,
|
||||||
|
dev: self_a
|
||||||
|
};
|
||||||
|
Some((rx_token, tx_token))
|
||||||
|
},
|
||||||
|
Err(_) => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn transmit(&'a mut self) -> Option<Self::TxToken> {
|
||||||
|
// Extend self lifetime from 'c to 'a for TxToken's access to EthController
|
||||||
|
let self_trans = unsafe {
|
||||||
|
transmute::<&mut SmoltcpDevice<'c>, &mut SmoltcpDevice<'a>>(&mut *self)
|
||||||
|
};
|
||||||
|
// Make self_a point to *self that has a lifetime of 'a (extended)
|
||||||
|
let self_a = self_trans as *mut SmoltcpDevice<'a>;
|
||||||
|
// Construct a blank TxToken
|
||||||
|
let tx_token = EthTxToken {
|
||||||
|
buf: &mut self.tx_packet_buf,
|
||||||
|
dev: self_a
|
||||||
|
};
|
||||||
|
Some(tx_token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EthRxToken<'a> {
|
||||||
|
buf: &'a mut [u8],
|
||||||
|
len: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> RxToken for EthRxToken<'a> {
|
||||||
|
fn consume<R, F>(self, _timestamp: Instant, f: F) -> Result<R, Error>
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut [u8]) -> Result<R, Error>,
|
||||||
|
{
|
||||||
|
f(&mut self.buf[..self.len])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EthTxToken<'a> {
|
||||||
|
buf: &'a mut [u8],
|
||||||
|
dev: *mut SmoltcpDevice<'a>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TxToken for EthTxToken<'a> {
|
||||||
|
fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R, Error>
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut [u8]) -> Result<R, Error>,
|
||||||
|
{
|
||||||
|
let result = f(&mut self.buf[..len]);
|
||||||
|
// Construct a TxPacket
|
||||||
|
let mut tx_packet = tx::TxPacket::new();
|
||||||
|
// Update frame length and write frame bytes
|
||||||
|
tx_packet.update_frame(&mut self.buf[..len], len);
|
||||||
|
// Send the packet as raw
|
||||||
|
let eth_controller = unsafe {
|
||||||
|
&mut (*self.dev).eth_controller
|
||||||
|
};
|
||||||
|
match eth_controller.send_raw_packet(&tx_packet) {
|
||||||
|
Ok(_) => { result },
|
||||||
|
Err(_) => Err(Error::Exhausted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
src/tx.rs
18
src/tx.rs
|
@ -5,7 +5,7 @@ pub const GPBUFEN_DEFAULT: u16 = 0x5340; // End of General-Purpose SRAM Buffe
|
||||||
/// Max raw frame array size
|
/// Max raw frame array size
|
||||||
pub const RAW_FRAME_LENGTH_MAX: usize = 0x1000;
|
pub const RAW_FRAME_LENGTH_MAX: usize = 0x1000;
|
||||||
|
|
||||||
/// Struct for TX Buffer
|
/// Struct for TX Buffer on the hardware
|
||||||
/// TODO: Should be a singleton
|
/// TODO: Should be a singleton
|
||||||
pub struct TxBuffer {
|
pub struct TxBuffer {
|
||||||
wrap_addr: u16,
|
wrap_addr: u16,
|
||||||
|
@ -37,7 +37,12 @@ impl TxBuffer {
|
||||||
self.next_addr
|
self.next_addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Need more functions for smoltcp::phy compatibility (maybe?)
|
pub fn set_tail_addr(&mut self, addr: u16) {
|
||||||
|
self.tail_addr = addr;
|
||||||
|
}
|
||||||
|
pub fn get_tail_addr(& self) -> u16{
|
||||||
|
self.tail_addr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Struct for TX Packet
|
/// Struct for TX Packet
|
||||||
|
@ -62,7 +67,7 @@ impl TxPacket {
|
||||||
self.frame[i] = raw_frame[i];
|
self.frame[i] = raw_frame[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn copy_from_frame(&self, frame: &mut [u8]) {
|
pub fn write_frame_to(&self, frame: &mut [u8]) {
|
||||||
for i in 0..self.frame_length {
|
for i in 0..self.frame_length {
|
||||||
frame[i] = self.frame[i];
|
frame[i] = self.frame[i];
|
||||||
}
|
}
|
||||||
|
@ -72,6 +77,13 @@ impl TxPacket {
|
||||||
self.frame_length
|
self.frame_length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_frame(&self) -> &[u8] {
|
||||||
|
&self.frame
|
||||||
|
}
|
||||||
|
pub fn get_mut_frame(&mut self) -> &mut [u8] {
|
||||||
|
&mut self.frame
|
||||||
|
}
|
||||||
|
|
||||||
/// TODO: Mostly for debugging only?
|
/// TODO: Mostly for debugging only?
|
||||||
pub fn get_frame_byte(&self, i: usize) -> u8 {
|
pub fn get_frame_byte(&self, i: usize) -> u8 {
|
||||||
self.frame[i]
|
self.frame[i]
|
||||||
|
|
Loading…
Reference in New Issue