This commit is contained in:
parent
8dc7e7ac6c
commit
4ee22efb7b
2
embedded-examples/stm32h7-rtic/Cargo.lock
generated
2
embedded-examples/stm32h7-rtic/Cargo.lock
generated
@ -315,6 +315,7 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
||||
dependencies = [
|
||||
"defmt",
|
||||
"hash32",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
@ -601,6 +602,7 @@ dependencies = [
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"cfg-if",
|
||||
"defmt",
|
||||
"heapless",
|
||||
"managed",
|
||||
]
|
||||
|
@ -25,7 +25,7 @@ stm32h7xx-hal = { version="0.16", features= ["stm32h743v", "ethernet"] }
|
||||
[dependencies.smoltcp]
|
||||
version = "0.11.0"
|
||||
default-features = false
|
||||
features = ["medium-ethernet", "proto-ipv4", "socket-raw", "socket-dhcpv4"]
|
||||
features = ["medium-ethernet", "proto-ipv4", "socket-raw", "socket-dhcpv4", "socket-udp", "defmt"]
|
||||
|
||||
[dependencies.rtic]
|
||||
version = "2"
|
||||
|
@ -4,15 +4,16 @@
|
||||
use rtic::app;
|
||||
use rtic_monotonics::systick::Systick;
|
||||
use rtic_monotonics::Monotonic;
|
||||
use satrs_stm32h7_nucleo_rtic as _; // global logger + panicking-behavior + memory layout
|
||||
use satrs_stm32h7_nucleo_rtic as _;
|
||||
use smoltcp::socket::{dhcpv4, udp}; // global logger + panicking-behavior + memory layout
|
||||
|
||||
use core::mem::MaybeUninit;
|
||||
use smoltcp::iface::{Config, Interface, SocketSet, SocketStorage};
|
||||
use smoltcp::time::Instant;
|
||||
use smoltcp::iface::{Config, Interface, SocketHandle, SocketSet, SocketStorage};
|
||||
use smoltcp::wire::{HardwareAddress, IpAddress, IpCidr};
|
||||
use stm32h7xx_hal::ethernet;
|
||||
|
||||
const DEFAULT_BLINK_FREQ_MS: u32 = 1000;
|
||||
const PORT: u16 = 7301;
|
||||
|
||||
/// Ethernet descriptor rings are a global singleton
|
||||
#[link_section = ".sram3.eth"]
|
||||
@ -26,6 +27,11 @@ pub struct NetStorageStatic<'a> {
|
||||
// initialised by the runtime
|
||||
static mut STORE: MaybeUninit<NetStorageStatic> = MaybeUninit::uninit();
|
||||
|
||||
static mut UDP_RX_META: [udp::PacketMetadata; 4] = [udp::PacketMetadata::EMPTY; 4];
|
||||
static mut UDP_RX: [u8; 2048] = [0; 2048];
|
||||
static mut UDP_TX_META: [udp::PacketMetadata; 4] = [udp::PacketMetadata::EMPTY; 4];
|
||||
static mut UDP_TX: [u8; 2048] = [0; 2048];
|
||||
|
||||
/// Locally administered MAC address
|
||||
const MAC_ADDRESS: [u8; 6] = [0x02, 0x00, 0x11, 0x22, 0x33, 0x44];
|
||||
|
||||
@ -33,6 +39,8 @@ pub struct Net<'a> {
|
||||
iface: Interface,
|
||||
ethdev: ethernet::EthernetDMA<4, 4>,
|
||||
sockets: SocketSet<'a>,
|
||||
dhcp_handle: SocketHandle,
|
||||
udp_handle: SocketHandle,
|
||||
}
|
||||
|
||||
impl<'a> Net<'a> {
|
||||
@ -40,21 +48,39 @@ impl<'a> Net<'a> {
|
||||
store: &'a mut NetStorageStatic<'a>,
|
||||
mut ethdev: ethernet::EthernetDMA<4, 4>,
|
||||
ethernet_addr: HardwareAddress,
|
||||
now: Instant,
|
||||
) -> Self {
|
||||
let config = Config::new(ethernet_addr);
|
||||
let mut iface = Interface::new(config, &mut ethdev, now);
|
||||
// Set IP address
|
||||
let mut iface = Interface::new(
|
||||
config,
|
||||
&mut ethdev,
|
||||
smoltcp::time::Instant::from_millis((Systick::now() - Systick::ZERO).to_millis()),
|
||||
);
|
||||
let udp_rx_buffer =
|
||||
smoltcp::socket::udp::PacketBuffer::new(unsafe { &mut UDP_RX_META[..] }, unsafe {
|
||||
&mut UDP_RX[..]
|
||||
});
|
||||
let udp_tx_buffer =
|
||||
smoltcp::socket::udp::PacketBuffer::new(unsafe { &mut UDP_TX_META[..] }, unsafe {
|
||||
&mut UDP_TX[..]
|
||||
});
|
||||
let udp_socket = smoltcp::socket::udp::Socket::new(udp_rx_buffer, udp_tx_buffer);
|
||||
|
||||
// Create sockets
|
||||
let dhcp_socket = dhcpv4::Socket::new();
|
||||
|
||||
iface.update_ip_addrs(|addrs| {
|
||||
let _ = addrs.push(IpCidr::new(IpAddress::v4(192, 168, 1, 99), 0));
|
||||
});
|
||||
|
||||
let sockets = SocketSet::new(&mut store.socket_storage[..]);
|
||||
|
||||
let mut sockets = SocketSet::new(&mut store.socket_storage[..]);
|
||||
let dhcp_handle = sockets.add(dhcp_socket);
|
||||
let udp_handle = sockets.add(udp_socket);
|
||||
Net::<'a> {
|
||||
iface,
|
||||
ethdev,
|
||||
sockets,
|
||||
dhcp_handle,
|
||||
udp_handle,
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,6 +93,73 @@ impl<'a> Net<'a> {
|
||||
self.iface
|
||||
.poll(timestamp, &mut self.ethdev, &mut self.sockets)
|
||||
}
|
||||
|
||||
pub fn poll_dhcp(&mut self) -> Option<dhcpv4::Event> {
|
||||
let opt_event = self
|
||||
.sockets
|
||||
.get_mut::<dhcpv4::Socket>(self.dhcp_handle)
|
||||
.poll();
|
||||
if let Some(event) = &opt_event {
|
||||
match event {
|
||||
dhcpv4::Event::Deconfigured => {
|
||||
defmt::info!("DHCP lost configuration");
|
||||
self.iface.update_ip_addrs(|addrs| addrs.clear());
|
||||
self.iface.routes_mut().remove_default_ipv4_route();
|
||||
}
|
||||
dhcpv4::Event::Configured(config) => {
|
||||
defmt::info!("DHCP configuration acquired");
|
||||
defmt::info!("IP address: {}", config.address);
|
||||
self.iface.update_ip_addrs(|addrs| {
|
||||
addrs.clear();
|
||||
addrs.push(IpCidr::Ipv4(config.address)).unwrap();
|
||||
});
|
||||
|
||||
if let Some(router) = config.router {
|
||||
defmt::debug!("Default gateway: {}", router);
|
||||
self.iface
|
||||
.routes_mut()
|
||||
.add_default_ipv4_route(router)
|
||||
.unwrap();
|
||||
} else {
|
||||
defmt::debug!("Default gateway: None");
|
||||
self.iface.routes_mut().remove_default_ipv4_route();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
opt_event
|
||||
}
|
||||
|
||||
pub fn poll_udp(&mut self) {
|
||||
let socket = self.sockets.get_mut::<udp::Socket>(self.udp_handle);
|
||||
if !socket.is_open() {
|
||||
if let Err(e) = socket.bind(PORT) {
|
||||
defmt::warn!("binding UDP socket failed");
|
||||
}
|
||||
}
|
||||
loop {
|
||||
match socket.recv() {
|
||||
Ok((data, client)) => {
|
||||
/*defmt::info!("UDP: rx {} bytes from {}", data.len(), endpoint);
|
||||
if let Ok(recv_str) = str::from_utf8(data) {
|
||||
defmt::info!("recv: {}", recv_str);
|
||||
}
|
||||
*/
|
||||
// TODO: Implement packet wiretapping.
|
||||
// TODO: Store last endpoint.
|
||||
// TODO: Send packet to PUS/CCSDS distributor via message queue.
|
||||
}
|
||||
Err(e) => match e {
|
||||
udp::RecvError::Exhausted => {
|
||||
break;
|
||||
}
|
||||
udp::RecvError::Truncated => {
|
||||
defmt::warn!("UDP packet was truncacted");
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[app(device = stm32h7xx_hal::stm32, peripherals = true)]
|
||||
@ -205,7 +298,7 @@ mod app {
|
||||
STORE.assume_init_mut()
|
||||
};
|
||||
|
||||
let net = Net::new(store, eth_dma, mac_addr.into(), Instant::ZERO);
|
||||
let net = Net::new(store, eth_dma, mac_addr.into());
|
||||
|
||||
eth_link_check::spawn().expect("eth link check failed");
|
||||
blink::spawn().expect("spawning blink task failed");
|
||||
@ -261,6 +354,10 @@ mod app {
|
||||
unsafe {
|
||||
ethernet::interrupt_handler();
|
||||
}
|
||||
// TODO: I am not fully sure whether we should do everything here. Mabye we should
|
||||
// offload this to a regular task?
|
||||
cx.local.net.poll();
|
||||
cx.local.net.poll_dhcp();
|
||||
cx.local.net.poll_udp();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user