Use core::cell::RefCell to refer to EthController

This commit is contained in:
Harry Ho 2020-12-29 11:43:55 +08:00
parent 4ba5052623
commit 25e682763c
3 changed files with 23 additions and 33 deletions

View File

@ -171,7 +171,7 @@ fn main() -> ! {
// Copied / modified from smoltcp: // Copied / modified from smoltcp:
// examples/loopback.rs, examples/multicast.rs // examples/loopback.rs, examples/multicast.rs
let device = smoltcp_phy::SmoltcpDevice::new(&mut spi_eth); let device = smoltcp_phy::SmoltcpDevice::new(spi_eth);
let mut neighbor_cache_entries = [None; 16]; let mut neighbor_cache_entries = [None; 16];
let neighbor_cache = NeighborCache::new(&mut neighbor_cache_entries[..]); let neighbor_cache = NeighborCache::new(&mut neighbor_cache_entries[..]);
let ip_addr = IpCidr::new(IpAddress::v4( let ip_addr = IpCidr::new(IpAddress::v4(

View File

@ -15,8 +15,8 @@ pub mod tx;
#[cfg(feature="smoltcp")] #[cfg(feature="smoltcp")]
pub mod smoltcp_phy; pub mod smoltcp_phy;
pub trait EthController<'c> { pub trait EthController {
fn init_dev(&mut self, delay: &mut dyn DelayUs<u16>) -> Result<(), EthControllerError>; fn init_dev(&mut self, delay: &mut impl DelayUs<u16>) -> Result<(), EthControllerError>;
fn init_rxbuf(&mut self) -> Result<(), EthControllerError>; fn init_rxbuf(&mut self) -> Result<(), EthControllerError>;
fn init_txbuf(&mut self) -> Result<(), EthControllerError>; fn init_txbuf(&mut self) -> Result<(), EthControllerError>;
fn receive_next(&mut self, is_poll: bool) -> Result<rx::RxPacket, EthControllerError>; fn receive_next(&mut self, is_poll: bool) -> Result<rx::RxPacket, EthControllerError>;
@ -58,9 +58,9 @@ impl <SPI: Transfer<u8>,
} }
} }
impl <'c, SPI: Transfer<u8>, impl <SPI: Transfer<u8>,
NSS: OutputPin> EthController<'c> for SpiEth<SPI, NSS> { NSS: OutputPin> EthController for SpiEth<SPI, NSS> {
fn init_dev(&mut self, delay: &mut dyn DelayUs<u16>) -> Result<(), EthControllerError> { fn init_dev(&mut self, delay: &mut impl DelayUs<u16>) -> Result<(), EthControllerError> {
// Write 0x1234 to EUDAST // Write 0x1234 to EUDAST
self.spi_port.write_reg_16b(spi::addrs::EUDAST, 0x1234)?; self.spi_port.write_reg_16b(spi::addrs::EUDAST, 0x1234)?;
// Verify that EUDAST is 0x1234 // Verify that EUDAST is 0x1234

View File

@ -1,45 +1,40 @@
use crate::{ use crate::{
EthController, rx, tx EthController, rx, tx
}; };
use core::intrinsics::transmute; use core::cell;
use smoltcp::{ use smoltcp::{
phy::{Device, DeviceCapabilities, RxToken, TxToken}, phy::{Device, DeviceCapabilities, RxToken, TxToken},
time::Instant, time::Instant,
Error Error
}; };
pub struct SmoltcpDevice<'c> { pub struct SmoltcpDevice<EC: EthController> {
eth_controller: &'c mut dyn EthController<'c>, pub eth_controller: cell::RefCell<EC>,
rx_packet_buf: [u8; rx::RAW_FRAME_LENGTH_MAX], rx_packet_buf: [u8; rx::RAW_FRAME_LENGTH_MAX],
tx_packet_buf: [u8; tx::RAW_FRAME_LENGTH_MAX] tx_packet_buf: [u8; tx::RAW_FRAME_LENGTH_MAX]
} }
impl<'c> SmoltcpDevice<'c> { impl<EC: EthController> SmoltcpDevice<EC> {
pub fn new(eth_controller: &'c mut dyn EthController<'c>) -> Self { pub fn new(eth_controller: EC) -> Self {
SmoltcpDevice { SmoltcpDevice {
eth_controller, eth_controller: cell::RefCell::new(eth_controller),
rx_packet_buf: [0; rx::RAW_FRAME_LENGTH_MAX], rx_packet_buf: [0; rx::RAW_FRAME_LENGTH_MAX],
tx_packet_buf: [0; tx::RAW_FRAME_LENGTH_MAX] tx_packet_buf: [0; tx::RAW_FRAME_LENGTH_MAX]
} }
} }
} }
impl<'a, 'c> Device<'a> for SmoltcpDevice<'c> { impl<'a, EC: 'a + EthController> Device<'a> for SmoltcpDevice<EC> {
type RxToken = EthRxToken<'a>; type RxToken = EthRxToken<'a>;
type TxToken = EthTxToken<'a>; type TxToken = EthTxToken<'a, EC>;
fn capabilities(&self) -> DeviceCapabilities { fn capabilities(&self) -> DeviceCapabilities {
DeviceCapabilities::default() DeviceCapabilities::default()
} }
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> { fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
// Extend self lifetime from 'c to 'a for tokens' access to EthController let self_p = (&mut *self) as *mut SmoltcpDevice<EC>;
let self_trans = unsafe { match self.eth_controller.borrow_mut().receive_next(false) {
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) => { Ok(rx_packet) => {
// Write received packet to RX packet buffer // Write received packet to RX packet buffer
rx_packet.write_frame_to(&mut self.rx_packet_buf); rx_packet.write_frame_to(&mut self.rx_packet_buf);
@ -51,7 +46,7 @@ impl<'a, 'c> Device<'a> for SmoltcpDevice<'c> {
// Construct a blank TxToken // Construct a blank TxToken
let tx_token = EthTxToken { let tx_token = EthTxToken {
buf: &mut self.tx_packet_buf, buf: &mut self.tx_packet_buf,
dev: self_a dev: self_p
}; };
Some((rx_token, tx_token)) Some((rx_token, tx_token))
}, },
@ -60,16 +55,11 @@ impl<'a, 'c> Device<'a> for SmoltcpDevice<'c> {
} }
fn transmit(&'a mut self) -> Option<Self::TxToken> { fn transmit(&'a mut self) -> Option<Self::TxToken> {
// Extend self lifetime from 'c to 'a for TxToken's access to EthController let self_p = (&mut *self) as *mut SmoltcpDevice<EC>;
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 // Construct a blank TxToken
let tx_token = EthTxToken { let tx_token = EthTxToken {
buf: &mut self.tx_packet_buf, buf: &mut self.tx_packet_buf,
dev: self_a dev: self_p
}; };
Some(tx_token) Some(tx_token)
} }
@ -89,12 +79,12 @@ impl<'a> RxToken for EthRxToken<'a> {
} }
} }
pub struct EthTxToken<'a> { pub struct EthTxToken<'a, EC: EthController> {
buf: &'a mut [u8], buf: &'a mut [u8],
dev: *mut SmoltcpDevice<'a> dev: *mut SmoltcpDevice<EC>
} }
impl<'a> TxToken for EthTxToken<'a> { impl<'a, EC: 'a + EthController> TxToken for EthTxToken<'a, EC> {
fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R, Error> fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R, Error>
where where
F: FnOnce(&mut [u8]) -> Result<R, Error>, F: FnOnce(&mut [u8]) -> Result<R, Error>,
@ -108,7 +98,7 @@ impl<'a> TxToken for EthTxToken<'a> {
let eth_controller = unsafe { let eth_controller = unsafe {
&mut (*self.dev).eth_controller &mut (*self.dev).eth_controller
}; };
match eth_controller.send_raw_packet(&tx_packet) { match eth_controller.borrow_mut().send_raw_packet(&tx_packet) {
Ok(_) => { result }, Ok(_) => { result },
Err(_) => Err(Error::Exhausted) Err(_) => Err(Error::Exhausted)
} }