2024-04-29 17:57:45 +08:00
|
|
|
use core::mem::{self, MaybeUninit};
|
2024-04-23 17:09:26 +08:00
|
|
|
|
2024-05-02 10:25:13 +08:00
|
|
|
use fugit::TimerDurationU32;
|
2024-03-04 16:13:52 +08:00
|
|
|
use log::{debug, info};
|
2024-03-05 16:44:03 +08:00
|
|
|
use serde::{Deserialize, Serialize};
|
2024-04-23 17:09:26 +08:00
|
|
|
use smoltcp::{iface::{self, Interface, SocketHandle, SocketSet, SocketStorage},
|
|
|
|
socket::tcp::{Socket, SocketBuffer, State},
|
|
|
|
time::{Duration, Instant},
|
|
|
|
wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address, Ipv4Cidr}};
|
|
|
|
use stm32_eth::{dma::{EthernetDMA, RxRingEntry, TxRingEntry},
|
|
|
|
mac::{EthernetMACWithMii, Speed},
|
|
|
|
EthPins, Parts, PartsIn};
|
|
|
|
use stm32f4xx_hal::{gpio::{gpioa::*, gpiob::*, gpioc::*, Alternate, Input, Pin},
|
2024-05-02 10:25:13 +08:00
|
|
|
pac::{interrupt, Interrupt, Peripherals, TIM5},
|
|
|
|
rcc::Clocks,
|
|
|
|
timer::{Counter, Event},
|
|
|
|
Listen};
|
2024-04-23 17:09:26 +08:00
|
|
|
|
|
|
|
use crate::device::sys_timer;
|
2024-01-31 17:16:10 +08:00
|
|
|
|
2024-03-05 16:44:03 +08:00
|
|
|
#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
|
|
|
|
pub struct IpSettings {
|
|
|
|
addr: [u8; 4],
|
|
|
|
port: u16,
|
|
|
|
prefix_len: u8,
|
2024-03-06 10:34:57 +08:00
|
|
|
gateway: [u8; 4],
|
2024-03-05 16:44:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for IpSettings {
|
|
|
|
fn default() -> Self {
|
|
|
|
IpSettings {
|
2024-03-06 16:29:02 +08:00
|
|
|
addr: [192, 168, 1, 128],
|
2024-03-05 16:44:03 +08:00
|
|
|
port: 1337,
|
|
|
|
prefix_len: 24,
|
2024-04-23 17:09:26 +08:00
|
|
|
gateway: [192, 168, 1, 1],
|
2024-03-05 16:44:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-01-31 17:16:10 +08:00
|
|
|
|
2024-05-02 10:25:13 +08:00
|
|
|
static mut IFACE_TIMER: Option<IfacePollTimer> = None;
|
|
|
|
|
2024-01-31 17:16:10 +08:00
|
|
|
pub struct ServerHandle {
|
2024-03-06 16:29:02 +08:00
|
|
|
socket_handles: [SocketHandle; NUM_OF_SOCKETS],
|
2024-01-31 17:16:10 +08:00
|
|
|
socket_set: SocketSet<'static>,
|
2024-03-05 16:44:03 +08:00
|
|
|
socket_addr: (IpAddress, u16),
|
2024-01-31 17:16:10 +08:00
|
|
|
iface: EthInterface,
|
|
|
|
dma: EthernetDMA<'static, 'static>,
|
2024-03-06 12:15:08 +08:00
|
|
|
phy: EthernetPhy<EthernetMACWithMii<Pin<'A', 2, Alternate<11>>, Pin<'C', 1, Alternate<11>>>>,
|
|
|
|
link_was_up: bool,
|
2024-01-31 17:16:10 +08:00
|
|
|
}
|
2024-04-23 17:09:26 +08:00
|
|
|
pub type EthernetPins = EthPins<PA1<Input>, PA7<Input>, PB11<Input>, PB12<Input>, PB13<Input>, PC4<Input>, PC5<Input>>;
|
2024-01-31 17:16:10 +08:00
|
|
|
pub struct EthernetMgmtPins {
|
|
|
|
pub mdio: PA2<Alternate<11>>,
|
|
|
|
pub mdc: PC1<Alternate<11>>,
|
|
|
|
}
|
|
|
|
pub type EthInterface = Interface;
|
|
|
|
|
2024-04-23 17:09:26 +08:00
|
|
|
pub const NUM_OF_SOCKETS: usize = 4;
|
|
|
|
const TCP_BUFFER_SIZE: usize = 4096;
|
2024-01-31 17:16:10 +08:00
|
|
|
static mut RX_RING: Option<[RxRingEntry; 8]> = None;
|
2024-04-23 17:09:26 +08:00
|
|
|
static mut TX_RING: Option<[TxRingEntry; 8]> = None;
|
2024-03-06 16:29:02 +08:00
|
|
|
static mut SOCKET_STORAGE: Option<[SocketStorage<'static>; NUM_OF_SOCKETS]> = None;
|
2024-01-31 17:16:10 +08:00
|
|
|
|
|
|
|
fn now_fn() -> smoltcp::time::Instant {
|
|
|
|
Instant::from_millis(i64::from(sys_timer::now()))
|
|
|
|
}
|
|
|
|
|
2024-04-23 17:09:26 +08:00
|
|
|
static mut SERVER_HANDLE: Option<ServerHandle> = None;
|
2024-01-31 17:16:10 +08:00
|
|
|
|
2024-05-02 10:25:13 +08:00
|
|
|
pub const FREQ: u32 = 1000000;
|
|
|
|
|
2024-01-31 17:16:10 +08:00
|
|
|
impl ServerHandle {
|
2024-04-23 17:09:26 +08:00
|
|
|
pub fn new(
|
|
|
|
eth_pins: EthernetPins,
|
2024-01-31 17:16:10 +08:00
|
|
|
eth_mgmt_pins: EthernetMgmtPins,
|
|
|
|
ethernet_parts_in: PartsIn,
|
|
|
|
clocks: Clocks,
|
2024-05-02 10:25:13 +08:00
|
|
|
tim5: Counter<TIM5, FREQ>,
|
2024-03-05 16:44:03 +08:00
|
|
|
mac_addr: [u8; 6],
|
|
|
|
ip_settings: IpSettings,
|
2024-04-23 17:09:26 +08:00
|
|
|
) {
|
2024-01-31 17:16:10 +08:00
|
|
|
let rx_ring = unsafe { RX_RING.get_or_insert(Default::default()) };
|
|
|
|
let tx_ring = unsafe { TX_RING.get_or_insert(Default::default()) };
|
2024-03-06 16:29:02 +08:00
|
|
|
let socket_storage = unsafe { SOCKET_STORAGE.get_or_insert([SocketStorage::EMPTY; NUM_OF_SOCKETS]) };
|
2024-01-31 17:16:10 +08:00
|
|
|
|
2024-04-23 17:09:26 +08:00
|
|
|
let Parts { mut dma, mac, .. } = stm32_eth::new_with_mii(
|
2024-01-31 17:16:10 +08:00
|
|
|
ethernet_parts_in,
|
|
|
|
&mut rx_ring[..],
|
|
|
|
&mut tx_ring[..],
|
|
|
|
clocks,
|
|
|
|
eth_pins,
|
|
|
|
eth_mgmt_pins.mdio,
|
2024-04-23 17:09:26 +08:00
|
|
|
eth_mgmt_pins.mdc,
|
|
|
|
)
|
|
|
|
.unwrap();
|
2024-01-31 17:16:10 +08:00
|
|
|
|
2024-03-05 16:44:03 +08:00
|
|
|
let ip_init = IpCidr::Ipv4(Ipv4Cidr::new(
|
2024-04-23 17:09:26 +08:00
|
|
|
Ipv4Address::new(
|
|
|
|
ip_settings.addr[0],
|
|
|
|
ip_settings.addr[1],
|
|
|
|
ip_settings.addr[2],
|
|
|
|
ip_settings.addr[3],
|
|
|
|
),
|
2024-03-05 16:44:03 +08:00
|
|
|
ip_settings.prefix_len,
|
|
|
|
));
|
|
|
|
let socket_addr: (IpAddress, u16) = (
|
|
|
|
IpAddress::Ipv4(Ipv4Address::new(
|
|
|
|
ip_settings.addr[0],
|
|
|
|
ip_settings.addr[1],
|
|
|
|
ip_settings.addr[2],
|
|
|
|
ip_settings.addr[3],
|
|
|
|
)),
|
|
|
|
ip_settings.port,
|
|
|
|
);
|
|
|
|
|
2024-01-31 17:16:10 +08:00
|
|
|
let mut routes = smoltcp::iface::Routes::new();
|
|
|
|
routes
|
2024-04-23 17:09:26 +08:00
|
|
|
.add_default_ipv4_route(Ipv4Address::new(
|
|
|
|
ip_settings.gateway[0],
|
|
|
|
ip_settings.gateway[1],
|
|
|
|
ip_settings.gateway[2],
|
|
|
|
ip_settings.gateway[3],
|
|
|
|
))
|
2024-01-31 17:16:10 +08:00
|
|
|
.ok();
|
|
|
|
dma.enable_interrupt();
|
|
|
|
|
2024-02-16 15:38:05 +08:00
|
|
|
let config = iface::Config::new(EthernetAddress::from_bytes(&mac_addr).into());
|
2024-01-31 17:16:10 +08:00
|
|
|
let mut iface = Interface::new(config, &mut &mut dma, smoltcp::time::Instant::ZERO);
|
2024-02-16 15:38:05 +08:00
|
|
|
iface.set_hardware_addr(EthernetAddress(mac_addr).into());
|
|
|
|
debug!("MAC ADDRESS: {:02X?}", EthernetAddress(mac_addr));
|
2024-03-05 16:44:03 +08:00
|
|
|
debug!("IP Settings: {:?}", ip_settings);
|
2024-01-31 17:16:10 +08:00
|
|
|
iface.update_ip_addrs(|addr| {
|
2024-03-05 16:44:03 +08:00
|
|
|
addr.push(ip_init).unwrap();
|
2024-01-31 17:16:10 +08:00
|
|
|
});
|
|
|
|
|
2024-03-06 16:29:02 +08:00
|
|
|
let mut socket_set = SocketSet::new(&mut socket_storage[..]);
|
|
|
|
|
|
|
|
let tcp_handles = {
|
2024-04-23 17:09:26 +08:00
|
|
|
// Do not use NUM_OF_SOCKETS to define array size to
|
2024-03-06 16:29:02 +08:00
|
|
|
// remind developers to create/remove tcp_handles accordingly after changing NUM_OF_SOCKETS
|
2024-04-23 17:09:26 +08:00
|
|
|
let mut tcp_handles: [MaybeUninit<SocketHandle>; 4] = unsafe { MaybeUninit::uninit().assume_init() };
|
2024-03-06 16:29:02 +08:00
|
|
|
|
|
|
|
macro_rules! create_tcp_handle {
|
|
|
|
($rx_storage:ident, $tx_storage:ident, $handle:expr) => {
|
2024-04-23 17:09:26 +08:00
|
|
|
static mut $rx_storage: [u8; TCP_BUFFER_SIZE] = [0; TCP_BUFFER_SIZE];
|
|
|
|
static mut $tx_storage: [u8; TCP_BUFFER_SIZE] = [0; TCP_BUFFER_SIZE];
|
2024-03-06 16:29:02 +08:00
|
|
|
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)));
|
|
|
|
}
|
2024-04-23 17:09:26 +08:00
|
|
|
};
|
2024-03-06 16:29:02 +08:00
|
|
|
}
|
|
|
|
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) }
|
|
|
|
};
|
2024-04-23 17:09:26 +08:00
|
|
|
|
2024-03-06 16:29:02 +08:00
|
|
|
for i in 0..NUM_OF_SOCKETS {
|
|
|
|
let socket = socket_set.get_mut::<Socket>(tcp_handles[i]);
|
|
|
|
socket.listen(socket_addr).ok();
|
2024-05-02 10:25:13 +08:00
|
|
|
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)));
|
2024-04-22 16:39:30 +08:00
|
|
|
socket.set_nagle_enabled(false);
|
2024-03-06 16:29:02 +08:00
|
|
|
}
|
2024-04-23 17:09:26 +08:00
|
|
|
|
|
|
|
iface.poll(
|
|
|
|
Instant::from_millis(i64::from(sys_timer::now())),
|
|
|
|
&mut &mut dma,
|
|
|
|
&mut socket_set,
|
|
|
|
);
|
|
|
|
|
2024-05-02 10:25:13 +08:00
|
|
|
IfacePollTimer::setup(tim5);
|
|
|
|
|
2024-01-31 17:16:10 +08:00
|
|
|
if let Ok(mut phy) = EthernetPhy::from_miim(mac, 0) {
|
2024-04-23 17:09:26 +08:00
|
|
|
info!("Resetting PHY as an extra step. Type: {}", phy.ident_string());
|
2024-01-31 17:16:10 +08:00
|
|
|
|
|
|
|
phy.phy_init();
|
2024-04-23 17:09:26 +08:00
|
|
|
|
2024-03-06 12:15:08 +08:00
|
|
|
let server = ServerHandle {
|
2024-03-06 16:29:02 +08:00
|
|
|
socket_handles: tcp_handles,
|
|
|
|
socket_set: socket_set,
|
2024-03-06 12:15:08 +08:00
|
|
|
socket_addr: socket_addr,
|
|
|
|
iface: iface,
|
|
|
|
dma: dma,
|
|
|
|
phy: phy,
|
|
|
|
link_was_up: false,
|
|
|
|
};
|
2024-04-23 17:09:26 +08:00
|
|
|
|
2024-03-06 12:15:08 +08:00
|
|
|
unsafe {
|
|
|
|
SERVER_HANDLE = Some(server);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
panic!("Ethernet Phy is not supported");
|
|
|
|
}
|
|
|
|
}
|
2024-02-28 12:58:57 +08:00
|
|
|
|
2024-04-23 17:09:26 +08:00
|
|
|
pub fn update_link_speed(&mut self) -> bool {
|
2024-03-06 12:15:08 +08:00
|
|
|
if !self.link_was_up & self.phy.phy_link_up() {
|
|
|
|
if let Some(speed) = self.phy.speed().map(|s| match s {
|
2024-02-28 12:58:57 +08:00
|
|
|
PhySpeed::HalfDuplexBase10T => Speed::HalfDuplexBase10T,
|
|
|
|
PhySpeed::FullDuplexBase10T => Speed::FullDuplexBase10T,
|
|
|
|
PhySpeed::HalfDuplexBase100Tx => Speed::HalfDuplexBase100Tx,
|
|
|
|
PhySpeed::FullDuplexBase100Tx => Speed::FullDuplexBase100Tx,
|
|
|
|
}) {
|
2024-03-06 12:15:08 +08:00
|
|
|
info!("New eth link is up. Setting detected PhySpeed: {:?}", speed);
|
|
|
|
self.phy.get_miim().set_speed(speed);
|
2024-04-22 16:01:32 +08:00
|
|
|
self.link_was_up = self.phy.phy_link_up();
|
|
|
|
return true;
|
2024-02-28 12:58:57 +08:00
|
|
|
} else {
|
|
|
|
debug!("Failed to detect link speed.");
|
|
|
|
}
|
2024-01-31 17:16:10 +08:00
|
|
|
}
|
2024-03-06 12:15:08 +08:00
|
|
|
self.link_was_up = self.phy.phy_link_up();
|
2024-04-22 16:01:32 +08:00
|
|
|
return false;
|
2024-01-31 17:16:10 +08:00
|
|
|
}
|
|
|
|
|
2024-03-20 14:25:35 +08:00
|
|
|
pub fn poll_iface(&mut self) {
|
2024-04-23 17:09:26 +08:00
|
|
|
self.iface.poll(now_fn(), &mut &mut self.dma, &mut self.socket_set);
|
2024-03-20 14:25:35 +08:00
|
|
|
}
|
|
|
|
|
2024-05-02 10:25:13 +08:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2024-04-23 17:09:26 +08:00
|
|
|
pub fn recv(
|
|
|
|
&mut self,
|
|
|
|
buffer: &mut [u8],
|
|
|
|
socket_handles: SocketHandle,
|
|
|
|
) -> Result<usize, smoltcp::socket::tcp::RecvError> {
|
2024-03-06 16:29:02 +08:00
|
|
|
let socket = self.socket_set.get_mut::<Socket>(socket_handles);
|
2024-02-02 14:07:25 +08:00
|
|
|
|
|
|
|
socket.recv_slice(buffer)
|
|
|
|
}
|
|
|
|
|
2024-03-06 16:29:02 +08:00
|
|
|
pub fn send(&mut self, buffer: &mut [u8], num_bytes: usize, socket_handles: SocketHandle) {
|
|
|
|
let socket = self.socket_set.get_mut::<Socket>(socket_handles);
|
2024-02-02 14:07:25 +08:00
|
|
|
if num_bytes > 0 {
|
2024-04-29 17:57:45 +08:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
};
|
2024-02-02 14:07:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-23 17:09:26 +08:00
|
|
|
pub fn is_socket_connected(&mut self, socket_handles: SocketHandle) -> bool {
|
2024-03-19 17:38:29 +08:00
|
|
|
let socket = self.socket_set.get_mut::<Socket>(socket_handles);
|
|
|
|
socket.state() == State::Established
|
|
|
|
}
|
|
|
|
|
2024-04-23 17:09:26 +08:00
|
|
|
pub fn poll_socket_status(&mut self, socket_handles: SocketHandle) -> bool {
|
2024-03-06 16:29:02 +08:00
|
|
|
let socket = self.socket_set.get_mut::<Socket>(socket_handles);
|
2024-02-02 14:07:25 +08:00
|
|
|
if !socket.is_listening() && !socket.is_open() || socket.state() == State::CloseWait {
|
|
|
|
socket.abort();
|
2024-03-05 16:44:03 +08:00
|
|
|
socket.listen(self.socket_addr).ok();
|
2024-02-02 14:07:25 +08:00
|
|
|
info!("Disconnected... Reopening listening socket.");
|
|
|
|
return false;
|
|
|
|
} else if socket.state() == State::Closed || socket.state() == State::Closing {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2024-02-16 16:47:17 +08:00
|
|
|
|
2024-03-06 16:29:02 +08:00
|
|
|
pub fn close_socket(&mut self, socket_handles: SocketHandle) {
|
|
|
|
let socket = self.socket_set.get_mut::<Socket>(socket_handles);
|
2024-02-16 16:47:17 +08:00
|
|
|
socket.abort();
|
|
|
|
}
|
2024-04-29 17:57:45 +08:00
|
|
|
|
|
|
|
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()
|
|
|
|
}
|
2024-01-31 17:16:10 +08:00
|
|
|
}
|
|
|
|
|
2024-04-23 17:09:26 +08:00
|
|
|
use ieee802_3_miim::{phy::{lan87xxa::{LAN8720A, LAN8742A},
|
|
|
|
BarePhy, PhySpeed, KSZ8081R},
|
|
|
|
Miim, Pause, Phy};
|
2024-01-31 17:16:10 +08:00
|
|
|
|
|
|
|
/// An ethernet PHY
|
|
|
|
pub enum EthernetPhy<M: Miim> {
|
|
|
|
/// LAN8720A
|
|
|
|
LAN8720A(LAN8720A<M>),
|
|
|
|
/// LAN8742A
|
|
|
|
LAN8742A(LAN8742A<M>),
|
|
|
|
/// KSZ8081R
|
|
|
|
KSZ8081R(KSZ8081R<M>),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<M: Miim> Phy<M> for EthernetPhy<M> {
|
|
|
|
fn best_supported_advertisement(&self) -> ieee802_3_miim::AutoNegotiationAdvertisement {
|
|
|
|
unimplemented!()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_miim(&mut self) -> &mut M {
|
|
|
|
match self {
|
|
|
|
EthernetPhy::LAN8720A(phy) => phy.get_miim(),
|
|
|
|
EthernetPhy::LAN8742A(phy) => phy.get_miim(),
|
|
|
|
EthernetPhy::KSZ8081R(phy) => phy.get_miim(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_phy_addr(&self) -> u8 {
|
|
|
|
match self {
|
|
|
|
EthernetPhy::LAN8720A(phy) => phy.get_phy_addr(),
|
|
|
|
EthernetPhy::LAN8742A(phy) => phy.get_phy_addr(),
|
|
|
|
EthernetPhy::KSZ8081R(phy) => phy.get_phy_addr(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<M: Miim> EthernetPhy<M> {
|
|
|
|
/// Attempt to create one of the known PHYs from the given
|
|
|
|
/// MIIM.
|
|
|
|
///
|
|
|
|
/// Returns an error if the PHY does not support the extended register
|
|
|
|
/// set, or if the PHY's identifier does not correspond to a known PHY.
|
|
|
|
pub fn from_miim(miim: M, phy_addr: u8) -> Result<Self, M> {
|
|
|
|
let mut bare = BarePhy::new(miim, phy_addr, Pause::NoPause);
|
|
|
|
let phy_ident = if let Some(id) = bare.phy_ident() {
|
|
|
|
id.raw_u32()
|
|
|
|
} else {
|
|
|
|
return Err(bare.release());
|
|
|
|
};
|
|
|
|
let miim = bare.release();
|
|
|
|
match phy_ident & 0xFFFFFFF0 {
|
|
|
|
0x0007C0F0 => Ok(Self::LAN8720A(LAN8720A::new(miim, phy_addr))),
|
|
|
|
0x0007C130 => Ok(Self::LAN8742A(LAN8742A::new(miim, phy_addr))),
|
|
|
|
0x00221560 => Ok(Self::KSZ8081R(KSZ8081R::new(miim, phy_addr))),
|
|
|
|
_ => Err(miim),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get a string describing the type of PHY
|
|
|
|
pub const fn ident_string(&self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
EthernetPhy::LAN8720A(_) => "LAN8720A",
|
|
|
|
EthernetPhy::LAN8742A(_) => "LAN8742A",
|
|
|
|
EthernetPhy::KSZ8081R(_) => "KSZ8081R",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Initialize the PHY
|
|
|
|
pub fn phy_init(&mut self) {
|
|
|
|
match self {
|
|
|
|
EthernetPhy::LAN8720A(phy) => phy.phy_init(),
|
|
|
|
EthernetPhy::LAN8742A(phy) => phy.phy_init(),
|
|
|
|
EthernetPhy::KSZ8081R(phy) => {
|
|
|
|
phy.set_autonegotiation_advertisement(phy.best_supported_advertisement());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
pub fn speed(&mut self) -> Option<ieee802_3_miim::phy::PhySpeed> {
|
|
|
|
match self {
|
|
|
|
EthernetPhy::LAN8720A(phy) => phy.link_speed(),
|
|
|
|
EthernetPhy::LAN8742A(phy) => phy.link_speed(),
|
|
|
|
EthernetPhy::KSZ8081R(phy) => phy.link_speed(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
pub fn release(self) -> M {
|
|
|
|
match self {
|
|
|
|
EthernetPhy::LAN8720A(phy) => phy.release(),
|
|
|
|
EthernetPhy::LAN8742A(phy) => phy.release(),
|
|
|
|
EthernetPhy::KSZ8081R(phy) => phy.release(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-29 17:57:45 +08:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-18 17:32:58 +08:00
|
|
|
pub fn eth_poll_link_status_and_update_link_speed() -> bool {
|
2024-03-06 12:15:08 +08:00
|
|
|
unsafe {
|
2024-04-23 17:09:26 +08:00
|
|
|
if let Some(ref mut server_handle) = SERVER_HANDLE {
|
2024-04-22 16:01:32 +08:00
|
|
|
let new_link_is_up = server_handle.update_link_speed();
|
|
|
|
if new_link_is_up {
|
|
|
|
info!("Resetting TCP Sockets");
|
|
|
|
for_each(|socket, _| {
|
|
|
|
eth_close_socket(socket);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return new_link_is_up;
|
2024-04-23 17:09:26 +08:00
|
|
|
} else {
|
2024-04-18 17:32:58 +08:00
|
|
|
panic!("eth_poll_link_status_and_update_link_speed is called before init");
|
2024-03-06 12:15:08 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-02 10:25:13 +08:00
|
|
|
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() {
|
2024-03-20 14:25:35 +08:00
|
|
|
unsafe {
|
2024-04-23 17:09:26 +08:00
|
|
|
if let Some(ref mut server_handle) = SERVER_HANDLE {
|
2024-03-20 14:25:35 +08:00
|
|
|
server_handle.poll_iface();
|
2024-04-23 17:09:26 +08:00
|
|
|
} else {
|
2024-03-20 14:25:35 +08:00
|
|
|
panic!("eth_poll_packet is called before init");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-06 16:29:02 +08:00
|
|
|
pub fn eth_send(buffer: &mut [u8], num_bytes: usize, socket_handles: SocketHandle) {
|
2024-02-02 14:07:25 +08:00
|
|
|
unsafe {
|
2024-04-23 17:09:26 +08:00
|
|
|
if let Some(ref mut server_handle) = SERVER_HANDLE {
|
2024-03-06 16:29:02 +08:00
|
|
|
server_handle.send(buffer, num_bytes, socket_handles);
|
2024-04-23 17:09:26 +08:00
|
|
|
} else {
|
2024-02-02 14:07:25 +08:00
|
|
|
panic!("eth_send is called before init");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-23 17:09:26 +08:00
|
|
|
pub fn eth_recv(buffer: &mut [u8], socket_handles: SocketHandle) -> usize {
|
2024-02-02 14:07:25 +08:00
|
|
|
unsafe {
|
2024-04-23 17:09:26 +08:00
|
|
|
if let Some(ref mut server_handle) = SERVER_HANDLE {
|
|
|
|
match server_handle.recv(buffer, socket_handles) {
|
|
|
|
Ok(recv_bytes) => return recv_bytes,
|
2024-02-02 14:07:25 +08:00
|
|
|
Err(err) => {
|
|
|
|
debug!("TCP Recv Error: {}", err);
|
2024-04-23 17:09:26 +08:00
|
|
|
return 0;
|
2024-02-02 14:07:25 +08:00
|
|
|
}
|
|
|
|
};
|
2024-04-23 17:09:26 +08:00
|
|
|
} else {
|
2024-02-02 14:07:25 +08:00
|
|
|
panic!("eth_send is called before init");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-19 17:38:29 +08:00
|
|
|
pub fn eth_is_socket_connected(socket_handles: SocketHandle) -> bool {
|
|
|
|
unsafe {
|
2024-04-23 17:09:26 +08:00
|
|
|
if let Some(ref mut server_handle) = SERVER_HANDLE {
|
2024-03-19 17:38:29 +08:00
|
|
|
server_handle.is_socket_connected(socket_handles)
|
2024-04-23 17:09:26 +08:00
|
|
|
} else {
|
2024-03-19 17:38:29 +08:00
|
|
|
panic!("eth_is_socket_connected is called before init");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-06 16:29:02 +08:00
|
|
|
pub fn eth_is_socket_active(socket_handles: SocketHandle) -> bool {
|
2024-02-02 14:07:25 +08:00
|
|
|
unsafe {
|
2024-04-23 17:09:26 +08:00
|
|
|
if let Some(ref mut server_handle) = SERVER_HANDLE {
|
2024-03-06 16:29:02 +08:00
|
|
|
server_handle.poll_socket_status(socket_handles)
|
2024-04-23 17:09:26 +08:00
|
|
|
} else {
|
2024-02-02 14:07:25 +08:00
|
|
|
panic!("eth_is_socket_active is called before init");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-06 16:29:02 +08:00
|
|
|
pub fn eth_close_socket(socket_handles: SocketHandle) {
|
|
|
|
unsafe {
|
2024-04-23 17:09:26 +08:00
|
|
|
if let Some(ref mut server_handle) = SERVER_HANDLE {
|
2024-03-06 16:29:02 +08:00
|
|
|
server_handle.close_socket(socket_handles)
|
2024-04-23 17:09:26 +08:00
|
|
|
} else {
|
2024-03-06 16:29:02 +08:00
|
|
|
panic!("eth_close_socket is called before init");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-19 17:38:29 +08:00
|
|
|
pub fn for_each<F: FnMut(SocketHandle, usize)>(mut callback: F) {
|
2024-02-16 16:47:17 +08:00
|
|
|
unsafe {
|
2024-04-23 17:09:26 +08:00
|
|
|
if let Some(ref mut server_handle) = SERVER_HANDLE {
|
2024-03-06 16:29:02 +08:00
|
|
|
for i in 0..NUM_OF_SOCKETS {
|
2024-03-19 17:38:29 +08:00
|
|
|
callback(server_handle.socket_handles[i], i);
|
2024-03-06 16:29:02 +08:00
|
|
|
}
|
2024-04-23 17:09:26 +08:00
|
|
|
} else {
|
2024-02-16 16:47:17 +08:00
|
|
|
panic!("eth_close_socket is called before init");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-31 17:16:10 +08:00
|
|
|
/// Potentially wake up from `wfi()`, set the interrupt pending flag,
|
|
|
|
/// clear interrupt flags.
|
|
|
|
#[interrupt]
|
|
|
|
fn ETH() {
|
|
|
|
let interrupt_reason = stm32_eth::eth_interrupt_handler();
|
2024-04-29 17:57:45 +08:00
|
|
|
cortex_m::interrupt::free(|_| {
|
2024-03-20 14:25:35 +08:00
|
|
|
if interrupt_reason.rx {
|
|
|
|
eth_poll_iface();
|
|
|
|
}
|
2024-02-02 14:07:25 +08:00
|
|
|
});
|
2024-01-31 17:16:10 +08:00
|
|
|
debug!("Ethernet Interrupt{:?}", interrupt_reason);
|
2024-02-02 14:07:25 +08:00
|
|
|
}
|
2024-05-02 10:25:13 +08:00
|
|
|
|
|
|
|
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();
|
|
|
|
});
|
|
|
|
}
|