forked from M-Labs/kirdy
Support controls from multiple TCP Socket Clients
This commit is contained in:
parent
eff8adc184
commit
7f6a385e1d
67
src/main.rs
67
src/main.rs
@ -145,40 +145,43 @@ fn main() -> ! {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
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 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);
|
||||
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.
|
||||
|
@ -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::<milliampere>(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)
|
||||
}
|
||||
|
126
src/net/net.rs
126
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<RefCell<bool>> = 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<TcpSocketStorage> = 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::<Socket>(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<SocketHandle>; 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::<Socket>(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<usize, smoltcp::socket::tcp::RecvError> {
|
||||
pub fn recv(&mut self, buffer: &mut [u8], socket_handles: SocketHandle)-> Result<usize, smoltcp::socket::tcp::RecvError> {
|
||||
self.iface.poll(now_fn(), &mut &mut self.dma, &mut self.socket_set);
|
||||
let socket = self.socket_set.get_mut::<Socket>(self.socket_handle);
|
||||
let socket = self.socket_set.get_mut::<Socket>(socket_handles);
|
||||
|
||||
socket.recv_slice(buffer)
|
||||
}
|
||||
|
||||
pub fn send(&mut self, buffer: &mut [u8], num_bytes: usize) {
|
||||
let socket = self.socket_set.get_mut::<Socket>(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>(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::<Socket>(self.socket_handle);
|
||||
pub fn poll_socket_status(&mut self, socket_handles: SocketHandle)-> bool {
|
||||
let socket = self.socket_set.get_mut::<Socket>(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::<Socket>(self.socket_handle);
|
||||
pub fn close_socket(&mut self, socket_handles: SocketHandle) {
|
||||
let socket = self.socket_set.get_mut::<Socket>(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<F: FnMut(SocketHandle)>(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");
|
||||
|
Loading…
Reference in New Issue
Block a user