forked from M-Labs/thermostat
Attempt then Try, try again WTF lifetime again
This commit is contained in:
parent
aeba19bca2
commit
c8ceb2dbad
|
@ -172,8 +172,8 @@ fn main() -> ! {
|
|||
let hwaddr = EthernetAddress(eui48);
|
||||
info!("EEPROM MAC address: {}", hwaddr);
|
||||
|
||||
net::run(clocks, dp.ETHERNET_MAC, dp.ETHERNET_DMA, eth_pins, hwaddr, ipv4_config.clone(), |iface| {
|
||||
Server::<Session>::run(iface, |server| {
|
||||
net::run::<_, Session>(clocks, dp.ETHERNET_MAC, dp.ETHERNET_DMA, eth_pins, hwaddr, ipv4_config.clone(), |iface, states| {
|
||||
Server::run(iface, states, |server| {
|
||||
leds.r1.off();
|
||||
let mut should_reset = false;
|
||||
|
||||
|
|
68
src/net.rs
68
src/net.rs
|
@ -8,14 +8,44 @@ use stm32f4xx_hal::{
|
|||
pac::{interrupt, Peripherals, ETHERNET_MAC, ETHERNET_DMA},
|
||||
};
|
||||
use smoltcp::wire::{EthernetAddress, Ipv4Address, Ipv4Cidr};
|
||||
use smoltcp::iface::{
|
||||
EthernetInterfaceBuilder, EthernetInterface,
|
||||
NeighborCache, Routes,
|
||||
use smoltcp::{
|
||||
iface::{
|
||||
InterfaceBuilder, Interface,
|
||||
NeighborCache, Routes,
|
||||
SocketHandle
|
||||
},
|
||||
socket::{TcpSocket, TcpSocketBuffer}
|
||||
};
|
||||
use stm32_eth::{Eth, RingEntry, RxDescriptor, TxDescriptor};
|
||||
use crate::command_parser::Ipv4Config;
|
||||
use crate::pins::EthernetPins;
|
||||
|
||||
pub struct SocketState<S> {
|
||||
pub handle: SocketHandle,
|
||||
pub state: S,
|
||||
}
|
||||
|
||||
impl<'a, S: Default> SocketState<S>{
|
||||
fn new(net: &mut Interface<'a, &'a mut stm32_eth::Eth<'static, 'static>>, tcp_rx_storage: &'a mut [u8; TCP_RX_BUFFER_SIZE], tcp_tx_storage: &'a mut [u8; TCP_TX_BUFFER_SIZE]) -> SocketState<S> {
|
||||
let tcp_rx_buffer = TcpSocketBuffer::new(&mut tcp_rx_storage[..]);
|
||||
let tcp_tx_buffer = TcpSocketBuffer::new(&mut tcp_tx_storage[..]);
|
||||
let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
|
||||
SocketState::<S> {
|
||||
handle: net.add_socket(tcp_socket),
|
||||
state: S::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Number of server sockets and therefore concurrent client
|
||||
/// sessions. Many data structures in `Server::run()` correspond to
|
||||
/// this const.
|
||||
const SOCKET_COUNT: usize = 4;
|
||||
|
||||
const TCP_RX_BUFFER_SIZE: usize = 2048;
|
||||
const TCP_TX_BUFFER_SIZE: usize = 2048;
|
||||
|
||||
|
||||
/// Not on the stack so that stack can be placed in CCMRAM (which the
|
||||
/// ethernet peripheral cannot access)
|
||||
static mut RX_RING: Option<[RingEntry<RxDescriptor>; 8]> = None;
|
||||
|
@ -28,7 +58,7 @@ static mut TX_RING: Option<[RingEntry<TxDescriptor>; 2]> = None;
|
|||
static NET_PENDING: Mutex<RefCell<bool>> = Mutex::new(RefCell::new(false));
|
||||
|
||||
/// Run callback `f` with ethernet driver and TCP/IP stack
|
||||
pub fn run<F>(
|
||||
pub fn run<'a, F, S: Default>(
|
||||
clocks: Clocks,
|
||||
ethernet_mac: ETHERNET_MAC, ethernet_dma: ETHERNET_DMA,
|
||||
eth_pins: EthernetPins,
|
||||
|
@ -36,7 +66,7 @@ pub fn run<F>(
|
|||
ipv4_config: Ipv4Config,
|
||||
f: F
|
||||
) where
|
||||
F: FnOnce(EthernetInterface<&mut stm32_eth::Eth<'static, 'static>>),
|
||||
F: FnOnce(Interface<'a, &mut stm32_eth::Eth<'static, 'static>>, [SocketState<S>; SOCKET_COUNT]),
|
||||
{
|
||||
let rx_ring = unsafe {
|
||||
RX_RING.get_or_insert(Default::default())
|
||||
|
@ -61,14 +91,36 @@ pub fn run<F>(
|
|||
let mut routes_storage = [None; 1];
|
||||
let mut routes = Routes::new(&mut routes_storage[..]);
|
||||
gateway.map(|gateway| routes.add_default_ipv4_route(gateway).unwrap());
|
||||
let iface = EthernetInterfaceBuilder::new(&mut eth_dev)
|
||||
.ethernet_addr(ethernet_addr)
|
||||
|
||||
let mut sockets: [_; SOCKET_COUNT] = Default::default();
|
||||
|
||||
macro_rules! create_rtx_storage {
|
||||
($rx_storage:ident, $tx_storage:ident) => {
|
||||
let mut $rx_storage = [0; TCP_RX_BUFFER_SIZE];
|
||||
let mut $tx_storage = [0; TCP_TX_BUFFER_SIZE];
|
||||
}
|
||||
}
|
||||
|
||||
create_rtx_storage!(tcp_rx_storage0, tcp_tx_storage0);
|
||||
create_rtx_storage!(tcp_rx_storage1, tcp_tx_storage1);
|
||||
create_rtx_storage!(tcp_rx_storage2, tcp_tx_storage2);
|
||||
create_rtx_storage!(tcp_rx_storage3, tcp_tx_storage3);
|
||||
|
||||
let mut iface = InterfaceBuilder::new(&mut eth_dev, &mut sockets[..])
|
||||
.hardware_addr(ethernet_addr.into())
|
||||
.ip_addrs(&mut ip_addrs[..])
|
||||
.neighbor_cache(neighbor_cache)
|
||||
.routes(routes)
|
||||
.finalize();
|
||||
|
||||
f(iface);
|
||||
let states: [SocketState<S>; SOCKET_COUNT] = [
|
||||
SocketState::<S>::new(&mut iface, &mut tcp_rx_storage0, &mut tcp_tx_storage0),
|
||||
SocketState::<S>::new(&mut iface, &mut tcp_rx_storage1, &mut tcp_tx_storage1),
|
||||
SocketState::<S>::new(&mut iface, &mut tcp_rx_storage2, &mut tcp_tx_storage2),
|
||||
SocketState::<S>::new(&mut iface, &mut tcp_rx_storage3, &mut tcp_tx_storage3),
|
||||
];
|
||||
|
||||
f(iface, states);
|
||||
}
|
||||
|
||||
/// Potentially wake up from `wfi()`, set the interrupt pending flag,
|
||||
|
|
|
@ -1,28 +1,11 @@
|
|||
use smoltcp::{
|
||||
iface::EthernetInterface,
|
||||
socket::{SocketSet, SocketHandle, TcpSocket, TcpSocketBuffer, SocketRef},
|
||||
iface::Interface,
|
||||
socket::TcpSocket,
|
||||
time::Instant,
|
||||
wire::{IpAddress, IpCidr, Ipv4Address, Ipv4Cidr},
|
||||
};
|
||||
use crate::command_parser::Ipv4Config;
|
||||
use crate::net::split_ipv4_config;
|
||||
|
||||
pub struct SocketState<S> {
|
||||
handle: SocketHandle,
|
||||
state: S,
|
||||
}
|
||||
|
||||
impl<'a, S: Default> SocketState<S>{
|
||||
fn new(sockets: &mut SocketSet<'a>, tcp_rx_storage: &'a mut [u8; TCP_RX_BUFFER_SIZE], tcp_tx_storage: &'a mut [u8; TCP_TX_BUFFER_SIZE]) -> SocketState<S> {
|
||||
let tcp_rx_buffer = TcpSocketBuffer::new(&mut tcp_rx_storage[..]);
|
||||
let tcp_tx_buffer = TcpSocketBuffer::new(&mut tcp_tx_storage[..]);
|
||||
let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
|
||||
SocketState::<S> {
|
||||
handle: sockets.add(tcp_socket),
|
||||
state: S::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
use crate::net::{split_ipv4_config, SocketState};
|
||||
|
||||
/// Number of server sockets and therefore concurrent client
|
||||
/// sessions. Many data structures in `Server::run()` correspond to
|
||||
|
@ -34,44 +17,20 @@ const TCP_TX_BUFFER_SIZE: usize = 2048;
|
|||
|
||||
/// Contains a number of server sockets that get all sent the same
|
||||
/// data (through `fmt::Write`).
|
||||
pub struct Server<'a, 'b, S> {
|
||||
net: EthernetInterface<'a, &'a mut stm32_eth::Eth<'static, 'static>>,
|
||||
sockets: SocketSet<'b>,
|
||||
pub struct Server<'a, S> {
|
||||
net: Interface<'a, &'a mut stm32_eth::Eth<'static, 'static>>,
|
||||
states: [SocketState<S>; SOCKET_COUNT],
|
||||
}
|
||||
|
||||
impl<'a, 'b, S: Default> Server<'a, 'b, S> {
|
||||
impl<'a, S: Default> Server<'a, S> {
|
||||
/// Run a server with stack-allocated sockets
|
||||
pub fn run<F>(net: EthernetInterface<'a, &'a mut stm32_eth::Eth<'static, 'static>>, f: F)
|
||||
pub fn run<F>(net: Interface<'a, &'a mut stm32_eth::Eth<'static, 'static>>, states: [SocketState<S>; SOCKET_COUNT], f: F)
|
||||
where
|
||||
F: FnOnce(&mut Server<'a, '_, S>),
|
||||
F: FnOnce(&mut Server<'a, S>),
|
||||
{
|
||||
macro_rules! create_rtx_storage {
|
||||
($rx_storage:ident, $tx_storage:ident) => {
|
||||
let mut $rx_storage = [0; TCP_RX_BUFFER_SIZE];
|
||||
let mut $tx_storage = [0; TCP_TX_BUFFER_SIZE];
|
||||
}
|
||||
}
|
||||
|
||||
create_rtx_storage!(tcp_rx_storage0, tcp_tx_storage0);
|
||||
create_rtx_storage!(tcp_rx_storage1, tcp_tx_storage1);
|
||||
create_rtx_storage!(tcp_rx_storage2, tcp_tx_storage2);
|
||||
create_rtx_storage!(tcp_rx_storage3, tcp_tx_storage3);
|
||||
|
||||
let mut sockets_storage: [_; SOCKET_COUNT] = Default::default();
|
||||
let mut sockets = SocketSet::new(&mut sockets_storage[..]);
|
||||
|
||||
let states: [SocketState<S>; SOCKET_COUNT] = [
|
||||
SocketState::<S>::new(&mut sockets, &mut tcp_rx_storage0, &mut tcp_tx_storage0),
|
||||
SocketState::<S>::new(&mut sockets, &mut tcp_rx_storage1, &mut tcp_tx_storage1),
|
||||
SocketState::<S>::new(&mut sockets, &mut tcp_rx_storage2, &mut tcp_tx_storage2),
|
||||
SocketState::<S>::new(&mut sockets, &mut tcp_rx_storage3, &mut tcp_tx_storage3),
|
||||
];
|
||||
|
||||
let mut server = Server {
|
||||
states,
|
||||
sockets,
|
||||
net,
|
||||
net
|
||||
};
|
||||
f(&mut server);
|
||||
}
|
||||
|
@ -80,7 +39,7 @@ impl<'a, 'b, S: Default> Server<'a, 'b, S> {
|
|||
pub fn poll(&mut self, now: Instant) -> Result<(), smoltcp::Error> {
|
||||
// Poll smoltcp EthernetInterface,
|
||||
// pass only unexpected smoltcp errors to the caller
|
||||
match self.net.poll(&mut self.sockets, now) {
|
||||
match self.net.poll(now) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(smoltcp::Error::Malformed) => Ok(()),
|
||||
Err(smoltcp::Error::Unrecognized) => Ok(()),
|
||||
|
@ -89,10 +48,10 @@ impl<'a, 'b, S: Default> Server<'a, 'b, S> {
|
|||
}
|
||||
|
||||
/// Iterate over all sockets managed by this server
|
||||
pub fn for_each<F: FnMut(SocketRef<TcpSocket>, &mut S)>(&mut self, mut callback: F) {
|
||||
pub fn for_each<F: FnMut(&mut TcpSocket, &mut S)>(&mut self, mut callback: F) {
|
||||
for state in &mut self.states {
|
||||
let socket = self.sockets.get::<TcpSocket>(state.handle);
|
||||
callback(socket, &mut state.state);
|
||||
let mut socket = self.net.get_socket::<TcpSocket>(state.handle);
|
||||
callback(&mut socket, &mut state.state);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue