net, server: put tcp storage on stack

This commit is contained in:
Astro 2019-03-18 20:02:57 +01:00
parent 912bc2db24
commit 1832bd5884
3 changed files with 102 additions and 101 deletions

View File

@ -100,40 +100,42 @@ fn main() -> ! {
timer::setup(cp.SYST, clocks); timer::setup(cp.SYST, clocks);
info!("Net startup"); info!("Net startup");
net::run(&mut cp.NVIC, dp.ETHERNET_MAC, dp.ETHERNET_DMA, |net| { net::run(&mut cp.NVIC, dp.ETHERNET_MAC, dp.ETHERNET_DMA, |iface| {
let mut server = Server::new(net); Server::run(iface, |server| {
let mut last_output = 0_u32;
loop {
led_green.on();
let now = timer::now().0;
let instant = Instant::from_millis(now as i64);
server.poll(instant);
led_green.off();
let mut last_output = 0_u32; led_blue.on();
loop { let now = timer::now().0;
led_green.on(); if now - last_output >= OUTPUT_INTERVAL {
let now = timer::now().0; let adc_value = adc_input::read();
let instant = Instant::from_millis(now as i64); adc_value.map(|adc_value| {
server.poll(instant); write!(server, "t={},pa3={}\r\n", now, adc_value).unwrap();
led_green.off(); });
last_output = now;
led_blue.on();
let now = timer::now().0;
if now - last_output >= OUTPUT_INTERVAL {
let adc_value = adc_input::read();
adc_value.map(|adc_value| {
write!(server, "t={},pa3={}\r\n", now, adc_value).unwrap();
});
last_output = now;
}
led_blue.off();
// Update watchdog
wd.feed();
led_red.on();
cortex_m::interrupt::free(|cs| {
if !net::is_pending(cs) {
// Wait for interrupts
wfi();
net::clear_pending(cs);
} }
}); led_blue.off();
led_red.off();
} // Update watchdog
}) wd.feed();
led_red.on();
cortex_m::interrupt::free(|cs| {
if !net::is_pending(cs) {
// Wait for interrupts
wfi();
net::clear_pending(cs);
}
});
led_red.off();
}
});
});
unimplemented!()
} }

View File

@ -7,14 +7,15 @@ use bare_metal::CriticalSection;
use stm32f4xx_hal::{ use stm32f4xx_hal::{
stm32::{interrupt, Peripherals, NVIC, ETHERNET_MAC, ETHERNET_DMA}, stm32::{interrupt, Peripherals, NVIC, ETHERNET_MAC, ETHERNET_DMA},
}; };
use smoltcp::time::Instant;
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder, EthernetInterface}; use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder, EthernetInterface};
use smoltcp::socket::SocketSet;
use stm32_eth::{Eth, RingEntry, RxDescriptor, TxDescriptor}; use stm32_eth::{Eth, RingEntry, RxDescriptor, TxDescriptor};
// TODO: ram regions /// 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; static mut RX_RING: Option<[RingEntry<RxDescriptor>; 8]> = None;
/// Not on the stack so that stack can be placed in CCMRAM (which the
/// ethernet peripheral cannot access)
static mut TX_RING: Option<[RingEntry<TxDescriptor>; 2]> = None; static mut TX_RING: Option<[RingEntry<TxDescriptor>; 2]> = None;
// TODO: generate one from device id // TODO: generate one from device id
@ -22,9 +23,9 @@ const SRC_MAC: [u8; 6] = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
static NET_PENDING: Mutex<RefCell<bool>> = Mutex::new(RefCell::new(false)); static NET_PENDING: Mutex<RefCell<bool>> = Mutex::new(RefCell::new(false));
pub fn run<F>(nvic: &mut NVIC, ethernet_mac: ETHERNET_MAC, ethernet_dma: ETHERNET_DMA, f: F) -> ! pub fn run<F>(nvic: &mut NVIC, ethernet_mac: ETHERNET_MAC, ethernet_dma: ETHERNET_DMA, f: F)
where where
F: FnOnce(&mut NetInterface) -> ! F: FnOnce(EthernetInterface<&mut stm32_eth::Eth<'static, 'static>>),
{ {
let rx_ring = unsafe { let rx_ring = unsafe {
RX_RING.get_or_insert(Default::default()) RX_RING.get_or_insert(Default::default())
@ -49,37 +50,10 @@ where
.neighbor_cache(neighbor_cache) .neighbor_cache(neighbor_cache)
.finalize(); .finalize();
let mut sockets_storage = [None, None, None, None]; f(iface);
let sockets = SocketSet::new(&mut sockets_storage[..]);
let mut net_iface = NetInterface {
iface,
sockets,
};
f(&mut net_iface);
} }
pub struct NetInterface<'a> { /// Wake up from `wfi()`, clear interrupt flags,
iface: EthernetInterface<'a, 'a, 'a, &'a mut stm32_eth::Eth<'static, 'static>>,
sockets: SocketSet<'a, 'static, 'static>,
}
impl<'a> NetInterface<'a> {
/// Passes the boolean that indicates any sockets change.
pub fn poll(&mut self, now: Instant) -> bool {
// TODO: clear pending flag
self.iface.poll(&mut self.sockets, now)
.ok()
.unwrap_or(false)
}
pub fn sockets(&mut self) -> &mut SocketSet<'a, 'static, 'static> {
&mut self.sockets
}
}
/// Wwake up from `wfi()`, clear interrupt flags,
/// and TODO: set pending flag /// and TODO: set pending flag
#[interrupt] #[interrupt]
fn ETH() { fn ETH() {

View File

@ -1,63 +1,88 @@
use core::fmt; use core::fmt;
use core::mem::uninitialized; use core::mem::uninitialized;
use smoltcp::{ use smoltcp::{
socket::{SocketHandle, TcpSocket, TcpSocketBuffer}, iface::EthernetInterface,
socket::{SocketSet, SocketHandle, TcpSocket, TcpSocketBuffer},
time::Instant, time::Instant,
}; };
use crate::net::NetInterface;
const TCP_PORT: u16 = 23; const TCP_PORT: u16 = 23;
const SOCKET_COUNT: usize = 4; const SOCKET_COUNT: usize = 8;
const SOCKET_BUFFER_SIZE: usize = 2048;
const SOCKET_BUFFERS_LENGTH: usize = 2 * SOCKET_COUNT * SOCKET_BUFFER_SIZE;
static mut SOCKET_BUFFERS: [u8; SOCKET_BUFFERS_LENGTH] = [0u8; SOCKET_BUFFERS_LENGTH]; const TCP_RX_BUFFER_SIZE: usize = 2048;
const TCP_TX_BUFFER_SIZE: usize = 2048;
fn get_socket_buffers(i: usize) -> (&'static mut [u8], &'static mut [u8]) { macro_rules! create_socket_storage {
let offset1 = 2 * i * SOCKET_BUFFER_SIZE; ($rx_storage:ident, $tx_storage:ident) => (
let offset2 = offset1 + SOCKET_BUFFER_SIZE; let mut $rx_storage = [0; TCP_RX_BUFFER_SIZE];
let offset3 = offset2 + SOCKET_BUFFER_SIZE; let mut $tx_storage = [0; TCP_TX_BUFFER_SIZE];
unsafe { )
(&mut SOCKET_BUFFERS[offset1..offset2], }
&mut SOCKET_BUFFERS[offset2..offset3])
} macro_rules! create_socket {
($set:ident, $rx_storage:ident, $tx_storage:ident, $target:expr) => (
let tcp_rx_buffer = TcpSocketBuffer::new(&mut $rx_storage[..]);
let tcp_tx_buffer = TcpSocketBuffer::new(&mut $tx_storage[..]);
let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
$target = $set.add(tcp_socket);
)
} }
/// Contains a number of server sockets that get all sent the same /// Contains a number of server sockets that get all sent the same
/// data (through `fmt::Write`). /// data (through `fmt::Write`).
pub struct Server<'a, 's> { pub struct Server<'a, 'b> {
net: EthernetInterface<'a, 'a, 'a, &'a mut stm32_eth::Eth<'static, 'static>>,
sockets: SocketSet<'b, 'b, 'static>,
handles: [SocketHandle; SOCKET_COUNT], handles: [SocketHandle; SOCKET_COUNT],
net: &'s mut NetInterface<'a>,
} }
impl<'a, 's> Server<'a, 's> { impl<'a, 'b> Server<'a, 'b> {
pub fn new(net: &'s mut NetInterface<'a>) -> Self { pub fn run<F>(net: EthernetInterface<'a, 'a, 'a, &'a mut stm32_eth::Eth<'static, 'static>>, f: F)
where
F: FnOnce(&mut Server<'a, '_>),
{
create_socket_storage!(tcp_rx_storage0, tcp_tx_storage0);
create_socket_storage!(tcp_rx_storage1, tcp_tx_storage1);
create_socket_storage!(tcp_rx_storage2, tcp_tx_storage2);
create_socket_storage!(tcp_rx_storage3, tcp_tx_storage3);
create_socket_storage!(tcp_rx_storage4, tcp_tx_storage4);
create_socket_storage!(tcp_rx_storage5, tcp_tx_storage5);
create_socket_storage!(tcp_rx_storage6, tcp_tx_storage6);
create_socket_storage!(tcp_rx_storage7, tcp_tx_storage7);
let mut sockets_storage = [
None, None, None, None,
None, None, None, None
];
let mut sockets = SocketSet::new(&mut sockets_storage[..]);
let mut handles: [SocketHandle; SOCKET_COUNT] = unsafe { uninitialized() };
create_socket!(sockets, tcp_rx_storage0, tcp_tx_storage0, handles[0]);
create_socket!(sockets, tcp_rx_storage1, tcp_tx_storage1, handles[1]);
create_socket!(sockets, tcp_rx_storage2, tcp_tx_storage2, handles[2]);
create_socket!(sockets, tcp_rx_storage3, tcp_tx_storage3, handles[3]);
create_socket!(sockets, tcp_rx_storage4, tcp_tx_storage4, handles[4]);
create_socket!(sockets, tcp_rx_storage5, tcp_tx_storage5, handles[5]);
create_socket!(sockets, tcp_rx_storage6, tcp_tx_storage6, handles[6]);
create_socket!(sockets, tcp_rx_storage7, tcp_tx_storage7, handles[7]);
let mut server = Server { let mut server = Server {
handles: unsafe { uninitialized() }, handles,
sockets,
net, net,
}; };
f(&mut server);
for i in 0..SOCKET_COUNT {
let buffers = get_socket_buffers(i);
let server_socket = TcpSocket::new(
TcpSocketBuffer::new(&mut buffers.0[..]),
TcpSocketBuffer::new(&mut buffers.1[..])
);
server.handles[i] = server.net.sockets().add(server_socket);
}
server
} }
pub fn poll(&mut self, now: Instant) { pub fn poll(&mut self, now: Instant) {
let activity = self.net.poll(now); let activity = self.net.poll(&mut self.sockets, now)
.unwrap_or(true);
if ! activity { if ! activity {
return; return;
} }
for handle in &self.handles { for handle in &self.handles {
let mut socket = self.net.sockets().get::<TcpSocket>(*handle); let mut socket = self.sockets.get::<TcpSocket>(*handle);
if ! socket.is_open() { if ! socket.is_open() {
socket.listen(TCP_PORT) socket.listen(TCP_PORT)
.unwrap(); .unwrap();
@ -70,7 +95,7 @@ impl<'a, 's> fmt::Write for Server<'a, 's> {
/// Write to all connected clients /// Write to all connected clients
fn write_str(&mut self, slice: &str) -> fmt::Result { fn write_str(&mut self, slice: &str) -> fmt::Result {
for handle in &self.handles { for handle in &self.handles {
let mut socket = self.net.sockets().get::<TcpSocket>(*handle); let mut socket = self.sockets.get::<TcpSocket>(*handle);
if socket.can_send() { if socket.can_send() {
// Ignore errors, proceed with next client // Ignore errors, proceed with next client
let _ = socket.write_str(slice); let _ = socket.write_str(slice);