forked from M-Labs/kirdy
net: Implement iface polling timer
- iface needs to be polled with ref to iface.poll_at time to ensure quality of service - iface.poll() also services TCP related Timers
This commit is contained in:
parent
70fed23c51
commit
e8aaf5f66b
@ -109,6 +109,7 @@ pub fn bootup(
|
|||||||
eth_mgmt_pins,
|
eth_mgmt_pins,
|
||||||
ethernet_parts_in,
|
ethernet_parts_in,
|
||||||
clocks,
|
clocks,
|
||||||
|
perif.TIM5.counter(&clocks),
|
||||||
mac_addr,
|
mac_addr,
|
||||||
ip_settings,
|
ip_settings,
|
||||||
);
|
);
|
||||||
|
@ -142,6 +142,8 @@ fn main() -> ! {
|
|||||||
State::MainLoop => {
|
State::MainLoop => {
|
||||||
laser.poll_and_update_output_current();
|
laser.poll_and_update_output_current();
|
||||||
|
|
||||||
|
net::net::eth_update_iface_poll_timer();
|
||||||
|
|
||||||
if thermostat.poll_adc() {
|
if thermostat.poll_adc() {
|
||||||
thermostat.update_pid();
|
thermostat.update_pid();
|
||||||
if thermostat.get_temp_mon_status().over_temp_alarm {
|
if thermostat.get_temp_mon_status().over_temp_alarm {
|
||||||
@ -160,8 +162,6 @@ fn main() -> ! {
|
|||||||
&mut thermostat,
|
&mut thermostat,
|
||||||
&mut socket,
|
&mut socket,
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
debug!("Socket {:?} is not ready to send status report", id)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -191,8 +191,6 @@ fn main() -> ! {
|
|||||||
&mut active_report[id],
|
&mut active_report[id],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
debug!("Socket {:?} is not ready to process command", id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
132
src/net/net.rs
132
src/net/net.rs
@ -1,5 +1,6 @@
|
|||||||
use core::mem::{self, MaybeUninit};
|
use core::mem::{self, MaybeUninit};
|
||||||
|
|
||||||
|
use fugit::TimerDurationU32;
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use smoltcp::{iface::{self, Interface, SocketHandle, SocketSet, SocketStorage},
|
use smoltcp::{iface::{self, Interface, SocketHandle, SocketSet, SocketStorage},
|
||||||
@ -10,8 +11,10 @@ use stm32_eth::{dma::{EthernetDMA, RxRingEntry, TxRingEntry},
|
|||||||
mac::{EthernetMACWithMii, Speed},
|
mac::{EthernetMACWithMii, Speed},
|
||||||
EthPins, Parts, PartsIn};
|
EthPins, Parts, PartsIn};
|
||||||
use stm32f4xx_hal::{gpio::{gpioa::*, gpiob::*, gpioc::*, Alternate, Input, Pin},
|
use stm32f4xx_hal::{gpio::{gpioa::*, gpiob::*, gpioc::*, Alternate, Input, Pin},
|
||||||
interrupt,
|
pac::{interrupt, Interrupt, Peripherals, TIM5},
|
||||||
rcc::Clocks};
|
rcc::Clocks,
|
||||||
|
timer::{Counter, Event},
|
||||||
|
Listen};
|
||||||
|
|
||||||
use crate::device::sys_timer;
|
use crate::device::sys_timer;
|
||||||
|
|
||||||
@ -34,6 +37,8 @@ impl Default for IpSettings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static mut IFACE_TIMER: Option<IfacePollTimer> = None;
|
||||||
|
|
||||||
pub struct ServerHandle {
|
pub struct ServerHandle {
|
||||||
socket_handles: [SocketHandle; NUM_OF_SOCKETS],
|
socket_handles: [SocketHandle; NUM_OF_SOCKETS],
|
||||||
socket_set: SocketSet<'static>,
|
socket_set: SocketSet<'static>,
|
||||||
@ -62,12 +67,15 @@ fn now_fn() -> smoltcp::time::Instant {
|
|||||||
|
|
||||||
static mut SERVER_HANDLE: Option<ServerHandle> = None;
|
static mut SERVER_HANDLE: Option<ServerHandle> = None;
|
||||||
|
|
||||||
|
pub const FREQ: u32 = 1000000;
|
||||||
|
|
||||||
impl ServerHandle {
|
impl ServerHandle {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
eth_pins: EthernetPins,
|
eth_pins: EthernetPins,
|
||||||
eth_mgmt_pins: EthernetMgmtPins,
|
eth_mgmt_pins: EthernetMgmtPins,
|
||||||
ethernet_parts_in: PartsIn,
|
ethernet_parts_in: PartsIn,
|
||||||
clocks: Clocks,
|
clocks: Clocks,
|
||||||
|
tim5: Counter<TIM5, FREQ>,
|
||||||
mac_addr: [u8; 6],
|
mac_addr: [u8; 6],
|
||||||
ip_settings: IpSettings,
|
ip_settings: IpSettings,
|
||||||
) {
|
) {
|
||||||
@ -154,7 +162,9 @@ impl ServerHandle {
|
|||||||
for i in 0..NUM_OF_SOCKETS {
|
for i in 0..NUM_OF_SOCKETS {
|
||||||
let socket = socket_set.get_mut::<Socket>(tcp_handles[i]);
|
let socket = socket_set.get_mut::<Socket>(tcp_handles[i]);
|
||||||
socket.listen(socket_addr).ok();
|
socket.listen(socket_addr).ok();
|
||||||
socket.set_keep_alive(Some(Duration::from_secs(1)));
|
socket.set_timeout(Some(Duration::from_secs(5)));
|
||||||
|
// Value from Linux net.ipv4.tcp_keepalive_time
|
||||||
|
socket.set_keep_alive(Some(Duration::from_secs(7200)));
|
||||||
socket.set_nagle_enabled(false);
|
socket.set_nagle_enabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,6 +174,8 @@ impl ServerHandle {
|
|||||||
&mut socket_set,
|
&mut socket_set,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
IfacePollTimer::setup(tim5);
|
||||||
|
|
||||||
if let Ok(mut phy) = EthernetPhy::from_miim(mac, 0) {
|
if let Ok(mut phy) = EthernetPhy::from_miim(mac, 0) {
|
||||||
info!("Resetting PHY as an extra step. Type: {}", phy.ident_string());
|
info!("Resetting PHY as an extra step. Type: {}", phy.ident_string());
|
||||||
|
|
||||||
@ -211,6 +223,14 @@ impl ServerHandle {
|
|||||||
self.iface.poll(now_fn(), &mut &mut self.dma, &mut self.socket_set);
|
self.iface.poll(now_fn(), &mut &mut self.dma, &mut self.socket_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn poll_at_iface(&mut self) -> Option<Instant> {
|
||||||
|
self.iface.poll_at(now_fn(), &mut self.socket_set)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poll_delay_iface(&mut self) -> Option<Duration> {
|
||||||
|
self.iface.poll_delay(now_fn(), &mut self.socket_set)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn recv(
|
pub fn recv(
|
||||||
&mut self,
|
&mut self,
|
||||||
buffer: &mut [u8],
|
buffer: &mut [u8],
|
||||||
@ -402,7 +422,17 @@ pub fn eth_poll_link_status_and_update_link_speed() -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eth_poll_iface() {
|
pub fn eth_update_iface_poll_timer() {
|
||||||
|
unsafe {
|
||||||
|
if let Some(ref mut server_handle) = SERVER_HANDLE {
|
||||||
|
IfacePollTimer::set_timer(server_handle.poll_at_iface(), server_handle.poll_delay_iface())
|
||||||
|
} else {
|
||||||
|
panic!("eth_update_iface_poll_timer is called before init")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eth_poll_iface() {
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(ref mut server_handle) = SERVER_HANDLE {
|
if let Some(ref mut server_handle) = SERVER_HANDLE {
|
||||||
server_handle.poll_iface();
|
server_handle.poll_iface();
|
||||||
@ -492,3 +522,97 @@ fn ETH() {
|
|||||||
});
|
});
|
||||||
debug!("Ethernet Interrupt{:?}", interrupt_reason);
|
debug!("Ethernet Interrupt{:?}", interrupt_reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct IfacePollTimer {
|
||||||
|
timer: Counter<TIM5, FREQ>,
|
||||||
|
poll_at_set: Instant,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IfacePollTimer {
|
||||||
|
fn get() -> Option<&'static mut Self> {
|
||||||
|
unsafe { IFACE_TIMER.as_mut() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup(tim5: Counter<TIM5, FREQ>) {
|
||||||
|
unsafe {
|
||||||
|
cortex_m::peripheral::NVIC::unmask(Interrupt::TIM5);
|
||||||
|
IFACE_TIMER = Some(IfacePollTimer {
|
||||||
|
timer: tim5,
|
||||||
|
poll_at_set: Instant::from_micros(u32::max_value()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_timer_running() -> bool {
|
||||||
|
unsafe { Peripherals::steal().TIM5.cr1.read().cen().bit() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_timer(poll_at: Option<Instant>, delay: Option<Duration>) {
|
||||||
|
if let Some(ref mut iface_timer) = IfacePollTimer::get() {
|
||||||
|
if !IfacePollTimer::is_timer_running() {
|
||||||
|
match poll_at {
|
||||||
|
Some(val) => {
|
||||||
|
IfacePollTimer::set_timer_delay(delay);
|
||||||
|
iface_timer.poll_at_set = val;
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match poll_at {
|
||||||
|
Some(val) => {
|
||||||
|
if iface_timer.poll_at_set != val {
|
||||||
|
IfacePollTimer::stop_listening();
|
||||||
|
IfacePollTimer::set_timer_delay(delay);
|
||||||
|
iface_timer.poll_at_set = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_timer_delay(delay: Option<Duration>) {
|
||||||
|
if let Some(ref mut iface_timer) = IfacePollTimer::get() {
|
||||||
|
match delay {
|
||||||
|
Some(val) => {
|
||||||
|
if val.micros() != 0 {
|
||||||
|
match iface_timer.timer.start(TimerDurationU32::micros(val.micros() as u32)) {
|
||||||
|
Ok(_) => {
|
||||||
|
iface_timer.timer.listen(Event::Update);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
debug!("Timer cannot be set {:?}", e)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
eth_poll_iface();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_irq_flag() {
|
||||||
|
if let Some(ref mut iface_timer) = IfacePollTimer::get() {
|
||||||
|
iface_timer.timer.wait().ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stop_listening() {
|
||||||
|
if let Some(ref mut iface_timer) = IfacePollTimer::get() {
|
||||||
|
iface_timer.timer.unlisten(Event::Update);
|
||||||
|
iface_timer.timer.cancel().ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[interrupt]
|
||||||
|
fn TIM5() {
|
||||||
|
eth_poll_iface();
|
||||||
|
cortex_m::interrupt::free(|_| {
|
||||||
|
IfacePollTimer::stop_listening();
|
||||||
|
IfacePollTimer::clear_irq_flag();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user