From 7f6a385e1d65a04a83da2a4913d45ab2c35254d3 Mon Sep 17 00:00:00 2001 From: linuswck Date: Wed, 6 Mar 2024 16:29:02 +0800 Subject: [PATCH] Support controls from multiple TCP Socket Clients --- src/main.rs | 71 ++++++++++++----------- src/net/cmd_handler.rs | 24 ++++---- src/net/net.rs | 126 ++++++++++++++++++++++++----------------- 3 files changed, 123 insertions(+), 98 deletions(-) diff --git a/src/main.rs b/src/main.rs index 9185442..c75960a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -144,41 +144,44 @@ fn main() -> ! { thermostat.set_pid_engaged(false); thermostat.power_down(); } - - if net::net::eth_is_socket_active() { - if device_settings.report_readings { - unsafe { - net::cmd_handler::send_status_report(&mut ETH_DATA_BUFFER, &mut laser, &mut thermostat); + + net::net::for_each(|mut socket| { + if net::net::eth_is_socket_active(socket) { + if device_settings.report_readings { + unsafe { + net::cmd_handler::send_status_report(&mut ETH_DATA_BUFFER, &mut laser, &mut thermostat, &mut socket); + } } } - } + }); } - - if net::net::eth_is_socket_active() { - cortex_m::interrupt::free(|cs| - { - eth_is_pending = net::net::is_pending(cs); - } - ); - - if eth_is_pending { - unsafe{ - cortex_m::interrupt::free(|cs| { - net::net::clear_pending(cs); - }); - let bytes = net::net::eth_recv(&mut ETH_DATA_BUFFER); - if bytes != 0 { - info!("Ts: {:?}", sys_timer::now()); - debug!("Number of bytes recv: {:?}", bytes); - // State Transition - (laser, thermostat, state, device_settings) = net::cmd_handler::execute_cmd(&mut ETH_DATA_BUFFER, bytes, laser, thermostat, state, device_settings); + net::net::for_each(|mut socket| { + if net::net::eth_is_socket_active(socket) { + cortex_m::interrupt::free(|cs| + { + eth_is_pending = net::net::is_pending(cs); + } + ); + + if eth_is_pending { + unsafe{ + cortex_m::interrupt::free(|cs| { + net::net::clear_pending(cs); + }); + let bytes = net::net::eth_recv(&mut ETH_DATA_BUFFER, socket); + if bytes != 0 { + info!("Ts: {:?}", sys_timer::now()); + debug!("Number of bytes recv: {:?}", bytes); + // State Transition + net::cmd_handler::execute_cmd(&mut ETH_DATA_BUFFER, bytes, &mut socket, &mut laser, &mut thermostat, &mut state, &mut device_settings); + } } } + if has_temp_reading { + thermostat.start_tec_readings_conversion(); + } } - if has_temp_reading { - thermostat.start_tec_readings_conversion(); - } - } + }); } State::SaveFlashSettings => { // State Transition @@ -220,10 +223,12 @@ fn main() -> ! { laser.power_down(); thermostat.power_down(); let mut any_socket_alive = false; - if net::net::eth_is_socket_active() { - net::net::eth_close_socket(); - any_socket_alive = true; - } + net::net::for_each(|socket| { + if net::net::eth_is_socket_active(socket) { + net::net::eth_close_socket(socket); + any_socket_alive = true; + } + }); // Must let loop run for one more cycle to poll server for RST to be sent, // this makes sure system does not reset right after socket.abort() is called. diff --git a/src/net/cmd_handler.rs b/src/net/cmd_handler.rs index 1a0030f..e3f49fb 100644 --- a/src/net/cmd_handler.rs +++ b/src/net/cmd_handler.rs @@ -20,6 +20,7 @@ use crate::thermostat::pid_state::PidSettings::*; use crate::device::{dfu, sys_timer}; use log::info; use crate::{DeviceSettings, State, IpSettings}; +use smoltcp::iface::SocketHandle; #[derive(Deserialize, Serialize, Copy, Clone, Default, Debug)] enum DeviceCmd { @@ -127,7 +128,7 @@ pub struct SettingsSummaryObj { json: SettingsSummary } -pub fn send_settings_summary(buffer: &mut [u8], laser: &mut LdDrive, tec: &mut Thermostat){ +pub fn send_settings_summary(buffer: &mut [u8], laser: &mut LdDrive, tec: &mut Thermostat, socket: &mut SocketHandle){ let settings_summary = SettingsSummaryObj { json: SettingsSummary { laser: laser.get_settings_summary(), @@ -135,11 +136,11 @@ pub fn send_settings_summary(buffer: &mut [u8], laser: &mut LdDrive, tec: &mut T } }; let num_bytes = settings_summary.get_json("/json", buffer).unwrap(); - net::eth_send(buffer, num_bytes); + net::eth_send(buffer, num_bytes, *socket); } -pub fn send_status_report(buffer: &mut [u8], laser: &mut LdDrive, tec: &mut Thermostat){ +pub fn send_status_report(buffer: &mut [u8], laser: &mut LdDrive, tec: &mut Thermostat, socket: &mut SocketHandle){ let status_report = StatusReportObj { json: StatusReport { ts: sys_timer::now(), @@ -148,7 +149,7 @@ pub fn send_status_report(buffer: &mut [u8], laser: &mut LdDrive, tec: &mut Ther } }; let num_bytes = status_report.get_json("/json", buffer).unwrap(); - net::eth_send(buffer, num_bytes); + net::eth_send(buffer, num_bytes, *socket); } // Use a minimal struct for high speed cmd ctrl to reduce processing overhead @@ -165,14 +166,14 @@ pub struct TecSetICmd { /// Make sure kirdy's firmware is flashed with release builds. /// The received message must contain only one json cmd. TCP client should set TCP_NODELAY or equivalent flag in its TCP Socket /// Settings to avoid unwanted buffering on TX Data and minimize TX latency. -pub fn execute_cmd(buffer: &mut [u8], buffer_size: usize, mut laser: LdDrive, mut tec: Thermostat, mut state: State, mut device_settings: DeviceSettings)->(LdDrive, Thermostat, State, DeviceSettings){ +pub fn execute_cmd(buffer: &mut [u8], buffer_size: usize, socket: &mut SocketHandle, laser: &mut LdDrive, tec: &mut Thermostat, state: &mut State, device_settings: &mut DeviceSettings){ let mut cmd = TecSetICmd { json: TecSetICmdJson::default() }; match cmd.set_json("/json", &buffer[0..buffer_size]){ Ok(_) => { tec.set_i(ElectricCurrent::new::(cmd.json.tec_set_i)); - return (laser, tec, state, device_settings); + return; } Err(_) => { /* Do Nothing */} } @@ -213,19 +214,19 @@ pub fn execute_cmd(buffer: &mut [u8], buffer_size: usize, mut laser: LdDrive, mu } } Some(DeviceCmd::GetStatusReport) => { - send_status_report(buffer, &mut laser, &mut tec); + send_status_report(buffer, laser, tec, socket); } Some(DeviceCmd::GetSettingsSummary) => { - send_settings_summary(buffer, &mut laser, &mut tec); + send_settings_summary(buffer, laser, tec, socket); } Some(DeviceCmd::SaveFlashSettings) => { - state = State::SaveFlashSettings; + *state = State::SaveFlashSettings; } Some(DeviceCmd::LoadFlashSettings) => { - state = State::LoadFlashSettings; + *state = State::LoadFlashSettings; } Some(DeviceCmd::HardReset) => { - state = State::HardReset; + *state = State::HardReset; } None => { /* Do Nothing */} _ => { @@ -557,5 +558,4 @@ pub fn execute_cmd(buffer: &mut [u8], buffer_size: usize, mut laser: LdDrive, mu info!("Invalid Command: {:?}", err); } } - (laser, tec, state, device_settings) } diff --git a/src/net/net.rs b/src/net/net.rs index daaaa97..01176bf 100644 --- a/src/net/net.rs +++ b/src/net/net.rs @@ -1,14 +1,12 @@ use crate::device::sys_timer; +use core::mem::{self, MaybeUninit}; use core::cell::RefCell; use cortex_m::interrupt::{CriticalSection, Mutex}; use log::{debug, info}; use smoltcp::{ iface::{ self, Interface, SocketHandle, SocketSet, SocketStorage - }, - socket::tcp::{State, SocketBuffer, Socket}, - wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address, Ipv4Cidr}, - time::Instant, + }, socket::tcp::{Socket, SocketBuffer, State}, time::Instant, wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address, Ipv4Cidr} }; use stm32_eth::{ Parts, EthPins, PartsIn, @@ -34,7 +32,7 @@ pub struct IpSettings { impl Default for IpSettings { fn default() -> Self { IpSettings { - addr: [192, 168, 1, 132], + addr: [192, 168, 1, 128], port: 1337, prefix_len: 24, gateway: [192, 168, 1, 1] @@ -47,7 +45,7 @@ impl Default for IpSettings { static NET_PENDING: Mutex> = Mutex::new(RefCell::new(false)); pub struct ServerHandle { - socket_handle: SocketHandle, + socket_handles: [SocketHandle; NUM_OF_SOCKETS], socket_set: SocketSet<'static>, socket_addr: (IpAddress, u16), iface: EthInterface, @@ -63,26 +61,11 @@ pub struct EthernetMgmtPins { } pub type EthInterface = Interface; +const NUM_OF_SOCKETS : usize = 4; +const TCP_BUFFER_SIZE: usize = 2048; static mut RX_RING: Option<[RxRingEntry; 8]> = None; static mut TX_RING: Option<[TxRingEntry; 2]> = None; -static mut SOCKET_STORAGE: Option<[SocketStorage<'static>; 1]> = None; - -static mut TCP_SOCKET_STORAGE : Option = None; - -#[derive(Copy, Clone)] -pub struct TcpSocketStorage { - rx_storage: [u8; 2048], - tx_storage: [u8; 2048], -} - -impl TcpSocketStorage { - const fn new() -> Self { - Self { - rx_storage: [0; 2048], - tx_storage: [0; 2048], - } - } -} +static mut SOCKET_STORAGE: Option<[SocketStorage<'static>; NUM_OF_SOCKETS]> = None; fn now_fn() -> smoltcp::time::Instant { Instant::from_millis(i64::from(sys_timer::now())) @@ -100,8 +83,7 @@ impl ServerHandle { ) { let rx_ring = unsafe { RX_RING.get_or_insert(Default::default()) }; let tx_ring = unsafe { TX_RING.get_or_insert(Default::default()) }; - let tcp_socket_storage = unsafe { TCP_SOCKET_STORAGE.get_or_insert(TcpSocketStorage::new()) }; - let socket_storage = unsafe { SOCKET_STORAGE.get_or_insert([SocketStorage::EMPTY; 1]) }; + let socket_storage = unsafe { SOCKET_STORAGE.get_or_insert([SocketStorage::EMPTY; NUM_OF_SOCKETS]) }; let Parts { mut dma, @@ -138,10 +120,6 @@ impl ServerHandle { .ok(); dma.enable_interrupt(); - let rx_buffer = SocketBuffer::new(&mut tcp_socket_storage.rx_storage[..]); - let tx_buffer = SocketBuffer::new(&mut tcp_socket_storage.tx_storage[..]); - let socket = Socket::new(rx_buffer, tx_buffer); - let config = iface::Config::new(EthernetAddress::from_bytes(&mac_addr).into()); let mut iface = Interface::new(config, &mut &mut dma, smoltcp::time::Instant::ZERO); iface.set_hardware_addr(EthernetAddress(mac_addr).into()); @@ -151,11 +129,40 @@ impl ServerHandle { addr.push(ip_init).unwrap(); }); - let mut sockets = SocketSet::new(&mut socket_storage[..]); - let tcp_handle = sockets.add(socket); - let socket = sockets.get_mut::(tcp_handle); - socket.listen(socket_addr).ok(); - iface.poll(Instant::from_millis(i64::from(sys_timer::now())), &mut &mut dma, &mut sockets); + let mut socket_set = SocketSet::new(&mut socket_storage[..]); + + let tcp_handles = { + // Do not use NUM_OF_SOCKETS to define array size to + // remind developers to create/remove tcp_handles accordingly after changing NUM_OF_SOCKETS + let mut tcp_handles: [MaybeUninit; 4]= unsafe { + MaybeUninit::uninit().assume_init() + }; + + macro_rules! create_tcp_handle { + ($rx_storage:ident, $tx_storage:ident, $handle:expr) => { + static mut $rx_storage : [u8; TCP_BUFFER_SIZE] = [0; TCP_BUFFER_SIZE]; + static mut $tx_storage : [u8; TCP_BUFFER_SIZE] = [0; TCP_BUFFER_SIZE]; + unsafe { + let rx_buffer = SocketBuffer::new(&mut $rx_storage[..]); + let tx_buffer = SocketBuffer::new(&mut $tx_storage[..]); + $handle.write(socket_set.add(Socket::new(rx_buffer, tx_buffer))); + } + } + } + create_tcp_handle!(RX_STORAGE0, TX_STORAGE0, tcp_handles[0]); + create_tcp_handle!(RX_STORAGE1, TX_STORAGE1, tcp_handles[1]); + create_tcp_handle!(RX_STORAGE2, TX_STORAGE2, tcp_handles[2]); + create_tcp_handle!(RX_STORAGE3, TX_STORAGE3, tcp_handles[3]); + + unsafe { mem::transmute::<_, [SocketHandle; 4]>(tcp_handles) } + }; + + for i in 0..NUM_OF_SOCKETS { + let socket = socket_set.get_mut::(tcp_handles[i]); + socket.listen(socket_addr).ok(); + } + + iface.poll(Instant::from_millis(i64::from(sys_timer::now())), &mut &mut dma, &mut socket_set); if let Ok(mut phy) = EthernetPhy::from_miim(mac, 0) { info!( @@ -166,8 +173,8 @@ impl ServerHandle { phy.phy_init(); let server = ServerHandle { - socket_handle: tcp_handle, - socket_set: sockets, + socket_handles: tcp_handles, + socket_set: socket_set, socket_addr: socket_addr, iface: iface, dma: dma, @@ -200,15 +207,15 @@ impl ServerHandle { self.link_was_up = self.phy.phy_link_up(); } - pub fn recv(&mut self, buffer: &mut [u8])-> Result { + pub fn recv(&mut self, buffer: &mut [u8], socket_handles: SocketHandle)-> Result { self.iface.poll(now_fn(), &mut &mut self.dma, &mut self.socket_set); - let socket = self.socket_set.get_mut::(self.socket_handle); + let socket = self.socket_set.get_mut::(socket_handles); socket.recv_slice(buffer) } - pub fn send(&mut self, buffer: &mut [u8], num_bytes: usize) { - let socket = self.socket_set.get_mut::(self.socket_handle); + pub fn send(&mut self, buffer: &mut [u8], num_bytes: usize, socket_handles: SocketHandle) { + let socket = self.socket_set.get_mut::(socket_handles); if num_bytes > 0 { socket.send_slice(&buffer[..num_bytes]).ok(); info!("Sent {} bytes.", num_bytes); @@ -218,8 +225,8 @@ impl ServerHandle { self.iface.poll(now_fn(), &mut &mut self.dma, &mut self.socket_set); } - pub fn poll_socket_status(&mut self)-> bool { - let socket = self.socket_set.get_mut::(self.socket_handle); + pub fn poll_socket_status(&mut self, socket_handles: SocketHandle)-> bool { + let socket = self.socket_set.get_mut::(socket_handles); if !socket.is_listening() && !socket.is_open() || socket.state() == State::CloseWait { socket.abort(); socket.listen(self.socket_addr).ok(); @@ -231,8 +238,8 @@ impl ServerHandle { return true; } - pub fn close_socket(&mut self) { - let socket = self.socket_set.get_mut::(self.socket_handle); + pub fn close_socket(&mut self, socket_handles: SocketHandle) { + let socket = self.socket_set.get_mut::(socket_handles); socket.abort(); } } @@ -350,10 +357,10 @@ pub fn eth_poll_and_update_link_speed() { } } -pub fn eth_send(buffer: &mut [u8], num_bytes: usize) { +pub fn eth_send(buffer: &mut [u8], num_bytes: usize, socket_handles: SocketHandle) { unsafe { if let Some(ref mut server_handle ) = SERVER_HANDLE { - server_handle.send(buffer, num_bytes); + server_handle.send(buffer, num_bytes, socket_handles); } else { panic!("eth_send is called before init"); @@ -361,10 +368,10 @@ pub fn eth_send(buffer: &mut [u8], num_bytes: usize) { } } -pub fn eth_recv(buffer: &mut [u8])-> usize{ +pub fn eth_recv(buffer: &mut [u8], socket_handles: SocketHandle)-> usize{ unsafe { if let Some(ref mut server_handle ) = SERVER_HANDLE { - match server_handle.recv(buffer){ + match server_handle.recv(buffer, socket_handles){ Ok(recv_bytes) => {return recv_bytes} Err(err) => { debug!("TCP Recv Error: {}", err); @@ -378,10 +385,10 @@ pub fn eth_recv(buffer: &mut [u8])-> usize{ } } -pub fn eth_is_socket_active() -> bool { +pub fn eth_is_socket_active(socket_handles: SocketHandle) -> bool { unsafe { if let Some(ref mut server_handle ) = SERVER_HANDLE { - server_handle.poll_socket_status() + server_handle.poll_socket_status(socket_handles) } else { panic!("eth_is_socket_active is called before init"); @@ -389,10 +396,23 @@ pub fn eth_is_socket_active() -> bool { } } -pub fn eth_close_socket() { +pub fn eth_close_socket(socket_handles: SocketHandle) { unsafe { if let Some(ref mut server_handle ) = SERVER_HANDLE { - server_handle.close_socket() + server_handle.close_socket(socket_handles) + } + else { + panic!("eth_close_socket is called before init"); + } + } +} + +pub fn for_each(mut callback: F) { + unsafe { + if let Some(ref mut server_handle ) = SERVER_HANDLE { + for i in 0..NUM_OF_SOCKETS { + callback(server_handle.socket_handles[i]); + } } else { panic!("eth_close_socket is called before init");