UDP works as well
All checks were successful
Rust/sat-rs/pipeline/head This commit looks good

This commit is contained in:
Robin Müller 2024-05-21 11:55:36 +02:00
parent 8dc7e7ac6c
commit 4ee22efb7b
Signed by: muellerr
GPG Key ID: A649FB78196E3849
3 changed files with 109 additions and 10 deletions

View File

@ -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",
]

View File

@ -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"

View File

@ -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();
}
}