Compare commits
2 Commits
b8241d1f27
...
4142519104
Author | SHA1 | Date |
---|---|---|
linuswck | 4142519104 | |
linuswck | 70fed23c51 |
|
@ -109,6 +109,7 @@ pub fn bootup(
|
|||
eth_mgmt_pins,
|
||||
ethernet_parts_in,
|
||||
clocks,
|
||||
perif.TIM5.counter(&clocks),
|
||||
mac_addr,
|
||||
ip_settings,
|
||||
);
|
||||
|
|
33
src/main.rs
33
src/main.rs
|
@ -140,10 +140,10 @@ fn main() -> ! {
|
|||
laser.load_settings_from_summary(laser_settings);
|
||||
}
|
||||
State::MainLoop => {
|
||||
let mut eth_is_pending = false;
|
||||
|
||||
laser.poll_and_update_output_current();
|
||||
|
||||
net::net::eth_update_iface_poll_timer();
|
||||
|
||||
if thermostat.poll_adc() {
|
||||
thermostat.update_pid();
|
||||
if thermostat.get_temp_mon_status().over_temp_alarm {
|
||||
|
@ -155,12 +155,14 @@ fn main() -> ! {
|
|||
net::net::for_each(|mut socket, id| {
|
||||
if net::net::eth_is_socket_active(socket) && net::net::eth_is_socket_connected(socket) {
|
||||
if active_report[id] {
|
||||
net::cmd_handler::send_status_report(
|
||||
eth_data_buffer,
|
||||
&mut laser,
|
||||
&mut thermostat,
|
||||
&mut socket,
|
||||
);
|
||||
if net::net::eth_can_sock_send(socket) {
|
||||
net::cmd_handler::send_status_report(
|
||||
eth_data_buffer,
|
||||
&mut laser,
|
||||
&mut thermostat,
|
||||
&mut socket,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
active_report[id] = false;
|
||||
|
@ -169,13 +171,10 @@ fn main() -> ! {
|
|||
|
||||
thermostat.start_tec_readings_conversion();
|
||||
}
|
||||
cortex_m::interrupt::free(|cs| {
|
||||
eth_is_pending = net::net::is_pending(cs);
|
||||
net::net::clear_pending(cs);
|
||||
});
|
||||
if eth_is_pending {
|
||||
net::net::for_each(|mut socket, id| {
|
||||
if net::net::eth_is_socket_active(socket) && net::net::eth_is_socket_connected(socket) {
|
||||
|
||||
net::net::for_each(|mut socket, id| {
|
||||
if net::net::eth_is_socket_active(socket) && net::net::eth_is_socket_connected(socket) {
|
||||
if net::net::eth_can_sock_recv(socket) && net::net::eth_can_sock_send(socket) {
|
||||
let bytes = net::net::eth_recv(eth_data_buffer, socket);
|
||||
if bytes != 0 {
|
||||
info!("Ts: {:?}", sys_timer::now());
|
||||
|
@ -193,8 +192,8 @@ fn main() -> ! {
|
|||
);
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
}
|
||||
})
|
||||
}
|
||||
State::SaveLdThermostatSettings => {
|
||||
// State Transition
|
||||
|
|
184
src/net/net.rs
184
src/net/net.rs
|
@ -1,7 +1,6 @@
|
|||
use core::{cell::RefCell,
|
||||
mem::{self, MaybeUninit}};
|
||||
use core::mem::{self, MaybeUninit};
|
||||
|
||||
use cortex_m::interrupt::{CriticalSection, Mutex};
|
||||
use fugit::TimerDurationU32;
|
||||
use log::{debug, info};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smoltcp::{iface::{self, Interface, SocketHandle, SocketSet, SocketStorage},
|
||||
|
@ -12,8 +11,10 @@ use stm32_eth::{dma::{EthernetDMA, RxRingEntry, TxRingEntry},
|
|||
mac::{EthernetMACWithMii, Speed},
|
||||
EthPins, Parts, PartsIn};
|
||||
use stm32f4xx_hal::{gpio::{gpioa::*, gpiob::*, gpioc::*, Alternate, Input, Pin},
|
||||
interrupt,
|
||||
rcc::Clocks};
|
||||
pac::{interrupt, Interrupt, Peripherals, TIM5},
|
||||
rcc::Clocks,
|
||||
timer::{Counter, Event},
|
||||
Listen};
|
||||
|
||||
use crate::device::sys_timer;
|
||||
|
||||
|
@ -36,9 +37,7 @@ impl Default for IpSettings {
|
|||
}
|
||||
}
|
||||
|
||||
/// Interrupt pending flag: set by the `ETH` interrupt handler, should
|
||||
/// be cleared before polling the interface.
|
||||
static NET_PENDING: Mutex<RefCell<bool>> = Mutex::new(RefCell::new(false));
|
||||
static mut IFACE_TIMER: Option<IfacePollTimer> = None;
|
||||
|
||||
pub struct ServerHandle {
|
||||
socket_handles: [SocketHandle; NUM_OF_SOCKETS],
|
||||
|
@ -68,12 +67,15 @@ fn now_fn() -> smoltcp::time::Instant {
|
|||
|
||||
static mut SERVER_HANDLE: Option<ServerHandle> = None;
|
||||
|
||||
pub const FREQ: u32 = 1000000;
|
||||
|
||||
impl ServerHandle {
|
||||
pub fn new(
|
||||
eth_pins: EthernetPins,
|
||||
eth_mgmt_pins: EthernetMgmtPins,
|
||||
ethernet_parts_in: PartsIn,
|
||||
clocks: Clocks,
|
||||
tim5: Counter<TIM5, FREQ>,
|
||||
mac_addr: [u8; 6],
|
||||
ip_settings: IpSettings,
|
||||
) {
|
||||
|
@ -160,7 +162,9 @@ impl ServerHandle {
|
|||
for i in 0..NUM_OF_SOCKETS {
|
||||
let socket = socket_set.get_mut::<Socket>(tcp_handles[i]);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -170,6 +174,8 @@ impl ServerHandle {
|
|||
&mut socket_set,
|
||||
);
|
||||
|
||||
IfacePollTimer::setup(tim5);
|
||||
|
||||
if let Ok(mut phy) = EthernetPhy::from_miim(mac, 0) {
|
||||
info!("Resetting PHY as an extra step. Type: {}", phy.ident_string());
|
||||
|
||||
|
@ -217,6 +223,14 @@ impl ServerHandle {
|
|||
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(
|
||||
&mut self,
|
||||
buffer: &mut [u8],
|
||||
|
@ -230,9 +244,15 @@ impl ServerHandle {
|
|||
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();
|
||||
self.poll_iface();
|
||||
info!("Sent {} bytes.", num_bytes);
|
||||
match socket.send_slice(&buffer[..num_bytes]) {
|
||||
Ok(_) => {
|
||||
self.poll_iface();
|
||||
info!("Sent {} bytes.", num_bytes);
|
||||
}
|
||||
Err(err) => {
|
||||
info!("Bytes cannot be sent. Error: {:?}", err)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,6 +278,14 @@ impl ServerHandle {
|
|||
let socket = self.socket_set.get_mut::<Socket>(socket_handles);
|
||||
socket.abort();
|
||||
}
|
||||
|
||||
pub fn can_send(&mut self, socket_handles: SocketHandle) -> bool {
|
||||
self.socket_set.get_mut::<Socket>(socket_handles).can_send()
|
||||
}
|
||||
|
||||
pub fn can_recv(&mut self, socket_handles: SocketHandle) -> bool {
|
||||
self.socket_set.get_mut::<Socket>(socket_handles).can_recv()
|
||||
}
|
||||
}
|
||||
|
||||
use ieee802_3_miim::{phy::{lan87xxa::{LAN8720A, LAN8742A},
|
||||
|
@ -357,6 +385,26 @@ impl<M: Miim> EthernetPhy<M> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn eth_can_sock_send(socket_handles: SocketHandle) -> bool {
|
||||
unsafe {
|
||||
if let Some(ref mut server_handle) = SERVER_HANDLE {
|
||||
server_handle.can_send(socket_handles)
|
||||
} else {
|
||||
panic!("eth_check_if_sock_can_send is called before init");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eth_can_sock_recv(socket_handles: SocketHandle) -> bool {
|
||||
unsafe {
|
||||
if let Some(ref mut server_handle) = SERVER_HANDLE {
|
||||
server_handle.can_recv(socket_handles)
|
||||
} else {
|
||||
panic!("eth_check_if_sock_can_recv is called before init");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eth_poll_link_status_and_update_link_speed() -> bool {
|
||||
unsafe {
|
||||
if let Some(ref mut server_handle) = SERVER_HANDLE {
|
||||
|
@ -374,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 {
|
||||
if let Some(ref mut server_handle) = SERVER_HANDLE {
|
||||
server_handle.poll_iface();
|
||||
|
@ -457,22 +515,104 @@ pub fn for_each<F: FnMut(SocketHandle, usize)>(mut callback: F) {
|
|||
#[interrupt]
|
||||
fn ETH() {
|
||||
let interrupt_reason = stm32_eth::eth_interrupt_handler();
|
||||
cortex_m::interrupt::free(|cs| {
|
||||
cortex_m::interrupt::free(|_| {
|
||||
if interrupt_reason.rx {
|
||||
*NET_PENDING.borrow(cs).borrow_mut() = true;
|
||||
eth_poll_iface();
|
||||
}
|
||||
});
|
||||
debug!("Ethernet Interrupt{:?}", interrupt_reason);
|
||||
}
|
||||
|
||||
/// Has an interrupt occurred since last call to `clear_pending()`?
|
||||
pub fn is_pending(cs: &CriticalSection) -> bool {
|
||||
*NET_PENDING.borrow(cs).borrow()
|
||||
pub struct IfacePollTimer {
|
||||
timer: Counter<TIM5, FREQ>,
|
||||
poll_at_set: Instant,
|
||||
}
|
||||
|
||||
/// Clear the interrupt pending flag before polling the interface for
|
||||
/// data.
|
||||
pub fn clear_pending(cs: &CriticalSection) {
|
||||
*NET_PENDING.borrow(cs).borrow_mut() = false;
|
||||
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