Skip to content

Commit

Permalink
Update smoltcp to 0.9.x
Browse files Browse the repository at this point in the history
Everything works, despite smoltcp-rs/smoltcp#783

Git stm32-eth is needed for now (but presumably smoltcp-0.9 support will
be in its next release).

With smoltcp 0.8 it wasn't possible to write send_with correctly: we only
know how big the packet will be when f() returns, which is too late for
udp::Socket::send; we need the new udp::Socket::send_with.
  • Loading branch information
pdh11 committed Feb 24, 2024
1 parent 7d14919 commit 2e993bb
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 169 deletions.
4 changes: 2 additions & 2 deletions cross/stm32f746-nucleo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ harness = false
[dependencies]
cotton-ssdp = { path = "../../cotton-ssdp", default_features = false }
cotton-netif = { path = "../../cotton-netif", default_features = false }
smoltcp = { version = "0.8", features = [ "medium-ethernet", "proto-ipv4", "socket-udp", "socket-tcp", "defmt", "proto-dhcpv4", "socket-dhcpv4", "proto-igmp" ], default-features = false }
stm32-eth = { version = "0.4", features = ["defmt", "stm32f746", "smoltcp-phy"], default-features = false }
smoltcp = { version = "0.9", features = [ "medium-ethernet", "proto-ipv4", "socket-udp", "socket-tcp", "defmt", "proto-dhcpv4", "socket-dhcpv4", "proto-igmp"], default-features = false }
stm32-eth = { git = "https://github.com/stm32-rs/stm32-eth", rev = "a44422f", features = ["defmt", "stm32f746", "smoltcp-phy"], default-features = false }
ieee802_3_miim = "0.8"
stm32f7xx-hal = { version = "0.7.0" }
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"]}
Expand Down
96 changes: 41 additions & 55 deletions cross/stm32f746-nucleo/src/bin/dhcp-rtic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ use defmt_rtt as _; // global logger
use panic_probe as _;
use stm32f7xx_hal as _;

use smoltcp::{
iface::{self, SocketStorage},
wire,
};
use smoltcp::iface::{self, SocketStorage};

use stm32_eth::hal::rcc::Clocks;

Expand All @@ -18,10 +15,7 @@ use stm32_eth::hal::rcc::RccExt;
pub fn setup_clocks(rcc: stm32_eth::stm32::RCC) -> Clocks {
let rcc = rcc.constrain();

rcc.cfgr
.sysclk(100.MHz())
.hclk(100.MHz())
.freeze()
rcc.cfgr.sysclk(100.MHz()).hclk(100.MHz()).freeze()
}

use ieee802_3_miim::{
Expand Down Expand Up @@ -150,17 +144,18 @@ mod app {

use core::hash::Hasher;
use smoltcp::{
iface::{self, Interface, SocketHandle},
socket::{Dhcpv4Event, Dhcpv4Socket},
iface::{self, Interface, SocketHandle, SocketSet},
socket::dhcpv4,
wire::{EthernetAddress, IpCidr},
};

use super::NetworkStorage;

#[local]
struct Local {
interface:
Interface<'static, &'static mut EthernetDMA<'static, 'static>>,
device: EthernetDMA<'static, 'static>,
interface: Interface,
socket_set: SocketSet<'static>,
dhcp_handle: SocketHandle,
}

Expand All @@ -179,7 +174,6 @@ mod app {
rx_ring: [RxRingEntry; 2] = [RxRingEntry::new(),RxRingEntry::new()],
tx_ring: [TxRingEntry; 2] = [TxRingEntry::new(),TxRingEntry::new()],
storage: NetworkStorage = NetworkStorage::new(),
dma: core::mem::MaybeUninit<EthernetDMA<'static, 'static>> = core::mem::MaybeUninit::uninit(),
])]
fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
defmt::println!("Pre-init");
Expand Down Expand Up @@ -240,7 +234,7 @@ mod app {

defmt::println!("Configuring ethernet");

let Parts { dma, mac } = stm32_eth::new_with_mii(
let Parts { mut dma, mac } = stm32_eth::new_with_mii(
ethernet,
rx_ring,
tx_ring,
Expand All @@ -259,34 +253,27 @@ mod app {
)
.unwrap();

let dma = cx.local.dma.write(dma);

defmt::println!("Enabling interrupts");
dma.enable_interrupt();

defmt::println!("Setting up smoltcp");
let store = cx.local.storage;

let mut routes =
smoltcp::iface::Routes::new(&mut store.routes_cache[..]);
let mut routes = smoltcp::iface::Routes::new();
routes
.add_default_ipv4_route(smoltcp::wire::Ipv4Address::UNSPECIFIED)
.ok();

let neighbor_cache =
smoltcp::iface::NeighborCache::new(&mut store.neighbor_cache[..]);
let mut config = smoltcp::iface::Config::new();
// config.random_seed = mono.now();
config.hardware_addr =
Some(EthernetAddress::from_bytes(&mac_address).into());

let mut interface =
iface::InterfaceBuilder::new(dma, &mut store.sockets[..])
.hardware_addr(
EthernetAddress::from_bytes(&mac_address).into(),
)
.neighbor_cache(neighbor_cache)
.ip_addrs(&mut store.ip_addrs[..])
.routes(routes)
.finalize();
let mut interface = iface::Interface::new(config, &mut &mut dma);
let mut socket_set =
smoltcp::iface::SocketSet::new(&mut store.sockets[..]);

interface.poll(now_fn()).unwrap();
interface.poll(now_fn(), &mut &mut dma, &mut socket_set);

if let Ok(mut phy) = EthernetPhy::from_miim(mac, 0) {
defmt::println!(
Expand Down Expand Up @@ -319,45 +306,52 @@ mod app {
);
}

let dhcp_socket = Dhcpv4Socket::new();
let dhcp_handle = interface.add_socket(dhcp_socket);
let dhcp_socket = dhcpv4::Socket::new();
let dhcp_handle = socket_set.add(dhcp_socket);

interface.poll(now_fn()).unwrap();
interface.get_socket::<Dhcpv4Socket>(dhcp_handle).poll();
interface.poll(now_fn(), &mut &mut dma, &mut socket_set);
socket_set.get_mut::<dhcpv4::Socket>(dhcp_handle).poll();

(
Shared {},
Local {
device: dma,
interface,
socket_set,
dhcp_handle,
},
init::Monotonics(mono),
)
}

#[task(binds = ETH, local = [interface, dhcp_handle], priority = 2)]
#[task(binds = ETH, local = [device, interface, socket_set, dhcp_handle], priority = 2)]
fn eth_interrupt(cx: eth_interrupt::Context) {
let (iface, dhcp_handle) = (cx.local.interface, cx.local.dhcp_handle);
let (mut device, iface, socket_set, dhcp_handle) = (
cx.local.device,
cx.local.interface,
cx.local.socket_set,
cx.local.dhcp_handle,
);

let interrupt_reason = iface.device_mut().interrupt_handler();
let interrupt_reason =
EthernetDMA::<'static, 'static>::interrupt_handler();
defmt::trace!(
"Got an ethernet interrupt! Reason: {}",
interrupt_reason
);

iface.poll(now_fn()).ok();
iface.poll(now_fn(), &mut device, socket_set);

let event = iface.get_socket::<Dhcpv4Socket>(*dhcp_handle).poll();
let event = socket_set.get_mut::<dhcpv4::Socket>(*dhcp_handle).poll();
match event {
None => {}
Some(Dhcpv4Event::Configured(config)) => {
Some(dhcpv4::Event::Configured(config)) => {
defmt::println!("DHCP config acquired!");

defmt::println!("IP address: {}", config.address);

iface.update_ip_addrs(|addrs| {
let dest = addrs.iter_mut().next().unwrap();
*dest = IpCidr::Ipv4(config.address);
addrs.push(IpCidr::Ipv4(config.address)).unwrap();
});

if let Some(router) = config.router {
Expand All @@ -372,34 +366,26 @@ mod app {
defmt::println!("DNS server {}: {}", i, s);
}
}
Some(Dhcpv4Event::Deconfigured) => {
Some(dhcpv4::Event::Deconfigured) => {
defmt::println!("DHCP lost config!");
iface.update_ip_addrs(|addrs| {
addrs.clear();
});
}
}

iface.poll(now_fn()).ok();
iface.poll(now_fn(), &mut device, socket_set);
}
}

/// All storage required for networking
pub struct NetworkStorage {
pub ip_addrs: [wire::IpCidr; 1],
pub sockets: [iface::SocketStorage<'static>; 2],
pub neighbor_cache: [Option<(wire::IpAddress, iface::Neighbor)>; 8],
pub routes_cache: [Option<(wire::IpCidr, iface::Route)>; 8],
}

impl NetworkStorage {
const IP_INIT: wire::IpCidr = wire::IpCidr::Ipv4(wire::Ipv4Cidr::new(
wire::Ipv4Address::UNSPECIFIED,
24,
));

pub const fn new() -> Self {
NetworkStorage {
ip_addrs: [Self::IP_INIT],
neighbor_cache: [None; 8],
routes_cache: [None; 8],
sockets: [SocketStorage::EMPTY; 2],
}
}
Expand Down
Loading

0 comments on commit 2e993bb

Please sign in to comment.