diff options
43 files changed, 506 insertions, 609 deletions
| @@ -47,7 +47,7 @@ cargo batch \ | |||
| 47 | --- build --release --manifest-path embassy-sync/Cargo.toml --target thumbv6m-none-eabi --features defmt \ | 47 | --- build --release --manifest-path embassy-sync/Cargo.toml --target thumbv6m-none-eabi --features defmt \ |
| 48 | --- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features defmt,defmt-timestamp-uptime,generic-queue-8,mock-driver \ | 48 | --- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features defmt,defmt-timestamp-uptime,generic-queue-8,mock-driver \ |
| 49 | --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet,packet-trace \ | 49 | --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet,packet-trace \ |
| 50 | --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,igmp,medium-ethernet \ | 50 | --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,multicast,medium-ethernet \ |
| 51 | --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet \ | 51 | --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet \ |
| 52 | --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,dhcpv4-hostname \ | 52 | --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,dhcpv4-hostname \ |
| 53 | --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ | 53 | --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ |
| @@ -290,8 +290,9 @@ cargo batch \ | |||
| 290 | $BUILD_EXTRA | 290 | $BUILD_EXTRA |
| 291 | 291 | ||
| 292 | 292 | ||
| 293 | # temporarily disabled, bluepill board got bricked | 293 | # temporarily disabled, these boards are dead. |
| 294 | rm -rf out/tests/stm32f103c8 | 294 | rm -rf out/tests/stm32f103c8 |
| 295 | rm -rf out/tests/nrf52840-dk | ||
| 295 | 296 | ||
| 296 | rm out/tests/stm32wb55rg/wpan_mac | 297 | rm out/tests/stm32wb55rg/wpan_mac |
| 297 | rm out/tests/stm32wb55rg/wpan_ble | 298 | rm out/tests/stm32wb55rg/wpan_ble |
diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index 28bac485b..2e21b4231 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml | |||
| @@ -16,11 +16,11 @@ categories = [ | |||
| 16 | [package.metadata.embassy_docs] | 16 | [package.metadata.embassy_docs] |
| 17 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-v$VERSION/embassy-net/src/" | 17 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-v$VERSION/embassy-net/src/" |
| 18 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net/src/" | 18 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net/src/" |
| 19 | features = ["defmt", "tcp", "udp", "raw", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "medium-ieee802154", "igmp", "dhcpv4-hostname"] | 19 | features = ["defmt", "tcp", "udp", "raw", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "medium-ieee802154", "multicast", "dhcpv4-hostname"] |
| 20 | target = "thumbv7em-none-eabi" | 20 | target = "thumbv7em-none-eabi" |
| 21 | 21 | ||
| 22 | [package.metadata.docs.rs] | 22 | [package.metadata.docs.rs] |
| 23 | features = ["defmt", "tcp", "udp", "raw", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "medium-ieee802154", "igmp", "dhcpv4-hostname"] | 23 | features = ["defmt", "tcp", "udp", "raw", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "medium-ieee802154", "multicast", "dhcpv4-hostname"] |
| 24 | 24 | ||
| 25 | [features] | 25 | [features] |
| 26 | default = [] | 26 | default = [] |
| @@ -60,15 +60,15 @@ medium-ethernet = ["smoltcp/medium-ethernet"] | |||
| 60 | medium-ip = ["smoltcp/medium-ip"] | 60 | medium-ip = ["smoltcp/medium-ip"] |
| 61 | ## Enable the IEEE 802.15.4 medium | 61 | ## Enable the IEEE 802.15.4 medium |
| 62 | medium-ieee802154 = ["smoltcp/medium-ieee802154"] | 62 | medium-ieee802154 = ["smoltcp/medium-ieee802154"] |
| 63 | ## Enable IGMP support | 63 | ## Enable multicast support (for both ipv4 and/or ipv6 if enabled) |
| 64 | igmp = ["smoltcp/proto-igmp"] | 64 | multicast = ["smoltcp/multicast"] |
| 65 | 65 | ||
| 66 | [dependencies] | 66 | [dependencies] |
| 67 | 67 | ||
| 68 | defmt = { version = "0.3", optional = true } | 68 | defmt = { version = "0.3", optional = true } |
| 69 | log = { version = "0.4.14", optional = true } | 69 | log = { version = "0.4.14", optional = true } |
| 70 | 70 | ||
| 71 | smoltcp = { version = "0.11.0", default-features = false, features = [ | 71 | smoltcp = { git="https://github.com/smoltcp-rs/smoltcp", rev="dd43c8f189178b0ab3bda798ed8578b5b0a6f094", default-features = false, features = [ |
| 72 | "socket", | 72 | "socket", |
| 73 | "async", | 73 | "async", |
| 74 | ] } | 74 | ] } |
diff --git a/embassy-net/README.md b/embassy-net/README.md index 6b7d46934..1722ffc7b 100644 --- a/embassy-net/README.md +++ b/embassy-net/README.md | |||
| @@ -10,8 +10,9 @@ memory management designed to work well for embedded systems, aiming for a more | |||
| 10 | 10 | ||
| 11 | - IPv4, IPv6 | 11 | - IPv4, IPv6 |
| 12 | - Ethernet and bare-IP mediums. | 12 | - Ethernet and bare-IP mediums. |
| 13 | - TCP, UDP, DNS, DHCPv4, IGMPv4 | 13 | - TCP, UDP, DNS, DHCPv4 |
| 14 | - TCP sockets implement the `embedded-io` async traits. | 14 | - TCP sockets implement the `embedded-io` async traits. |
| 15 | - Multicast | ||
| 15 | 16 | ||
| 16 | See the [`smoltcp`](https://github.com/smoltcp-rs/smoltcp) README for a detailed list of implemented and | 17 | See the [`smoltcp`](https://github.com/smoltcp-rs/smoltcp) README for a detailed list of implemented and |
| 17 | unimplemented features of the network protocols. | 18 | unimplemented features of the network protocols. |
diff --git a/embassy-net/src/dns.rs b/embassy-net/src/dns.rs index 8ccfa4e4f..1fbaea4f0 100644 --- a/embassy-net/src/dns.rs +++ b/embassy-net/src/dns.rs | |||
| @@ -9,7 +9,7 @@ pub use smoltcp::socket::dns::{DnsQuery, Socket}; | |||
| 9 | pub(crate) use smoltcp::socket::dns::{GetQueryResultError, StartQueryError}; | 9 | pub(crate) use smoltcp::socket::dns::{GetQueryResultError, StartQueryError}; |
| 10 | pub use smoltcp::wire::{DnsQueryType, IpAddress}; | 10 | pub use smoltcp::wire::{DnsQueryType, IpAddress}; |
| 11 | 11 | ||
| 12 | use crate::{Driver, Stack}; | 12 | use crate::Stack; |
| 13 | 13 | ||
| 14 | /// Errors returned by DnsSocket. | 14 | /// Errors returned by DnsSocket. |
| 15 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | 15 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] |
| @@ -44,21 +44,15 @@ impl From<StartQueryError> for Error { | |||
| 44 | /// This exists only for compatibility with crates that use `embedded-nal-async`. | 44 | /// This exists only for compatibility with crates that use `embedded-nal-async`. |
| 45 | /// Prefer using [`Stack::dns_query`](crate::Stack::dns_query) directly if you're | 45 | /// Prefer using [`Stack::dns_query`](crate::Stack::dns_query) directly if you're |
| 46 | /// not using `embedded-nal-async`. | 46 | /// not using `embedded-nal-async`. |
| 47 | pub struct DnsSocket<'a, D> | 47 | pub struct DnsSocket<'a> { |
| 48 | where | 48 | stack: Stack<'a>, |
| 49 | D: Driver + 'static, | ||
| 50 | { | ||
| 51 | stack: &'a Stack<D>, | ||
| 52 | } | 49 | } |
| 53 | 50 | ||
| 54 | impl<'a, D> DnsSocket<'a, D> | 51 | impl<'a> DnsSocket<'a> { |
| 55 | where | ||
| 56 | D: Driver + 'static, | ||
| 57 | { | ||
| 58 | /// Create a new DNS socket using the provided stack. | 52 | /// Create a new DNS socket using the provided stack. |
| 59 | /// | 53 | /// |
| 60 | /// NOTE: If using DHCP, make sure it has reconfigured the stack to ensure the DNS servers are updated. | 54 | /// NOTE: If using DHCP, make sure it has reconfigured the stack to ensure the DNS servers are updated. |
| 61 | pub fn new(stack: &'a Stack<D>) -> Self { | 55 | pub fn new(stack: Stack<'a>) -> Self { |
| 62 | Self { stack } | 56 | Self { stack } |
| 63 | } | 57 | } |
| 64 | 58 | ||
| @@ -72,10 +66,7 @@ where | |||
| 72 | } | 66 | } |
| 73 | } | 67 | } |
| 74 | 68 | ||
| 75 | impl<'a, D> embedded_nal_async::Dns for DnsSocket<'a, D> | 69 | impl<'a> embedded_nal_async::Dns for DnsSocket<'a> { |
| 76 | where | ||
| 77 | D: Driver + 'static, | ||
| 78 | { | ||
| 79 | type Error = Error; | 70 | type Error = Error; |
| 80 | 71 | ||
| 81 | async fn get_host_by_name( | 72 | async fn get_host_by_name( |
| @@ -124,3 +115,7 @@ where | |||
| 124 | todo!() | 115 | todo!() |
| 125 | } | 116 | } |
| 126 | } | 117 | } |
| 118 | |||
| 119 | fn _assert_covariant<'a, 'b: 'a>(x: DnsSocket<'b>) -> DnsSocket<'a> { | ||
| 120 | x | ||
| 121 | } | ||
diff --git a/embassy-net/src/device.rs b/embassy-net/src/driver_util.rs index 3b1d3c47c..b2af1d499 100644 --- a/embassy-net/src/device.rs +++ b/embassy-net/src/driver_util.rs | |||
| @@ -74,7 +74,7 @@ where | |||
| 74 | { | 74 | { |
| 75 | fn consume<R, F>(self, f: F) -> R | 75 | fn consume<R, F>(self, f: F) -> R |
| 76 | where | 76 | where |
| 77 | F: FnOnce(&mut [u8]) -> R, | 77 | F: FnOnce(&[u8]) -> R, |
| 78 | { | 78 | { |
| 79 | self.0.consume(|buf| { | 79 | self.0.consume(|buf| { |
| 80 | #[cfg(feature = "packet-trace")] | 80 | #[cfg(feature = "packet-trace")] |
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 56321cec9..ef53fb905 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs | |||
| @@ -12,9 +12,9 @@ compile_error!("You must enable at least one of the following features: proto-ip | |||
| 12 | // This mod MUST go first, so that the others see its macros. | 12 | // This mod MUST go first, so that the others see its macros. |
| 13 | pub(crate) mod fmt; | 13 | pub(crate) mod fmt; |
| 14 | 14 | ||
| 15 | mod device; | ||
| 16 | #[cfg(feature = "dns")] | 15 | #[cfg(feature = "dns")] |
| 17 | pub mod dns; | 16 | pub mod dns; |
| 17 | mod driver_util; | ||
| 18 | #[cfg(feature = "raw")] | 18 | #[cfg(feature = "raw")] |
| 19 | pub mod raw; | 19 | pub mod raw; |
| 20 | #[cfg(feature = "tcp")] | 20 | #[cfg(feature = "tcp")] |
| @@ -25,6 +25,7 @@ pub mod udp; | |||
| 25 | 25 | ||
| 26 | use core::cell::RefCell; | 26 | use core::cell::RefCell; |
| 27 | use core::future::{poll_fn, Future}; | 27 | use core::future::{poll_fn, Future}; |
| 28 | use core::mem::MaybeUninit; | ||
| 28 | use core::pin::pin; | 29 | use core::pin::pin; |
| 29 | use core::task::{Context, Poll}; | 30 | use core::task::{Context, Poll}; |
| 30 | 31 | ||
| @@ -36,7 +37,7 @@ use embassy_time::{Instant, Timer}; | |||
| 36 | use heapless::Vec; | 37 | use heapless::Vec; |
| 37 | #[cfg(feature = "dns")] | 38 | #[cfg(feature = "dns")] |
| 38 | pub use smoltcp::config::DNS_MAX_SERVER_COUNT; | 39 | pub use smoltcp::config::DNS_MAX_SERVER_COUNT; |
| 39 | #[cfg(feature = "igmp")] | 40 | #[cfg(feature = "multicast")] |
| 40 | pub use smoltcp::iface::MulticastError; | 41 | pub use smoltcp::iface::MulticastError; |
| 41 | #[allow(unused_imports)] | 42 | #[allow(unused_imports)] |
| 42 | use smoltcp::iface::{Interface, SocketHandle, SocketSet, SocketStorage}; | 43 | use smoltcp::iface::{Interface, SocketHandle, SocketSet, SocketStorage}; |
| @@ -57,7 +58,7 @@ pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr}; | |||
| 57 | #[cfg(feature = "proto-ipv6")] | 58 | #[cfg(feature = "proto-ipv6")] |
| 58 | pub use smoltcp::wire::{Ipv6Address, Ipv6Cidr}; | 59 | pub use smoltcp::wire::{Ipv6Address, Ipv6Cidr}; |
| 59 | 60 | ||
| 60 | use crate::device::DriverAdapter; | 61 | use crate::driver_util::DriverAdapter; |
| 61 | use crate::time::{instant_from_smoltcp, instant_to_smoltcp}; | 62 | use crate::time::{instant_from_smoltcp, instant_to_smoltcp}; |
| 62 | 63 | ||
| 63 | const LOCAL_PORT_MIN: u16 = 1025; | 64 | const LOCAL_PORT_MIN: u16 = 1025; |
| @@ -69,33 +70,33 @@ const MAX_HOSTNAME_LEN: usize = 32; | |||
| 69 | 70 | ||
| 70 | /// Memory resources needed for a network stack. | 71 | /// Memory resources needed for a network stack. |
| 71 | pub struct StackResources<const SOCK: usize> { | 72 | pub struct StackResources<const SOCK: usize> { |
| 72 | sockets: [SocketStorage<'static>; SOCK], | 73 | sockets: MaybeUninit<[SocketStorage<'static>; SOCK]>, |
| 74 | inner: MaybeUninit<RefCell<Inner>>, | ||
| 73 | #[cfg(feature = "dns")] | 75 | #[cfg(feature = "dns")] |
| 74 | queries: [Option<dns::DnsQuery>; MAX_QUERIES], | 76 | queries: MaybeUninit<[Option<dns::DnsQuery>; MAX_QUERIES]>, |
| 75 | #[cfg(feature = "dhcpv4-hostname")] | 77 | #[cfg(feature = "dhcpv4-hostname")] |
| 76 | hostname: core::cell::UnsafeCell<HostnameResources>, | 78 | hostname: HostnameResources, |
| 77 | } | 79 | } |
| 78 | 80 | ||
| 79 | #[cfg(feature = "dhcpv4-hostname")] | 81 | #[cfg(feature = "dhcpv4-hostname")] |
| 80 | struct HostnameResources { | 82 | struct HostnameResources { |
| 81 | option: smoltcp::wire::DhcpOption<'static>, | 83 | option: MaybeUninit<smoltcp::wire::DhcpOption<'static>>, |
| 82 | data: [u8; MAX_HOSTNAME_LEN], | 84 | data: MaybeUninit<[u8; MAX_HOSTNAME_LEN]>, |
| 83 | } | 85 | } |
| 84 | 86 | ||
| 85 | impl<const SOCK: usize> StackResources<SOCK> { | 87 | impl<const SOCK: usize> StackResources<SOCK> { |
| 86 | /// Create a new set of stack resources. | 88 | /// Create a new set of stack resources. |
| 87 | pub const fn new() -> Self { | 89 | pub const fn new() -> Self { |
| 88 | #[cfg(feature = "dns")] | ||
| 89 | const INIT: Option<dns::DnsQuery> = None; | ||
| 90 | Self { | 90 | Self { |
| 91 | sockets: [SocketStorage::EMPTY; SOCK], | 91 | sockets: MaybeUninit::uninit(), |
| 92 | inner: MaybeUninit::uninit(), | ||
| 92 | #[cfg(feature = "dns")] | 93 | #[cfg(feature = "dns")] |
| 93 | queries: [INIT; MAX_QUERIES], | 94 | queries: MaybeUninit::uninit(), |
| 94 | #[cfg(feature = "dhcpv4-hostname")] | 95 | #[cfg(feature = "dhcpv4-hostname")] |
| 95 | hostname: core::cell::UnsafeCell::new(HostnameResources { | 96 | hostname: HostnameResources { |
| 96 | option: smoltcp::wire::DhcpOption { kind: 0, data: &[] }, | 97 | option: MaybeUninit::uninit(), |
| 97 | data: [0; MAX_HOSTNAME_LEN], | 98 | data: MaybeUninit::uninit(), |
| 98 | }), | 99 | }, |
| 99 | } | 100 | } |
| 100 | } | 101 | } |
| 101 | } | 102 | } |
| @@ -239,16 +240,29 @@ pub enum ConfigV6 { | |||
| 239 | Static(StaticConfigV6), | 240 | Static(StaticConfigV6), |
| 240 | } | 241 | } |
| 241 | 242 | ||
| 242 | /// A network stack. | 243 | /// Network stack runner. |
| 244 | /// | ||
| 245 | /// You must call [`Runner::run()`] in a background task for the network stack to work. | ||
| 246 | pub struct Runner<'d, D: Driver> { | ||
| 247 | driver: D, | ||
| 248 | stack: Stack<'d>, | ||
| 249 | } | ||
| 250 | |||
| 251 | /// Network stack handle | ||
| 243 | /// | 252 | /// |
| 244 | /// This is the main entry point for the network stack. | 253 | /// Use this to create sockets. It's `Copy`, so you can pass |
| 245 | pub struct Stack<D: Driver> { | 254 | /// it by value instead of by reference. |
| 246 | pub(crate) socket: RefCell<SocketStack>, | 255 | #[derive(Copy, Clone)] |
| 247 | inner: RefCell<Inner<D>>, | 256 | pub struct Stack<'d> { |
| 257 | inner: &'d RefCell<Inner>, | ||
| 248 | } | 258 | } |
| 249 | 259 | ||
| 250 | struct Inner<D: Driver> { | 260 | pub(crate) struct Inner { |
| 251 | device: D, | 261 | pub(crate) sockets: SocketSet<'static>, // Lifetime type-erased. |
| 262 | pub(crate) iface: Interface, | ||
| 263 | pub(crate) waker: WakerRegistration, | ||
| 264 | hardware_address: HardwareAddress, | ||
| 265 | next_local_port: u16, | ||
| 252 | link_up: bool, | 266 | link_up: bool, |
| 253 | #[cfg(feature = "proto-ipv4")] | 267 | #[cfg(feature = "proto-ipv4")] |
| 254 | static_v4: Option<StaticConfigV4>, | 268 | static_v4: Option<StaticConfigV4>, |
| @@ -262,14 +276,83 @@ struct Inner<D: Driver> { | |||
| 262 | #[cfg(feature = "dns")] | 276 | #[cfg(feature = "dns")] |
| 263 | dns_waker: WakerRegistration, | 277 | dns_waker: WakerRegistration, |
| 264 | #[cfg(feature = "dhcpv4-hostname")] | 278 | #[cfg(feature = "dhcpv4-hostname")] |
| 265 | hostname: &'static mut core::cell::UnsafeCell<HostnameResources>, | 279 | hostname: *mut HostnameResources, |
| 266 | } | 280 | } |
| 267 | 281 | ||
| 268 | pub(crate) struct SocketStack { | 282 | fn _assert_covariant<'a, 'b: 'a>(x: Stack<'b>) -> Stack<'a> { |
| 269 | pub(crate) sockets: SocketSet<'static>, | 283 | x |
| 270 | pub(crate) iface: Interface, | 284 | } |
| 271 | pub(crate) waker: WakerRegistration, | 285 | |
| 272 | next_local_port: u16, | 286 | /// Create a new network stack. |
| 287 | pub fn new<'d, D: Driver, const SOCK: usize>( | ||
| 288 | mut driver: D, | ||
| 289 | config: Config, | ||
| 290 | resources: &'d mut StackResources<SOCK>, | ||
| 291 | random_seed: u64, | ||
| 292 | ) -> (Stack<'d>, Runner<'d, D>) { | ||
| 293 | let (hardware_address, medium) = to_smoltcp_hardware_address(driver.hardware_address()); | ||
| 294 | let mut iface_cfg = smoltcp::iface::Config::new(hardware_address); | ||
| 295 | iface_cfg.random_seed = random_seed; | ||
| 296 | |||
| 297 | let iface = Interface::new( | ||
| 298 | iface_cfg, | ||
| 299 | &mut DriverAdapter { | ||
| 300 | inner: &mut driver, | ||
| 301 | cx: None, | ||
| 302 | medium, | ||
| 303 | }, | ||
| 304 | instant_to_smoltcp(Instant::now()), | ||
| 305 | ); | ||
| 306 | |||
| 307 | unsafe fn transmute_slice<T>(x: &mut [T]) -> &'static mut [T] { | ||
| 308 | core::mem::transmute(x) | ||
| 309 | } | ||
| 310 | |||
| 311 | let sockets = resources.sockets.write([SocketStorage::EMPTY; SOCK]); | ||
| 312 | #[allow(unused_mut)] | ||
| 313 | let mut sockets: SocketSet<'static> = SocketSet::new(unsafe { transmute_slice(sockets) }); | ||
| 314 | |||
| 315 | let next_local_port = (random_seed % (LOCAL_PORT_MAX - LOCAL_PORT_MIN) as u64) as u16 + LOCAL_PORT_MIN; | ||
| 316 | |||
| 317 | #[cfg(feature = "dns")] | ||
| 318 | let dns_socket = sockets.add(dns::Socket::new( | ||
| 319 | &[], | ||
| 320 | managed::ManagedSlice::Borrowed(unsafe { | ||
| 321 | transmute_slice(resources.queries.write([const { None }; MAX_QUERIES])) | ||
| 322 | }), | ||
| 323 | )); | ||
| 324 | |||
| 325 | let mut inner = Inner { | ||
| 326 | sockets, | ||
| 327 | iface, | ||
| 328 | waker: WakerRegistration::new(), | ||
| 329 | next_local_port, | ||
| 330 | hardware_address, | ||
| 331 | link_up: false, | ||
| 332 | #[cfg(feature = "proto-ipv4")] | ||
| 333 | static_v4: None, | ||
| 334 | #[cfg(feature = "proto-ipv6")] | ||
| 335 | static_v6: None, | ||
| 336 | #[cfg(feature = "dhcpv4")] | ||
| 337 | dhcp_socket: None, | ||
| 338 | config_waker: WakerRegistration::new(), | ||
| 339 | #[cfg(feature = "dns")] | ||
| 340 | dns_socket, | ||
| 341 | #[cfg(feature = "dns")] | ||
| 342 | dns_waker: WakerRegistration::new(), | ||
| 343 | #[cfg(feature = "dhcpv4-hostname")] | ||
| 344 | hostname: &mut resources.hostname, | ||
| 345 | }; | ||
| 346 | |||
| 347 | #[cfg(feature = "proto-ipv4")] | ||
| 348 | inner.set_config_v4(config.ipv4); | ||
| 349 | #[cfg(feature = "proto-ipv6")] | ||
| 350 | inner.set_config_v6(config.ipv6); | ||
| 351 | inner.apply_static_config(); | ||
| 352 | |||
| 353 | let inner = &*resources.inner.write(RefCell::new(inner)); | ||
| 354 | let stack = Stack { inner }; | ||
| 355 | (stack, Runner { driver, stack }) | ||
| 273 | } | 356 | } |
| 274 | 357 | ||
| 275 | fn to_smoltcp_hardware_address(addr: driver::HardwareAddress) -> (HardwareAddress, Medium) { | 358 | fn to_smoltcp_hardware_address(addr: driver::HardwareAddress) -> (HardwareAddress, Medium) { |
| @@ -292,89 +375,23 @@ fn to_smoltcp_hardware_address(addr: driver::HardwareAddress) -> (HardwareAddres | |||
| 292 | } | 375 | } |
| 293 | } | 376 | } |
| 294 | 377 | ||
| 295 | impl<D: Driver> Stack<D> { | 378 | impl<'d> Stack<'d> { |
| 296 | /// Create a new network stack. | 379 | fn with<R>(&self, f: impl FnOnce(&Inner) -> R) -> R { |
| 297 | pub fn new<const SOCK: usize>( | 380 | f(&*self.inner.borrow()) |
| 298 | mut device: D, | ||
| 299 | config: Config, | ||
| 300 | resources: &'static mut StackResources<SOCK>, | ||
| 301 | random_seed: u64, | ||
| 302 | ) -> Self { | ||
| 303 | let (hardware_addr, medium) = to_smoltcp_hardware_address(device.hardware_address()); | ||
| 304 | let mut iface_cfg = smoltcp::iface::Config::new(hardware_addr); | ||
| 305 | iface_cfg.random_seed = random_seed; | ||
| 306 | |||
| 307 | let iface = Interface::new( | ||
| 308 | iface_cfg, | ||
| 309 | &mut DriverAdapter { | ||
| 310 | inner: &mut device, | ||
| 311 | cx: None, | ||
| 312 | medium, | ||
| 313 | }, | ||
| 314 | instant_to_smoltcp(Instant::now()), | ||
| 315 | ); | ||
| 316 | |||
| 317 | let sockets = SocketSet::new(&mut resources.sockets[..]); | ||
| 318 | |||
| 319 | let next_local_port = (random_seed % (LOCAL_PORT_MAX - LOCAL_PORT_MIN) as u64) as u16 + LOCAL_PORT_MIN; | ||
| 320 | |||
| 321 | #[cfg_attr(feature = "medium-ieee802154", allow(unused_mut))] | ||
| 322 | let mut socket = SocketStack { | ||
| 323 | sockets, | ||
| 324 | iface, | ||
| 325 | waker: WakerRegistration::new(), | ||
| 326 | next_local_port, | ||
| 327 | }; | ||
| 328 | |||
| 329 | let mut inner = Inner { | ||
| 330 | device, | ||
| 331 | link_up: false, | ||
| 332 | #[cfg(feature = "proto-ipv4")] | ||
| 333 | static_v4: None, | ||
| 334 | #[cfg(feature = "proto-ipv6")] | ||
| 335 | static_v6: None, | ||
| 336 | #[cfg(feature = "dhcpv4")] | ||
| 337 | dhcp_socket: None, | ||
| 338 | config_waker: WakerRegistration::new(), | ||
| 339 | #[cfg(feature = "dns")] | ||
| 340 | dns_socket: socket.sockets.add(dns::Socket::new( | ||
| 341 | &[], | ||
| 342 | managed::ManagedSlice::Borrowed(&mut resources.queries), | ||
| 343 | )), | ||
| 344 | #[cfg(feature = "dns")] | ||
| 345 | dns_waker: WakerRegistration::new(), | ||
| 346 | #[cfg(feature = "dhcpv4-hostname")] | ||
| 347 | hostname: &mut resources.hostname, | ||
| 348 | }; | ||
| 349 | |||
| 350 | #[cfg(feature = "proto-ipv4")] | ||
| 351 | inner.set_config_v4(&mut socket, config.ipv4); | ||
| 352 | #[cfg(feature = "proto-ipv6")] | ||
| 353 | inner.set_config_v6(&mut socket, config.ipv6); | ||
| 354 | inner.apply_static_config(&mut socket); | ||
| 355 | |||
| 356 | Self { | ||
| 357 | socket: RefCell::new(socket), | ||
| 358 | inner: RefCell::new(inner), | ||
| 359 | } | ||
| 360 | } | ||
| 361 | |||
| 362 | fn with<R>(&self, f: impl FnOnce(&SocketStack, &Inner<D>) -> R) -> R { | ||
| 363 | f(&*self.socket.borrow(), &*self.inner.borrow()) | ||
| 364 | } | 381 | } |
| 365 | 382 | ||
| 366 | fn with_mut<R>(&self, f: impl FnOnce(&mut SocketStack, &mut Inner<D>) -> R) -> R { | 383 | fn with_mut<R>(&self, f: impl FnOnce(&mut Inner) -> R) -> R { |
| 367 | f(&mut *self.socket.borrow_mut(), &mut *self.inner.borrow_mut()) | 384 | f(&mut *self.inner.borrow_mut()) |
| 368 | } | 385 | } |
| 369 | 386 | ||
| 370 | /// Get the hardware address of the network interface. | 387 | /// Get the hardware address of the network interface. |
| 371 | pub fn hardware_address(&self) -> HardwareAddress { | 388 | pub fn hardware_address(&self) -> HardwareAddress { |
| 372 | self.with(|_s, i| to_smoltcp_hardware_address(i.device.hardware_address()).0) | 389 | self.with(|i| i.hardware_address) |
| 373 | } | 390 | } |
| 374 | 391 | ||
| 375 | /// Get whether the link is up. | 392 | /// Get whether the link is up. |
| 376 | pub fn is_link_up(&self) -> bool { | 393 | pub fn is_link_up(&self) -> bool { |
| 377 | self.with(|_s, i| i.link_up) | 394 | self.with(|i| i.link_up) |
| 378 | } | 395 | } |
| 379 | 396 | ||
| 380 | /// Get whether the network stack has a valid IP configuration. | 397 | /// Get whether the network stack has a valid IP configuration. |
| @@ -420,15 +437,14 @@ impl<D: Driver> Stack<D> { | |||
| 420 | /// // provisioning space for 3 sockets here: one for DHCP, one for DNS, and one for your code (e.g. TCP). | 437 | /// // provisioning space for 3 sockets here: one for DHCP, one for DNS, and one for your code (e.g. TCP). |
| 421 | /// // If you use more sockets you must increase this. If you don't enable DHCP or DNS you can decrease it. | 438 | /// // If you use more sockets you must increase this. If you don't enable DHCP or DNS you can decrease it. |
| 422 | /// static RESOURCES: StaticCell<embassy_net::StackResources<3>> = StaticCell::new(); | 439 | /// static RESOURCES: StaticCell<embassy_net::StackResources<3>> = StaticCell::new(); |
| 423 | /// static STACK: StaticCell<embassy_net::Stack> = StaticCell::new(); | 440 | /// let (stack, runner) = embassy_net::new( |
| 424 | /// let stack = &*STACK.init(embassy_net::Stack::new( | 441 | /// driver, |
| 425 | /// device, | ||
| 426 | /// config, | 442 | /// config, |
| 427 | /// RESOURCES.init(embassy_net::StackResources::new()), | 443 | /// RESOURCES.init(embassy_net::StackResources::new()), |
| 428 | /// seed | 444 | /// seed |
| 429 | /// )); | 445 | /// ); |
| 430 | /// // Launch network task that runs `stack.run().await` | 446 | /// // Launch network task that runs `runner.run().await` |
| 431 | /// spawner.spawn(net_task(stack)).unwrap(); | 447 | /// spawner.spawn(net_task(runner)).unwrap(); |
| 432 | /// // Wait for DHCP config | 448 | /// // Wait for DHCP config |
| 433 | /// stack.wait_config_up().await; | 449 | /// stack.wait_config_up().await; |
| 434 | /// // use the network stack | 450 | /// // use the network stack |
| @@ -448,7 +464,7 @@ impl<D: Driver> Stack<D> { | |||
| 448 | // when a config is applied (static or DHCP). | 464 | // when a config is applied (static or DHCP). |
| 449 | trace!("Waiting for config up"); | 465 | trace!("Waiting for config up"); |
| 450 | 466 | ||
| 451 | self.with_mut(|_, i| { | 467 | self.with_mut(|i| { |
| 452 | i.config_waker.register(cx.waker()); | 468 | i.config_waker.register(cx.waker()); |
| 453 | }); | 469 | }); |
| 454 | 470 | ||
| @@ -464,45 +480,33 @@ impl<D: Driver> Stack<D> { | |||
| 464 | /// acquire an IP address, or Some if it has. | 480 | /// acquire an IP address, or Some if it has. |
| 465 | #[cfg(feature = "proto-ipv4")] | 481 | #[cfg(feature = "proto-ipv4")] |
| 466 | pub fn config_v4(&self) -> Option<StaticConfigV4> { | 482 | pub fn config_v4(&self) -> Option<StaticConfigV4> { |
| 467 | self.with(|_, i| i.static_v4.clone()) | 483 | self.with(|i| i.static_v4.clone()) |
| 468 | } | 484 | } |
| 469 | 485 | ||
| 470 | /// Get the current IPv6 configuration. | 486 | /// Get the current IPv6 configuration. |
| 471 | #[cfg(feature = "proto-ipv6")] | 487 | #[cfg(feature = "proto-ipv6")] |
| 472 | pub fn config_v6(&self) -> Option<StaticConfigV6> { | 488 | pub fn config_v6(&self) -> Option<StaticConfigV6> { |
| 473 | self.with(|_, i| i.static_v6.clone()) | 489 | self.with(|i| i.static_v6.clone()) |
| 474 | } | 490 | } |
| 475 | 491 | ||
| 476 | /// Set the IPv4 configuration. | 492 | /// Set the IPv4 configuration. |
| 477 | #[cfg(feature = "proto-ipv4")] | 493 | #[cfg(feature = "proto-ipv4")] |
| 478 | pub fn set_config_v4(&self, config: ConfigV4) { | 494 | pub fn set_config_v4(&self, config: ConfigV4) { |
| 479 | self.with_mut(|s, i| { | 495 | self.with_mut(|i| { |
| 480 | i.set_config_v4(s, config); | 496 | i.set_config_v4(config); |
| 481 | i.apply_static_config(s); | 497 | i.apply_static_config(); |
| 482 | }) | 498 | }) |
| 483 | } | 499 | } |
| 484 | 500 | ||
| 485 | /// Set the IPv6 configuration. | 501 | /// Set the IPv6 configuration. |
| 486 | #[cfg(feature = "proto-ipv6")] | 502 | #[cfg(feature = "proto-ipv6")] |
| 487 | pub fn set_config_v6(&self, config: ConfigV6) { | 503 | pub fn set_config_v6(&self, config: ConfigV6) { |
| 488 | self.with_mut(|s, i| { | 504 | self.with_mut(|i| { |
| 489 | i.set_config_v6(s, config); | 505 | i.set_config_v6(config); |
| 490 | i.apply_static_config(s); | 506 | i.apply_static_config(); |
| 491 | }) | 507 | }) |
| 492 | } | 508 | } |
| 493 | 509 | ||
| 494 | /// Run the network stack. | ||
| 495 | /// | ||
| 496 | /// You must call this in a background task, to process network events. | ||
| 497 | pub async fn run(&self) -> ! { | ||
| 498 | poll_fn(|cx| { | ||
| 499 | self.with_mut(|s, i| i.poll(cx, s)); | ||
| 500 | Poll::<()>::Pending | ||
| 501 | }) | ||
| 502 | .await; | ||
| 503 | unreachable!() | ||
| 504 | } | ||
| 505 | |||
| 506 | /// Make a query for a given name and return the corresponding IP addresses. | 510 | /// Make a query for a given name and return the corresponding IP addresses. |
| 507 | #[cfg(feature = "dns")] | 511 | #[cfg(feature = "dns")] |
| 508 | pub async fn dns_query( | 512 | pub async fn dns_query( |
| @@ -528,11 +532,11 @@ impl<D: Driver> Stack<D> { | |||
| 528 | } | 532 | } |
| 529 | 533 | ||
| 530 | let query = poll_fn(|cx| { | 534 | let query = poll_fn(|cx| { |
| 531 | self.with_mut(|s, i| { | 535 | self.with_mut(|i| { |
| 532 | let socket = s.sockets.get_mut::<dns::Socket>(i.dns_socket); | 536 | let socket = i.sockets.get_mut::<dns::Socket>(i.dns_socket); |
| 533 | match socket.start_query(s.iface.context(), name, qtype) { | 537 | match socket.start_query(i.iface.context(), name, qtype) { |
| 534 | Ok(handle) => { | 538 | Ok(handle) => { |
| 535 | s.waker.wake(); | 539 | i.waker.wake(); |
| 536 | Poll::Ready(Ok(handle)) | 540 | Poll::Ready(Ok(handle)) |
| 537 | } | 541 | } |
| 538 | Err(dns::StartQueryError::NoFreeSlot) => { | 542 | Err(dns::StartQueryError::NoFreeSlot) => { |
| @@ -569,17 +573,17 @@ impl<D: Driver> Stack<D> { | |||
| 569 | } | 573 | } |
| 570 | 574 | ||
| 571 | let drop = OnDrop::new(|| { | 575 | let drop = OnDrop::new(|| { |
| 572 | self.with_mut(|s, i| { | 576 | self.with_mut(|i| { |
| 573 | let socket = s.sockets.get_mut::<dns::Socket>(i.dns_socket); | 577 | let socket = i.sockets.get_mut::<dns::Socket>(i.dns_socket); |
| 574 | socket.cancel_query(query); | 578 | socket.cancel_query(query); |
| 575 | s.waker.wake(); | 579 | i.waker.wake(); |
| 576 | i.dns_waker.wake(); | 580 | i.dns_waker.wake(); |
| 577 | }) | 581 | }) |
| 578 | }); | 582 | }); |
| 579 | 583 | ||
| 580 | let res = poll_fn(|cx| { | 584 | let res = poll_fn(|cx| { |
| 581 | self.with_mut(|s, i| { | 585 | self.with_mut(|i| { |
| 582 | let socket = s.sockets.get_mut::<dns::Socket>(i.dns_socket); | 586 | let socket = i.sockets.get_mut::<dns::Socket>(i.dns_socket); |
| 583 | match socket.get_query_result(query) { | 587 | match socket.get_query_result(query) { |
| 584 | Ok(addrs) => { | 588 | Ok(addrs) => { |
| 585 | i.dns_waker.wake(); | 589 | i.dns_waker.wake(); |
| @@ -604,104 +608,34 @@ impl<D: Driver> Stack<D> { | |||
| 604 | } | 608 | } |
| 605 | } | 609 | } |
| 606 | 610 | ||
| 607 | #[cfg(feature = "igmp")] | 611 | #[cfg(feature = "multicast")] |
| 608 | impl<D: Driver> Stack<D> { | 612 | impl<'d> Stack<'d> { |
| 609 | /// Join a multicast group. | 613 | /// Join a multicast group. |
| 610 | pub async fn join_multicast_group<T>(&self, addr: T) -> Result<bool, MulticastError> | 614 | pub fn join_multicast_group(&self, addr: impl Into<IpAddress>) -> Result<(), MulticastError> { |
| 611 | where | 615 | self.with_mut(|i| i.iface.join_multicast_group(addr)) |
| 612 | T: Into<IpAddress>, | ||
| 613 | { | ||
| 614 | let addr = addr.into(); | ||
| 615 | |||
| 616 | poll_fn(move |cx| self.poll_join_multicast_group(addr, cx)).await | ||
| 617 | } | ||
| 618 | |||
| 619 | /// Join a multicast group. | ||
| 620 | /// | ||
| 621 | /// When the send queue is full, this method will return `Poll::Pending` | ||
| 622 | /// and register the current task to be notified when the queue has space available. | ||
| 623 | pub fn poll_join_multicast_group<T>(&self, addr: T, cx: &mut Context<'_>) -> Poll<Result<bool, MulticastError>> | ||
| 624 | where | ||
| 625 | T: Into<IpAddress>, | ||
| 626 | { | ||
| 627 | let addr = addr.into(); | ||
| 628 | |||
| 629 | self.with_mut(|s, i| { | ||
| 630 | let (_hardware_addr, medium) = to_smoltcp_hardware_address(i.device.hardware_address()); | ||
| 631 | let mut smoldev = DriverAdapter { | ||
| 632 | cx: Some(cx), | ||
| 633 | inner: &mut i.device, | ||
| 634 | medium, | ||
| 635 | }; | ||
| 636 | |||
| 637 | match s | ||
| 638 | .iface | ||
| 639 | .join_multicast_group(&mut smoldev, addr, instant_to_smoltcp(Instant::now())) | ||
| 640 | { | ||
| 641 | Ok(announce_sent) => Poll::Ready(Ok(announce_sent)), | ||
| 642 | Err(MulticastError::Exhausted) => Poll::Pending, | ||
| 643 | Err(other) => Poll::Ready(Err(other)), | ||
| 644 | } | ||
| 645 | }) | ||
| 646 | } | 616 | } |
| 647 | 617 | ||
| 648 | /// Leave a multicast group. | 618 | /// Leave a multicast group. |
| 649 | pub async fn leave_multicast_group<T>(&self, addr: T) -> Result<bool, MulticastError> | 619 | pub fn leave_multicast_group(&self, addr: impl Into<IpAddress>) -> Result<(), MulticastError> { |
| 650 | where | 620 | self.with_mut(|i| i.iface.leave_multicast_group(addr)) |
| 651 | T: Into<IpAddress>, | ||
| 652 | { | ||
| 653 | let addr = addr.into(); | ||
| 654 | |||
| 655 | poll_fn(move |cx| self.poll_leave_multicast_group(addr, cx)).await | ||
| 656 | } | ||
| 657 | |||
| 658 | /// Leave a multicast group. | ||
| 659 | /// | ||
| 660 | /// When the send queue is full, this method will return `Poll::Pending` | ||
| 661 | /// and register the current task to be notified when the queue has space available. | ||
| 662 | pub fn poll_leave_multicast_group<T>(&self, addr: T, cx: &mut Context<'_>) -> Poll<Result<bool, MulticastError>> | ||
| 663 | where | ||
| 664 | T: Into<IpAddress>, | ||
| 665 | { | ||
| 666 | let addr = addr.into(); | ||
| 667 | |||
| 668 | self.with_mut(|s, i| { | ||
| 669 | let (_hardware_addr, medium) = to_smoltcp_hardware_address(i.device.hardware_address()); | ||
| 670 | let mut smoldev = DriverAdapter { | ||
| 671 | cx: Some(cx), | ||
| 672 | inner: &mut i.device, | ||
| 673 | medium, | ||
| 674 | }; | ||
| 675 | |||
| 676 | match s | ||
| 677 | .iface | ||
| 678 | .leave_multicast_group(&mut smoldev, addr, instant_to_smoltcp(Instant::now())) | ||
| 679 | { | ||
| 680 | Ok(leave_sent) => Poll::Ready(Ok(leave_sent)), | ||
| 681 | Err(MulticastError::Exhausted) => Poll::Pending, | ||
| 682 | Err(other) => Poll::Ready(Err(other)), | ||
| 683 | } | ||
| 684 | }) | ||
| 685 | } | 621 | } |
| 686 | 622 | ||
| 687 | /// Get whether the network stack has joined the given multicast group. | 623 | /// Get whether the network stack has joined the given multicast group. |
| 688 | pub fn has_multicast_group<T: Into<IpAddress>>(&self, addr: T) -> bool { | 624 | pub fn has_multicast_group(&self, addr: impl Into<IpAddress>) -> bool { |
| 689 | self.socket.borrow().iface.has_multicast_group(addr) | 625 | self.with(|i| i.iface.has_multicast_group(addr)) |
| 690 | } | 626 | } |
| 691 | } | 627 | } |
| 692 | 628 | ||
| 693 | impl SocketStack { | 629 | impl Inner { |
| 694 | #[allow(clippy::absurd_extreme_comparisons, dead_code)] | 630 | #[allow(clippy::absurd_extreme_comparisons, dead_code)] |
| 695 | pub fn get_local_port(&mut self) -> u16 { | 631 | pub fn get_local_port(&mut self) -> u16 { |
| 696 | let res = self.next_local_port; | 632 | let res = self.next_local_port; |
| 697 | self.next_local_port = if res >= LOCAL_PORT_MAX { LOCAL_PORT_MIN } else { res + 1 }; | 633 | self.next_local_port = if res >= LOCAL_PORT_MAX { LOCAL_PORT_MIN } else { res + 1 }; |
| 698 | res | 634 | res |
| 699 | } | 635 | } |
| 700 | } | ||
| 701 | 636 | ||
| 702 | impl<D: Driver> Inner<D> { | ||
| 703 | #[cfg(feature = "proto-ipv4")] | 637 | #[cfg(feature = "proto-ipv4")] |
| 704 | pub fn set_config_v4(&mut self, _s: &mut SocketStack, config: ConfigV4) { | 638 | pub fn set_config_v4(&mut self, config: ConfigV4) { |
| 705 | // Handle static config. | 639 | // Handle static config. |
| 706 | self.static_v4 = match config.clone() { | 640 | self.static_v4 = match config.clone() { |
| 707 | ConfigV4::None => None, | 641 | ConfigV4::None => None, |
| @@ -717,12 +651,12 @@ impl<D: Driver> Inner<D> { | |||
| 717 | // Create the socket if it doesn't exist. | 651 | // Create the socket if it doesn't exist. |
| 718 | if self.dhcp_socket.is_none() { | 652 | if self.dhcp_socket.is_none() { |
| 719 | let socket = smoltcp::socket::dhcpv4::Socket::new(); | 653 | let socket = smoltcp::socket::dhcpv4::Socket::new(); |
| 720 | let handle = _s.sockets.add(socket); | 654 | let handle = self.sockets.add(socket); |
| 721 | self.dhcp_socket = Some(handle); | 655 | self.dhcp_socket = Some(handle); |
| 722 | } | 656 | } |
| 723 | 657 | ||
| 724 | // Configure it | 658 | // Configure it |
| 725 | let socket = _s.sockets.get_mut::<dhcpv4::Socket>(unwrap!(self.dhcp_socket)); | 659 | let socket = self.sockets.get_mut::<dhcpv4::Socket>(unwrap!(self.dhcp_socket)); |
| 726 | socket.set_ignore_naks(c.ignore_naks); | 660 | socket.set_ignore_naks(c.ignore_naks); |
| 727 | socket.set_max_lease_duration(c.max_lease_duration.map(crate::time::duration_to_smoltcp)); | 661 | socket.set_max_lease_duration(c.max_lease_duration.map(crate::time::duration_to_smoltcp)); |
| 728 | socket.set_ports(c.server_port, c.client_port); | 662 | socket.set_ports(c.server_port, c.client_port); |
| @@ -731,19 +665,20 @@ impl<D: Driver> Inner<D> { | |||
| 731 | socket.set_outgoing_options(&[]); | 665 | socket.set_outgoing_options(&[]); |
| 732 | #[cfg(feature = "dhcpv4-hostname")] | 666 | #[cfg(feature = "dhcpv4-hostname")] |
| 733 | if let Some(h) = c.hostname { | 667 | if let Some(h) = c.hostname { |
| 734 | // safety: we just did set_outgoing_options([]) so we know the socket is no longer holding a reference. | 668 | // safety: |
| 735 | let hostname = unsafe { &mut *self.hostname.get() }; | 669 | // - we just did set_outgoing_options([]) so we know the socket is no longer holding a reference. |
| 670 | // - we know this pointer lives for as long as the stack exists, because `new()` borrows | ||
| 671 | // the resources for `'d`. Therefore it's OK to pass a reference to this to smoltcp. | ||
| 672 | let hostname = unsafe { &mut *self.hostname }; | ||
| 736 | 673 | ||
| 737 | // create data | 674 | // create data |
| 738 | // safety: we know the buffer lives forever, new borrows the StackResources for 'static. | 675 | let data = hostname.data.write([0; MAX_HOSTNAME_LEN]); |
| 739 | // also we won't modify it until next call to this function. | 676 | data[..h.len()].copy_from_slice(h.as_bytes()); |
| 740 | hostname.data[..h.len()].copy_from_slice(h.as_bytes()); | 677 | let data: &[u8] = &data[..h.len()]; |
| 741 | let data: &[u8] = &hostname.data[..h.len()]; | ||
| 742 | let data: &'static [u8] = unsafe { core::mem::transmute(data) }; | ||
| 743 | 678 | ||
| 744 | // set the option. | 679 | // set the option. |
| 745 | hostname.option = smoltcp::wire::DhcpOption { data, kind: 12 }; | 680 | let option = hostname.option.write(smoltcp::wire::DhcpOption { data, kind: 12 }); |
| 746 | socket.set_outgoing_options(core::slice::from_ref(&hostname.option)); | 681 | socket.set_outgoing_options(core::slice::from_ref(option)); |
| 747 | } | 682 | } |
| 748 | 683 | ||
| 749 | socket.reset(); | 684 | socket.reset(); |
| @@ -751,7 +686,7 @@ impl<D: Driver> Inner<D> { | |||
| 751 | _ => { | 686 | _ => { |
| 752 | // Remove DHCP socket if any. | 687 | // Remove DHCP socket if any. |
| 753 | if let Some(socket) = self.dhcp_socket { | 688 | if let Some(socket) = self.dhcp_socket { |
| 754 | _s.sockets.remove(socket); | 689 | self.sockets.remove(socket); |
| 755 | self.dhcp_socket = None; | 690 | self.dhcp_socket = None; |
| 756 | } | 691 | } |
| 757 | } | 692 | } |
| @@ -759,14 +694,14 @@ impl<D: Driver> Inner<D> { | |||
| 759 | } | 694 | } |
| 760 | 695 | ||
| 761 | #[cfg(feature = "proto-ipv6")] | 696 | #[cfg(feature = "proto-ipv6")] |
| 762 | pub fn set_config_v6(&mut self, _s: &mut SocketStack, config: ConfigV6) { | 697 | pub fn set_config_v6(&mut self, config: ConfigV6) { |
| 763 | self.static_v6 = match config { | 698 | self.static_v6 = match config { |
| 764 | ConfigV6::None => None, | 699 | ConfigV6::None => None, |
| 765 | ConfigV6::Static(c) => Some(c), | 700 | ConfigV6::Static(c) => Some(c), |
| 766 | }; | 701 | }; |
| 767 | } | 702 | } |
| 768 | 703 | ||
| 769 | fn apply_static_config(&mut self, s: &mut SocketStack) { | 704 | fn apply_static_config(&mut self) { |
| 770 | let mut addrs = Vec::new(); | 705 | let mut addrs = Vec::new(); |
| 771 | #[cfg(feature = "dns")] | 706 | #[cfg(feature = "dns")] |
| 772 | let mut dns_servers: Vec<_, 6> = Vec::new(); | 707 | let mut dns_servers: Vec<_, 6> = Vec::new(); |
| @@ -810,20 +745,20 @@ impl<D: Driver> Inner<D> { | |||
| 810 | } | 745 | } |
| 811 | 746 | ||
| 812 | // Apply addresses | 747 | // Apply addresses |
| 813 | s.iface.update_ip_addrs(|a| *a = addrs); | 748 | self.iface.update_ip_addrs(|a| *a = addrs); |
| 814 | 749 | ||
| 815 | // Apply gateways | 750 | // Apply gateways |
| 816 | #[cfg(feature = "proto-ipv4")] | 751 | #[cfg(feature = "proto-ipv4")] |
| 817 | if let Some(gateway) = gateway_v4 { | 752 | if let Some(gateway) = gateway_v4 { |
| 818 | unwrap!(s.iface.routes_mut().add_default_ipv4_route(gateway)); | 753 | unwrap!(self.iface.routes_mut().add_default_ipv4_route(gateway)); |
| 819 | } else { | 754 | } else { |
| 820 | s.iface.routes_mut().remove_default_ipv4_route(); | 755 | self.iface.routes_mut().remove_default_ipv4_route(); |
| 821 | } | 756 | } |
| 822 | #[cfg(feature = "proto-ipv6")] | 757 | #[cfg(feature = "proto-ipv6")] |
| 823 | if let Some(gateway) = gateway_v6 { | 758 | if let Some(gateway) = gateway_v6 { |
| 824 | unwrap!(s.iface.routes_mut().add_default_ipv6_route(gateway)); | 759 | unwrap!(self.iface.routes_mut().add_default_ipv6_route(gateway)); |
| 825 | } else { | 760 | } else { |
| 826 | s.iface.routes_mut().remove_default_ipv6_route(); | 761 | self.iface.routes_mut().remove_default_ipv6_route(); |
| 827 | } | 762 | } |
| 828 | 763 | ||
| 829 | // Apply DNS servers | 764 | // Apply DNS servers |
| @@ -835,7 +770,7 @@ impl<D: Driver> Inner<D> { | |||
| 835 | } else { | 770 | } else { |
| 836 | dns_servers.len() | 771 | dns_servers.len() |
| 837 | }; | 772 | }; |
| 838 | s.sockets | 773 | self.sockets |
| 839 | .get_mut::<smoltcp::socket::dns::Socket>(self.dns_socket) | 774 | .get_mut::<smoltcp::socket::dns::Socket>(self.dns_socket) |
| 840 | .update_servers(&dns_servers[..count]); | 775 | .update_servers(&dns_servers[..count]); |
| 841 | } | 776 | } |
| @@ -843,10 +778,10 @@ impl<D: Driver> Inner<D> { | |||
| 843 | self.config_waker.wake(); | 778 | self.config_waker.wake(); |
| 844 | } | 779 | } |
| 845 | 780 | ||
| 846 | fn poll(&mut self, cx: &mut Context<'_>, s: &mut SocketStack) { | 781 | fn poll<D: Driver>(&mut self, cx: &mut Context<'_>, driver: &mut D) { |
| 847 | s.waker.register(cx.waker()); | 782 | self.waker.register(cx.waker()); |
| 848 | 783 | ||
| 849 | let (_hardware_addr, medium) = to_smoltcp_hardware_address(self.device.hardware_address()); | 784 | let (_hardware_addr, medium) = to_smoltcp_hardware_address(driver.hardware_address()); |
| 850 | 785 | ||
| 851 | #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] | 786 | #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] |
| 852 | { | 787 | { |
| @@ -859,21 +794,21 @@ impl<D: Driver> Inner<D> { | |||
| 859 | _ => false, | 794 | _ => false, |
| 860 | }; | 795 | }; |
| 861 | if do_set { | 796 | if do_set { |
| 862 | s.iface.set_hardware_addr(_hardware_addr); | 797 | self.iface.set_hardware_addr(_hardware_addr); |
| 863 | } | 798 | } |
| 864 | } | 799 | } |
| 865 | 800 | ||
| 866 | let timestamp = instant_to_smoltcp(Instant::now()); | 801 | let timestamp = instant_to_smoltcp(Instant::now()); |
| 867 | let mut smoldev = DriverAdapter { | 802 | let mut smoldev = DriverAdapter { |
| 868 | cx: Some(cx), | 803 | cx: Some(cx), |
| 869 | inner: &mut self.device, | 804 | inner: driver, |
| 870 | medium, | 805 | medium, |
| 871 | }; | 806 | }; |
| 872 | s.iface.poll(timestamp, &mut smoldev, &mut s.sockets); | 807 | self.iface.poll(timestamp, &mut smoldev, &mut self.sockets); |
| 873 | 808 | ||
| 874 | // Update link up | 809 | // Update link up |
| 875 | let old_link_up = self.link_up; | 810 | let old_link_up = self.link_up; |
| 876 | self.link_up = self.device.link_state(cx) == LinkState::Up; | 811 | self.link_up = driver.link_state(cx) == LinkState::Up; |
| 877 | 812 | ||
| 878 | // Print when changed | 813 | // Print when changed |
| 879 | if old_link_up != self.link_up { | 814 | if old_link_up != self.link_up { |
| @@ -885,7 +820,7 @@ impl<D: Driver> Inner<D> { | |||
| 885 | 820 | ||
| 886 | #[cfg(feature = "dhcpv4")] | 821 | #[cfg(feature = "dhcpv4")] |
| 887 | if let Some(dhcp_handle) = self.dhcp_socket { | 822 | if let Some(dhcp_handle) = self.dhcp_socket { |
| 888 | let socket = s.sockets.get_mut::<dhcpv4::Socket>(dhcp_handle); | 823 | let socket = self.sockets.get_mut::<dhcpv4::Socket>(dhcp_handle); |
| 889 | 824 | ||
| 890 | if self.link_up { | 825 | if self.link_up { |
| 891 | if old_link_up != self.link_up { | 826 | if old_link_up != self.link_up { |
| @@ -914,10 +849,10 @@ impl<D: Driver> Inner<D> { | |||
| 914 | } | 849 | } |
| 915 | 850 | ||
| 916 | if apply_config { | 851 | if apply_config { |
| 917 | self.apply_static_config(s); | 852 | self.apply_static_config(); |
| 918 | } | 853 | } |
| 919 | 854 | ||
| 920 | if let Some(poll_at) = s.iface.poll_at(timestamp, &mut s.sockets) { | 855 | if let Some(poll_at) = self.iface.poll_at(timestamp, &mut self.sockets) { |
| 921 | let t = pin!(Timer::at(instant_from_smoltcp(poll_at))); | 856 | let t = pin!(Timer::at(instant_from_smoltcp(poll_at))); |
| 922 | if t.poll(cx).is_ready() { | 857 | if t.poll(cx).is_ready() { |
| 923 | cx.waker().wake_by_ref(); | 858 | cx.waker().wake_by_ref(); |
| @@ -925,3 +860,17 @@ impl<D: Driver> Inner<D> { | |||
| 925 | } | 860 | } |
| 926 | } | 861 | } |
| 927 | } | 862 | } |
| 863 | |||
| 864 | impl<'d, D: Driver> Runner<'d, D> { | ||
| 865 | /// Run the network stack. | ||
| 866 | /// | ||
| 867 | /// You must call this in a background task, to process network events. | ||
| 868 | pub async fn run(&mut self) -> ! { | ||
| 869 | poll_fn(|cx| { | ||
| 870 | self.stack.with_mut(|i| i.poll(cx, &mut self.driver)); | ||
| 871 | Poll::<()>::Pending | ||
| 872 | }) | ||
| 873 | .await; | ||
| 874 | unreachable!() | ||
| 875 | } | ||
| 876 | } | ||
diff --git a/embassy-net/src/raw.rs b/embassy-net/src/raw.rs index 7ecd913e7..1098dc208 100644 --- a/embassy-net/src/raw.rs +++ b/embassy-net/src/raw.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | //! Raw sockets. | 1 | //! Raw sockets. |
| 2 | 2 | ||
| 3 | use core::cell::RefCell; | ||
| 4 | use core::future::poll_fn; | 3 | use core::future::poll_fn; |
| 5 | use core::mem; | 4 | use core::mem; |
| 6 | use core::task::{Context, Poll}; | 5 | use core::task::{Context, Poll}; |
| @@ -11,7 +10,7 @@ use smoltcp::socket::raw; | |||
| 11 | pub use smoltcp::socket::raw::PacketMetadata; | 10 | pub use smoltcp::socket::raw::PacketMetadata; |
| 12 | use smoltcp::wire::{IpProtocol, IpVersion}; | 11 | use smoltcp::wire::{IpProtocol, IpVersion}; |
| 13 | 12 | ||
| 14 | use crate::{SocketStack, Stack}; | 13 | use crate::Stack; |
| 15 | 14 | ||
| 16 | /// Error returned by [`RawSocket::recv`] and [`RawSocket::send`]. | 15 | /// Error returned by [`RawSocket::recv`] and [`RawSocket::send`]. |
| 17 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] | 16 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
| @@ -23,14 +22,14 @@ pub enum RecvError { | |||
| 23 | 22 | ||
| 24 | /// An Raw socket. | 23 | /// An Raw socket. |
| 25 | pub struct RawSocket<'a> { | 24 | pub struct RawSocket<'a> { |
| 26 | stack: &'a RefCell<SocketStack>, | 25 | stack: Stack<'a>, |
| 27 | handle: SocketHandle, | 26 | handle: SocketHandle, |
| 28 | } | 27 | } |
| 29 | 28 | ||
| 30 | impl<'a> RawSocket<'a> { | 29 | impl<'a> RawSocket<'a> { |
| 31 | /// Create a new Raw socket using the provided stack and buffers. | 30 | /// Create a new Raw socket using the provided stack and buffers. |
| 32 | pub fn new<D: Driver>( | 31 | pub fn new<D: Driver>( |
| 33 | stack: &'a Stack<D>, | 32 | stack: Stack<'a>, |
| 34 | ip_version: IpVersion, | 33 | ip_version: IpVersion, |
| 35 | ip_protocol: IpProtocol, | 34 | ip_protocol: IpProtocol, |
| 36 | rx_meta: &'a mut [PacketMetadata], | 35 | rx_meta: &'a mut [PacketMetadata], |
| @@ -38,31 +37,29 @@ impl<'a> RawSocket<'a> { | |||
| 38 | tx_meta: &'a mut [PacketMetadata], | 37 | tx_meta: &'a mut [PacketMetadata], |
| 39 | tx_buffer: &'a mut [u8], | 38 | tx_buffer: &'a mut [u8], |
| 40 | ) -> Self { | 39 | ) -> Self { |
| 41 | let s = &mut *stack.socket.borrow_mut(); | 40 | let handle = stack.with_mut(|i| { |
| 41 | let rx_meta: &'static mut [PacketMetadata] = unsafe { mem::transmute(rx_meta) }; | ||
| 42 | let rx_buffer: &'static mut [u8] = unsafe { mem::transmute(rx_buffer) }; | ||
| 43 | let tx_meta: &'static mut [PacketMetadata] = unsafe { mem::transmute(tx_meta) }; | ||
| 44 | let tx_buffer: &'static mut [u8] = unsafe { mem::transmute(tx_buffer) }; | ||
| 45 | i.sockets.add(raw::Socket::new( | ||
| 46 | ip_version, | ||
| 47 | ip_protocol, | ||
| 48 | raw::PacketBuffer::new(rx_meta, rx_buffer), | ||
| 49 | raw::PacketBuffer::new(tx_meta, tx_buffer), | ||
| 50 | )) | ||
| 51 | }); | ||
| 42 | 52 | ||
| 43 | let rx_meta: &'static mut [PacketMetadata] = unsafe { mem::transmute(rx_meta) }; | 53 | Self { stack, handle } |
| 44 | let rx_buffer: &'static mut [u8] = unsafe { mem::transmute(rx_buffer) }; | ||
| 45 | let tx_meta: &'static mut [PacketMetadata] = unsafe { mem::transmute(tx_meta) }; | ||
| 46 | let tx_buffer: &'static mut [u8] = unsafe { mem::transmute(tx_buffer) }; | ||
| 47 | let handle = s.sockets.add(raw::Socket::new( | ||
| 48 | ip_version, | ||
| 49 | ip_protocol, | ||
| 50 | raw::PacketBuffer::new(rx_meta, rx_buffer), | ||
| 51 | raw::PacketBuffer::new(tx_meta, tx_buffer), | ||
| 52 | )); | ||
| 53 | |||
| 54 | Self { | ||
| 55 | stack: &stack.socket, | ||
| 56 | handle, | ||
| 57 | } | ||
| 58 | } | 54 | } |
| 59 | 55 | ||
| 60 | fn with_mut<R>(&self, f: impl FnOnce(&mut raw::Socket, &mut Interface) -> R) -> R { | 56 | fn with_mut<R>(&self, f: impl FnOnce(&mut raw::Socket, &mut Interface) -> R) -> R { |
| 61 | let s = &mut *self.stack.borrow_mut(); | 57 | self.stack.with_mut(|i| { |
| 62 | let socket = s.sockets.get_mut::<raw::Socket>(self.handle); | 58 | let socket = i.sockets.get_mut::<raw::Socket>(self.handle); |
| 63 | let res = f(socket, &mut s.iface); | 59 | let res = f(socket, &mut i.iface); |
| 64 | s.waker.wake(); | 60 | i.waker.wake(); |
| 65 | res | 61 | res |
| 62 | }) | ||
| 66 | } | 63 | } |
| 67 | 64 | ||
| 68 | /// Receive a datagram. | 65 | /// Receive a datagram. |
| @@ -115,6 +112,10 @@ impl<'a> RawSocket<'a> { | |||
| 115 | 112 | ||
| 116 | impl Drop for RawSocket<'_> { | 113 | impl Drop for RawSocket<'_> { |
| 117 | fn drop(&mut self) { | 114 | fn drop(&mut self) { |
| 118 | self.stack.borrow_mut().sockets.remove(self.handle); | 115 | self.stack.with_mut(|i| i.sockets.remove(self.handle)); |
| 119 | } | 116 | } |
| 120 | } | 117 | } |
| 118 | |||
| 119 | fn _assert_covariant<'a, 'b: 'a>(x: RawSocket<'b>) -> RawSocket<'a> { | ||
| 120 | x | ||
| 121 | } | ||
diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs index b2e3279cc..bcddbc95b 100644 --- a/embassy-net/src/tcp.rs +++ b/embassy-net/src/tcp.rs | |||
| @@ -8,12 +8,10 @@ | |||
| 8 | //! Incoming connections when no socket is listening are rejected. To accept many incoming | 8 | //! Incoming connections when no socket is listening are rejected. To accept many incoming |
| 9 | //! connections, create many sockets and put them all into listening mode. | 9 | //! connections, create many sockets and put them all into listening mode. |
| 10 | 10 | ||
| 11 | use core::cell::RefCell; | ||
| 12 | use core::future::poll_fn; | 11 | use core::future::poll_fn; |
| 13 | use core::mem; | 12 | use core::mem; |
| 14 | use core::task::Poll; | 13 | use core::task::Poll; |
| 15 | 14 | ||
| 16 | use embassy_net_driver::Driver; | ||
| 17 | use embassy_time::Duration; | 15 | use embassy_time::Duration; |
| 18 | use smoltcp::iface::{Interface, SocketHandle}; | 16 | use smoltcp::iface::{Interface, SocketHandle}; |
| 19 | use smoltcp::socket::tcp; | 17 | use smoltcp::socket::tcp; |
| @@ -21,7 +19,7 @@ pub use smoltcp::socket::tcp::State; | |||
| 21 | use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; | 19 | use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; |
| 22 | 20 | ||
| 23 | use crate::time::duration_to_smoltcp; | 21 | use crate::time::duration_to_smoltcp; |
| 24 | use crate::{SocketStack, Stack}; | 22 | use crate::Stack; |
| 25 | 23 | ||
| 26 | /// Error returned by TcpSocket read/write functions. | 24 | /// Error returned by TcpSocket read/write functions. |
| 27 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] | 25 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
| @@ -157,20 +155,18 @@ impl<'a> TcpWriter<'a> { | |||
| 157 | 155 | ||
| 158 | impl<'a> TcpSocket<'a> { | 156 | impl<'a> TcpSocket<'a> { |
| 159 | /// Create a new TCP socket on the given stack, with the given buffers. | 157 | /// Create a new TCP socket on the given stack, with the given buffers. |
| 160 | pub fn new<D: Driver>(stack: &'a Stack<D>, rx_buffer: &'a mut [u8], tx_buffer: &'a mut [u8]) -> Self { | 158 | pub fn new(stack: Stack<'a>, rx_buffer: &'a mut [u8], tx_buffer: &'a mut [u8]) -> Self { |
| 161 | let s = &mut *stack.socket.borrow_mut(); | 159 | let handle = stack.with_mut(|i| { |
| 162 | let rx_buffer: &'static mut [u8] = unsafe { mem::transmute(rx_buffer) }; | 160 | let rx_buffer: &'static mut [u8] = unsafe { mem::transmute(rx_buffer) }; |
| 163 | let tx_buffer: &'static mut [u8] = unsafe { mem::transmute(tx_buffer) }; | 161 | let tx_buffer: &'static mut [u8] = unsafe { mem::transmute(tx_buffer) }; |
| 164 | let handle = s.sockets.add(tcp::Socket::new( | 162 | i.sockets.add(tcp::Socket::new( |
| 165 | tcp::SocketBuffer::new(rx_buffer), | 163 | tcp::SocketBuffer::new(rx_buffer), |
| 166 | tcp::SocketBuffer::new(tx_buffer), | 164 | tcp::SocketBuffer::new(tx_buffer), |
| 167 | )); | 165 | )) |
| 166 | }); | ||
| 168 | 167 | ||
| 169 | Self { | 168 | Self { |
| 170 | io: TcpIo { | 169 | io: TcpIo { stack: stack, handle }, |
| 171 | stack: &stack.socket, | ||
| 172 | handle, | ||
| 173 | }, | ||
| 174 | } | 170 | } |
| 175 | } | 171 | } |
| 176 | 172 | ||
| @@ -228,7 +224,7 @@ impl<'a> TcpSocket<'a> { | |||
| 228 | where | 224 | where |
| 229 | T: Into<IpEndpoint>, | 225 | T: Into<IpEndpoint>, |
| 230 | { | 226 | { |
| 231 | let local_port = self.io.stack.borrow_mut().get_local_port(); | 227 | let local_port = self.io.stack.with_mut(|i| i.get_local_port()); |
| 232 | 228 | ||
| 233 | match { | 229 | match { |
| 234 | self.io | 230 | self.io |
| @@ -401,31 +397,43 @@ impl<'a> TcpSocket<'a> { | |||
| 401 | 397 | ||
| 402 | impl<'a> Drop for TcpSocket<'a> { | 398 | impl<'a> Drop for TcpSocket<'a> { |
| 403 | fn drop(&mut self) { | 399 | fn drop(&mut self) { |
| 404 | self.io.stack.borrow_mut().sockets.remove(self.io.handle); | 400 | self.io.stack.with_mut(|i| i.sockets.remove(self.io.handle)); |
| 405 | } | 401 | } |
| 406 | } | 402 | } |
| 407 | 403 | ||
| 404 | fn _assert_covariant<'a, 'b: 'a>(x: TcpSocket<'b>) -> TcpSocket<'a> { | ||
| 405 | x | ||
| 406 | } | ||
| 407 | fn _assert_covariant_reader<'a, 'b: 'a>(x: TcpReader<'b>) -> TcpReader<'a> { | ||
| 408 | x | ||
| 409 | } | ||
| 410 | fn _assert_covariant_writer<'a, 'b: 'a>(x: TcpWriter<'b>) -> TcpWriter<'a> { | ||
| 411 | x | ||
| 412 | } | ||
| 413 | |||
| 408 | // ======================= | 414 | // ======================= |
| 409 | 415 | ||
| 410 | #[derive(Copy, Clone)] | 416 | #[derive(Copy, Clone)] |
| 411 | struct TcpIo<'a> { | 417 | struct TcpIo<'a> { |
| 412 | stack: &'a RefCell<SocketStack>, | 418 | stack: Stack<'a>, |
| 413 | handle: SocketHandle, | 419 | handle: SocketHandle, |
| 414 | } | 420 | } |
| 415 | 421 | ||
| 416 | impl<'d> TcpIo<'d> { | 422 | impl<'d> TcpIo<'d> { |
| 417 | fn with<R>(&self, f: impl FnOnce(&tcp::Socket, &Interface) -> R) -> R { | 423 | fn with<R>(&self, f: impl FnOnce(&tcp::Socket, &Interface) -> R) -> R { |
| 418 | let s = &*self.stack.borrow(); | 424 | self.stack.with(|i| { |
| 419 | let socket = s.sockets.get::<tcp::Socket>(self.handle); | 425 | let socket = i.sockets.get::<tcp::Socket>(self.handle); |
| 420 | f(socket, &s.iface) | 426 | f(socket, &i.iface) |
| 427 | }) | ||
| 421 | } | 428 | } |
| 422 | 429 | ||
| 423 | fn with_mut<R>(&mut self, f: impl FnOnce(&mut tcp::Socket, &mut Interface) -> R) -> R { | 430 | fn with_mut<R>(&mut self, f: impl FnOnce(&mut tcp::Socket, &mut Interface) -> R) -> R { |
| 424 | let s = &mut *self.stack.borrow_mut(); | 431 | self.stack.with_mut(|i| { |
| 425 | let socket = s.sockets.get_mut::<tcp::Socket>(self.handle); | 432 | let socket = i.sockets.get_mut::<tcp::Socket>(self.handle); |
| 426 | let res = f(socket, &mut s.iface); | 433 | let res = f(socket, &mut i.iface); |
| 427 | s.waker.wake(); | 434 | i.waker.wake(); |
| 428 | res | 435 | res |
| 436 | }) | ||
| 429 | } | 437 | } |
| 430 | 438 | ||
| 431 | async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { | 439 | async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { |
| @@ -676,15 +684,15 @@ pub mod client { | |||
| 676 | /// TCP client connection pool compatible with `embedded-nal-async` traits. | 684 | /// TCP client connection pool compatible with `embedded-nal-async` traits. |
| 677 | /// | 685 | /// |
| 678 | /// The pool is capable of managing up to N concurrent connections with tx and rx buffers according to TX_SZ and RX_SZ. | 686 | /// The pool is capable of managing up to N concurrent connections with tx and rx buffers according to TX_SZ and RX_SZ. |
| 679 | pub struct TcpClient<'d, D: Driver, const N: usize, const TX_SZ: usize = 1024, const RX_SZ: usize = 1024> { | 687 | pub struct TcpClient<'d, const N: usize, const TX_SZ: usize = 1024, const RX_SZ: usize = 1024> { |
| 680 | stack: &'d Stack<D>, | 688 | stack: Stack<'d>, |
| 681 | state: &'d TcpClientState<N, TX_SZ, RX_SZ>, | 689 | state: &'d TcpClientState<N, TX_SZ, RX_SZ>, |
| 682 | socket_timeout: Option<Duration>, | 690 | socket_timeout: Option<Duration>, |
| 683 | } | 691 | } |
| 684 | 692 | ||
| 685 | impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpClient<'d, D, N, TX_SZ, RX_SZ> { | 693 | impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpClient<'d, N, TX_SZ, RX_SZ> { |
| 686 | /// Create a new `TcpClient`. | 694 | /// Create a new `TcpClient`. |
| 687 | pub fn new(stack: &'d Stack<D>, state: &'d TcpClientState<N, TX_SZ, RX_SZ>) -> Self { | 695 | pub fn new(stack: Stack<'d>, state: &'d TcpClientState<N, TX_SZ, RX_SZ>) -> Self { |
| 688 | Self { | 696 | Self { |
| 689 | stack, | 697 | stack, |
| 690 | state, | 698 | state, |
| @@ -701,8 +709,8 @@ pub mod client { | |||
| 701 | } | 709 | } |
| 702 | } | 710 | } |
| 703 | 711 | ||
| 704 | impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize> embedded_nal_async::TcpConnect | 712 | impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> embedded_nal_async::TcpConnect |
| 705 | for TcpClient<'d, D, N, TX_SZ, RX_SZ> | 713 | for TcpClient<'d, N, TX_SZ, RX_SZ> |
| 706 | { | 714 | { |
| 707 | type Error = Error; | 715 | type Error = Error; |
| 708 | type Connection<'m> = TcpConnection<'m, N, TX_SZ, RX_SZ> where Self: 'm; | 716 | type Connection<'m> = TcpConnection<'m, N, TX_SZ, RX_SZ> where Self: 'm; |
| @@ -722,7 +730,7 @@ pub mod client { | |||
| 722 | IpAddr::V6(_) => panic!("ipv6 support not enabled"), | 730 | IpAddr::V6(_) => panic!("ipv6 support not enabled"), |
| 723 | }; | 731 | }; |
| 724 | let remote_endpoint = (addr, remote.port()); | 732 | let remote_endpoint = (addr, remote.port()); |
| 725 | let mut socket = TcpConnection::new(&self.stack, self.state)?; | 733 | let mut socket = TcpConnection::new(self.stack, self.state)?; |
| 726 | socket.socket.set_timeout(self.socket_timeout.clone()); | 734 | socket.socket.set_timeout(self.socket_timeout.clone()); |
| 727 | socket | 735 | socket |
| 728 | .socket | 736 | .socket |
| @@ -741,7 +749,7 @@ pub mod client { | |||
| 741 | } | 749 | } |
| 742 | 750 | ||
| 743 | impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpConnection<'d, N, TX_SZ, RX_SZ> { | 751 | impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpConnection<'d, N, TX_SZ, RX_SZ> { |
| 744 | fn new<D: Driver>(stack: &'d Stack<D>, state: &'d TcpClientState<N, TX_SZ, RX_SZ>) -> Result<Self, Error> { | 752 | fn new(stack: Stack<'d>, state: &'d TcpClientState<N, TX_SZ, RX_SZ>) -> Result<Self, Error> { |
| 745 | let mut bufs = state.pool.alloc().ok_or(Error::ConnectionReset)?; | 753 | let mut bufs = state.pool.alloc().ok_or(Error::ConnectionReset)?; |
| 746 | Ok(Self { | 754 | Ok(Self { |
| 747 | socket: unsafe { TcpSocket::new(stack, &mut bufs.as_mut().1, &mut bufs.as_mut().0) }, | 755 | socket: unsafe { TcpSocket::new(stack, &mut bufs.as_mut().1, &mut bufs.as_mut().0) }, |
diff --git a/embassy-net/src/udp.rs b/embassy-net/src/udp.rs index 1d5360187..3eb6e2f83 100644 --- a/embassy-net/src/udp.rs +++ b/embassy-net/src/udp.rs | |||
| @@ -1,17 +1,15 @@ | |||
| 1 | //! UDP sockets. | 1 | //! UDP sockets. |
| 2 | 2 | ||
| 3 | use core::cell::RefCell; | ||
| 4 | use core::future::poll_fn; | 3 | use core::future::poll_fn; |
| 5 | use core::mem; | 4 | use core::mem; |
| 6 | use core::task::{Context, Poll}; | 5 | use core::task::{Context, Poll}; |
| 7 | 6 | ||
| 8 | use embassy_net_driver::Driver; | ||
| 9 | use smoltcp::iface::{Interface, SocketHandle}; | 7 | use smoltcp::iface::{Interface, SocketHandle}; |
| 10 | use smoltcp::socket::udp; | 8 | use smoltcp::socket::udp; |
| 11 | pub use smoltcp::socket::udp::{PacketMetadata, UdpMetadata}; | 9 | pub use smoltcp::socket::udp::{PacketMetadata, UdpMetadata}; |
| 12 | use smoltcp::wire::IpListenEndpoint; | 10 | use smoltcp::wire::IpListenEndpoint; |
| 13 | 11 | ||
| 14 | use crate::{SocketStack, Stack}; | 12 | use crate::Stack; |
| 15 | 13 | ||
| 16 | /// Error returned by [`UdpSocket::bind`]. | 14 | /// Error returned by [`UdpSocket::bind`]. |
| 17 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] | 15 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
| @@ -43,34 +41,31 @@ pub enum RecvError { | |||
| 43 | 41 | ||
| 44 | /// An UDP socket. | 42 | /// An UDP socket. |
| 45 | pub struct UdpSocket<'a> { | 43 | pub struct UdpSocket<'a> { |
| 46 | stack: &'a RefCell<SocketStack>, | 44 | stack: Stack<'a>, |
| 47 | handle: SocketHandle, | 45 | handle: SocketHandle, |
| 48 | } | 46 | } |
| 49 | 47 | ||
| 50 | impl<'a> UdpSocket<'a> { | 48 | impl<'a> UdpSocket<'a> { |
| 51 | /// Create a new UDP socket using the provided stack and buffers. | 49 | /// Create a new UDP socket using the provided stack and buffers. |
| 52 | pub fn new<D: Driver>( | 50 | pub fn new( |
| 53 | stack: &'a Stack<D>, | 51 | stack: Stack<'a>, |
| 54 | rx_meta: &'a mut [PacketMetadata], | 52 | rx_meta: &'a mut [PacketMetadata], |
| 55 | rx_buffer: &'a mut [u8], | 53 | rx_buffer: &'a mut [u8], |
| 56 | tx_meta: &'a mut [PacketMetadata], | 54 | tx_meta: &'a mut [PacketMetadata], |
| 57 | tx_buffer: &'a mut [u8], | 55 | tx_buffer: &'a mut [u8], |
| 58 | ) -> Self { | 56 | ) -> Self { |
| 59 | let s = &mut *stack.socket.borrow_mut(); | 57 | let handle = stack.with_mut(|i| { |
| 60 | 58 | let rx_meta: &'static mut [PacketMetadata] = unsafe { mem::transmute(rx_meta) }; | |
| 61 | let rx_meta: &'static mut [PacketMetadata] = unsafe { mem::transmute(rx_meta) }; | 59 | let rx_buffer: &'static mut [u8] = unsafe { mem::transmute(rx_buffer) }; |
| 62 | let rx_buffer: &'static mut [u8] = unsafe { mem::transmute(rx_buffer) }; | 60 | let tx_meta: &'static mut [PacketMetadata] = unsafe { mem::transmute(tx_meta) }; |
| 63 | let tx_meta: &'static mut [PacketMetadata] = unsafe { mem::transmute(tx_meta) }; | 61 | let tx_buffer: &'static mut [u8] = unsafe { mem::transmute(tx_buffer) }; |
| 64 | let tx_buffer: &'static mut [u8] = unsafe { mem::transmute(tx_buffer) }; | 62 | i.sockets.add(udp::Socket::new( |
| 65 | let handle = s.sockets.add(udp::Socket::new( | 63 | udp::PacketBuffer::new(rx_meta, rx_buffer), |
| 66 | udp::PacketBuffer::new(rx_meta, rx_buffer), | 64 | udp::PacketBuffer::new(tx_meta, tx_buffer), |
| 67 | udp::PacketBuffer::new(tx_meta, tx_buffer), | 65 | )) |
| 68 | )); | 66 | }); |
| 69 | 67 | ||
| 70 | Self { | 68 | Self { stack, handle } |
| 71 | stack: &stack.socket, | ||
| 72 | handle, | ||
| 73 | } | ||
| 74 | } | 69 | } |
| 75 | 70 | ||
| 76 | /// Bind the socket to a local endpoint. | 71 | /// Bind the socket to a local endpoint. |
| @@ -82,7 +77,7 @@ impl<'a> UdpSocket<'a> { | |||
| 82 | 77 | ||
| 83 | if endpoint.port == 0 { | 78 | if endpoint.port == 0 { |
| 84 | // If user didn't specify port allocate a dynamic port. | 79 | // If user didn't specify port allocate a dynamic port. |
| 85 | endpoint.port = self.stack.borrow_mut().get_local_port(); | 80 | endpoint.port = self.stack.with_mut(|i| i.get_local_port()); |
| 86 | } | 81 | } |
| 87 | 82 | ||
| 88 | match self.with_mut(|s, _| s.bind(endpoint)) { | 83 | match self.with_mut(|s, _| s.bind(endpoint)) { |
| @@ -93,17 +88,19 @@ impl<'a> UdpSocket<'a> { | |||
| 93 | } | 88 | } |
| 94 | 89 | ||
| 95 | fn with<R>(&self, f: impl FnOnce(&udp::Socket, &Interface) -> R) -> R { | 90 | fn with<R>(&self, f: impl FnOnce(&udp::Socket, &Interface) -> R) -> R { |
| 96 | let s = &*self.stack.borrow(); | 91 | self.stack.with(|i| { |
| 97 | let socket = s.sockets.get::<udp::Socket>(self.handle); | 92 | let socket = i.sockets.get::<udp::Socket>(self.handle); |
| 98 | f(socket, &s.iface) | 93 | f(socket, &i.iface) |
| 94 | }) | ||
| 99 | } | 95 | } |
| 100 | 96 | ||
| 101 | fn with_mut<R>(&self, f: impl FnOnce(&mut udp::Socket, &mut Interface) -> R) -> R { | 97 | fn with_mut<R>(&self, f: impl FnOnce(&mut udp::Socket, &mut Interface) -> R) -> R { |
| 102 | let s = &mut *self.stack.borrow_mut(); | 98 | self.stack.with_mut(|i| { |
| 103 | let socket = s.sockets.get_mut::<udp::Socket>(self.handle); | 99 | let socket = i.sockets.get_mut::<udp::Socket>(self.handle); |
| 104 | let res = f(socket, &mut s.iface); | 100 | let res = f(socket, &mut i.iface); |
| 105 | s.waker.wake(); | 101 | i.waker.wake(); |
| 106 | res | 102 | res |
| 103 | }) | ||
| 107 | } | 104 | } |
| 108 | 105 | ||
| 109 | /// Receive a datagram. | 106 | /// Receive a datagram. |
| @@ -298,6 +295,10 @@ impl<'a> UdpSocket<'a> { | |||
| 298 | 295 | ||
| 299 | impl Drop for UdpSocket<'_> { | 296 | impl Drop for UdpSocket<'_> { |
| 300 | fn drop(&mut self) { | 297 | fn drop(&mut self) { |
| 301 | self.stack.borrow_mut().sockets.remove(self.handle); | 298 | self.stack.with_mut(|i| i.sockets.remove(self.handle)); |
| 302 | } | 299 | } |
| 303 | } | 300 | } |
| 301 | |||
| 302 | fn _assert_covariant<'a, 'b: 'a>(x: UdpSocket<'b>) -> UdpSocket<'a> { | ||
| 303 | x | ||
| 304 | } | ||
diff --git a/examples/nrf52840/src/bin/ethernet_enc28j60.rs b/examples/nrf52840/src/bin/ethernet_enc28j60.rs index 94cf09c88..0946492fe 100644 --- a/examples/nrf52840/src/bin/ethernet_enc28j60.rs +++ b/examples/nrf52840/src/bin/ethernet_enc28j60.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | 6 | use embassy_net::tcp::TcpSocket; |
| 7 | use embassy_net::{Stack, StackResources}; | 7 | use embassy_net::StackResources; |
| 8 | use embassy_net_enc28j60::Enc28j60; | 8 | use embassy_net_enc28j60::Enc28j60; |
| 9 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; | 9 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; |
| 10 | use embassy_nrf::rng::Rng; | 10 | use embassy_nrf::rng::Rng; |
| @@ -23,11 +23,12 @@ bind_interrupts!(struct Irqs { | |||
| 23 | 23 | ||
| 24 | #[embassy_executor::task] | 24 | #[embassy_executor::task] |
| 25 | async fn net_task( | 25 | async fn net_task( |
| 26 | stack: &'static Stack< | 26 | mut runner: embassy_net::Runner< |
| 27 | 'static, | ||
| 27 | Enc28j60<ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static>, Delay>, Output<'static>>, | 28 | Enc28j60<ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static>, Delay>, Output<'static>>, |
| 28 | >, | 29 | >, |
| 29 | ) -> ! { | 30 | ) -> ! { |
| 30 | stack.run().await | 31 | runner.run().await |
| 31 | } | 32 | } |
| 32 | 33 | ||
| 33 | #[embassy_executor::main] | 34 | #[embassy_executor::main] |
| @@ -67,12 +68,9 @@ async fn main(spawner: Spawner) { | |||
| 67 | 68 | ||
| 68 | // Init network stack | 69 | // Init network stack |
| 69 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 70 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 70 | static STACK: StaticCell< | 71 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 71 | Stack<Enc28j60<ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static>, Delay>, Output<'static>>>, | ||
| 72 | > = StaticCell::new(); | ||
| 73 | let stack = STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | ||
| 74 | 72 | ||
| 75 | unwrap!(spawner.spawn(net_task(stack))); | 73 | unwrap!(spawner.spawn(net_task(runner))); |
| 76 | 74 | ||
| 77 | // And now we can use it! | 75 | // And now we can use it! |
| 78 | 76 | ||
diff --git a/examples/nrf52840/src/bin/usb_ethernet.rs b/examples/nrf52840/src/bin/usb_ethernet.rs index e56b215e3..b07adac1f 100644 --- a/examples/nrf52840/src/bin/usb_ethernet.rs +++ b/examples/nrf52840/src/bin/usb_ethernet.rs | |||
| @@ -6,7 +6,7 @@ use core::mem; | |||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_net::tcp::TcpSocket; | 8 | use embassy_net::tcp::TcpSocket; |
| 9 | use embassy_net::{Stack, StackResources}; | 9 | use embassy_net::StackResources; |
| 10 | use embassy_nrf::rng::Rng; | 10 | use embassy_nrf::rng::Rng; |
| 11 | use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; | 11 | use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; |
| 12 | use embassy_nrf::usb::Driver; | 12 | use embassy_nrf::usb::Driver; |
| @@ -39,8 +39,8 @@ async fn usb_ncm_task(class: Runner<'static, MyDriver, MTU>) -> ! { | |||
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | #[embassy_executor::task] | 41 | #[embassy_executor::task] |
| 42 | async fn net_task(stack: &'static Stack<Device<'static, MTU>>) -> ! { | 42 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static, MTU>>) -> ! { |
| 43 | stack.run().await | 43 | runner.run().await |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | #[embassy_executor::main] | 46 | #[embassy_executor::main] |
| @@ -116,10 +116,9 @@ async fn main(spawner: Spawner) { | |||
| 116 | 116 | ||
| 117 | // Init network stack | 117 | // Init network stack |
| 118 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 118 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 119 | static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new(); | 119 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 120 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | ||
| 121 | 120 | ||
| 122 | unwrap!(spawner.spawn(net_task(stack))); | 121 | unwrap!(spawner.spawn(net_task(runner))); |
| 123 | 122 | ||
| 124 | // And now we can use it! | 123 | // And now we can use it! |
| 125 | 124 | ||
diff --git a/examples/nrf52840/src/bin/wifi_esp_hosted.rs b/examples/nrf52840/src/bin/wifi_esp_hosted.rs index a3b69a99b..26eaf485e 100644 --- a/examples/nrf52840/src/bin/wifi_esp_hosted.rs +++ b/examples/nrf52840/src/bin/wifi_esp_hosted.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::{info, unwrap, warn}; | 4 | use defmt::{info, unwrap, warn}; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | 6 | use embassy_net::tcp::TcpSocket; |
| 7 | use embassy_net::{Stack, StackResources}; | 7 | use embassy_net::StackResources; |
| 8 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; | 8 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; |
| 9 | use embassy_nrf::rng::Rng; | 9 | use embassy_nrf::rng::Rng; |
| 10 | use embassy_nrf::spim::{self, Spim}; | 10 | use embassy_nrf::spim::{self, Spim}; |
| @@ -36,8 +36,8 @@ async fn wifi_task( | |||
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | #[embassy_executor::task] | 38 | #[embassy_executor::task] |
| 39 | async fn net_task(stack: &'static Stack<hosted::NetDriver<'static>>) -> ! { | 39 | async fn net_task(mut runner: embassy_net::Runner<'static, hosted::NetDriver<'static>>) -> ! { |
| 40 | stack.run().await | 40 | runner.run().await |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | #[embassy_executor::main] | 43 | #[embassy_executor::main] |
| @@ -90,10 +90,9 @@ async fn main(spawner: Spawner) { | |||
| 90 | 90 | ||
| 91 | // Init network stack | 91 | // Init network stack |
| 92 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 92 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 93 | static STACK: StaticCell<Stack<hosted::NetDriver<'static>>> = StaticCell::new(); | 93 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 94 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | ||
| 95 | 94 | ||
| 96 | unwrap!(spawner.spawn(net_task(stack))); | 95 | unwrap!(spawner.spawn(net_task(runner))); |
| 97 | 96 | ||
| 98 | // And now we can use it! | 97 | // And now we can use it! |
| 99 | 98 | ||
diff --git a/examples/nrf9160/src/bin/modem_tcp_client.rs b/examples/nrf9160/src/bin/modem_tcp_client.rs index 5335b6b51..929883884 100644 --- a/examples/nrf9160/src/bin/modem_tcp_client.rs +++ b/examples/nrf9160/src/bin/modem_tcp_client.rs | |||
| @@ -46,15 +46,15 @@ async fn modem_task(runner: Runner<'static>) -> ! { | |||
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | #[embassy_executor::task] | 48 | #[embassy_executor::task] |
| 49 | async fn net_task(stack: &'static Stack<embassy_net_nrf91::NetDriver<'static>>) -> ! { | 49 | async fn net_task(mut runner: embassy_net::Runner<'static, embassy_net_nrf91::NetDriver<'static>>) -> ! { |
| 50 | stack.run().await | 50 | runner.run().await |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | #[embassy_executor::task] | 53 | #[embassy_executor::task] |
| 54 | async fn control_task( | 54 | async fn control_task( |
| 55 | control: &'static context::Control<'static>, | 55 | control: &'static context::Control<'static>, |
| 56 | config: context::Config<'static>, | 56 | config: context::Config<'static>, |
| 57 | stack: &'static Stack<embassy_net_nrf91::NetDriver<'static>>, | 57 | stack: Stack<'static>, |
| 58 | ) { | 58 | ) { |
| 59 | unwrap!(control.configure(&config).await); | 59 | unwrap!(control.configure(&config).await); |
| 60 | unwrap!( | 60 | unwrap!( |
| @@ -150,15 +150,9 @@ async fn main(spawner: Spawner) { | |||
| 150 | 150 | ||
| 151 | // Init network stack | 151 | // Init network stack |
| 152 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 152 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); |
| 153 | static STACK: StaticCell<Stack<embassy_net_nrf91::NetDriver<'static>>> = StaticCell::new(); | 153 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::<2>::new()), seed); |
| 154 | let stack = &*STACK.init(Stack::new( | ||
| 155 | device, | ||
| 156 | config, | ||
| 157 | RESOURCES.init(StackResources::<2>::new()), | ||
| 158 | seed, | ||
| 159 | )); | ||
| 160 | 154 | ||
| 161 | unwrap!(spawner.spawn(net_task(stack))); | 155 | unwrap!(spawner.spawn(net_task(runner))); |
| 162 | 156 | ||
| 163 | static CONTROL: StaticCell<context::Control<'static>> = StaticCell::new(); | 157 | static CONTROL: StaticCell<context::Control<'static>> = StaticCell::new(); |
| 164 | let control = CONTROL.init(context::Control::new(control, 0).await); | 158 | let control = CONTROL.init(context::Control::new(control, 0).await); |
diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index aaa035a72..12003adbe 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs | |||
| @@ -36,8 +36,8 @@ async fn ethernet_task( | |||
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | #[embassy_executor::task] | 38 | #[embassy_executor::task] |
| 39 | async fn net_task(stack: &'static Stack<Device<'static>>) -> ! { | 39 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { |
| 40 | stack.run().await | 40 | runner.run().await |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | #[embassy_executor::main] | 43 | #[embassy_executor::main] |
| @@ -71,17 +71,16 @@ async fn main(spawner: Spawner) { | |||
| 71 | let seed = rng.next_u64(); | 71 | let seed = rng.next_u64(); |
| 72 | 72 | ||
| 73 | // Init network stack | 73 | // Init network stack |
| 74 | static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new(); | ||
| 75 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 74 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 76 | let stack = &*STACK.init(Stack::new( | 75 | let (stack, runner) = embassy_net::new( |
| 77 | device, | 76 | device, |
| 78 | embassy_net::Config::dhcpv4(Default::default()), | 77 | embassy_net::Config::dhcpv4(Default::default()), |
| 79 | RESOURCES.init(StackResources::new()), | 78 | RESOURCES.init(StackResources::new()), |
| 80 | seed, | 79 | seed, |
| 81 | )); | 80 | ); |
| 82 | 81 | ||
| 83 | // Launch network task | 82 | // Launch network task |
| 84 | unwrap!(spawner.spawn(net_task(&stack))); | 83 | unwrap!(spawner.spawn(net_task(runner))); |
| 85 | 84 | ||
| 86 | info!("Waiting for DHCP..."); | 85 | info!("Waiting for DHCP..."); |
| 87 | let cfg = wait_for_config(stack).await; | 86 | let cfg = wait_for_config(stack).await; |
| @@ -89,12 +88,12 @@ async fn main(spawner: Spawner) { | |||
| 89 | info!("IP address: {:?}", local_addr); | 88 | info!("IP address: {:?}", local_addr); |
| 90 | 89 | ||
| 91 | // Create two sockets listening to the same port, to handle simultaneous connections | 90 | // Create two sockets listening to the same port, to handle simultaneous connections |
| 92 | unwrap!(spawner.spawn(listen_task(&stack, 0, 1234))); | 91 | unwrap!(spawner.spawn(listen_task(stack, 0, 1234))); |
| 93 | unwrap!(spawner.spawn(listen_task(&stack, 1, 1234))); | 92 | unwrap!(spawner.spawn(listen_task(stack, 1, 1234))); |
| 94 | } | 93 | } |
| 95 | 94 | ||
| 96 | #[embassy_executor::task(pool_size = 2)] | 95 | #[embassy_executor::task(pool_size = 2)] |
| 97 | async fn listen_task(stack: &'static Stack<Device<'static>>, id: u8, port: u16) { | 96 | async fn listen_task(stack: Stack<'static>, id: u8, port: u16) { |
| 98 | let mut rx_buffer = [0; 4096]; | 97 | let mut rx_buffer = [0; 4096]; |
| 99 | let mut tx_buffer = [0; 4096]; | 98 | let mut tx_buffer = [0; 4096]; |
| 100 | let mut buf = [0; 4096]; | 99 | let mut buf = [0; 4096]; |
| @@ -131,7 +130,7 @@ async fn listen_task(stack: &'static Stack<Device<'static>>, id: u8, port: u16) | |||
| 131 | } | 130 | } |
| 132 | } | 131 | } |
| 133 | 132 | ||
| 134 | async fn wait_for_config(stack: &'static Stack<Device<'static>>) -> embassy_net::StaticConfigV4 { | 133 | async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { |
| 135 | loop { | 134 | loop { |
| 136 | if let Some(config) = stack.config_v4() { | 135 | if let Some(config) = stack.config_v4() { |
| 137 | return config.clone(); | 136 | return config.clone(); |
diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index 8e96a114c..d66a43a88 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs | |||
| @@ -38,8 +38,8 @@ async fn ethernet_task( | |||
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | #[embassy_executor::task] | 40 | #[embassy_executor::task] |
| 41 | async fn net_task(stack: &'static Stack<Device<'static>>) -> ! { | 41 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { |
| 42 | stack.run().await | 42 | runner.run().await |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | #[embassy_executor::main] | 45 | #[embassy_executor::main] |
| @@ -74,17 +74,16 @@ async fn main(spawner: Spawner) { | |||
| 74 | let seed = rng.next_u64(); | 74 | let seed = rng.next_u64(); |
| 75 | 75 | ||
| 76 | // Init network stack | 76 | // Init network stack |
| 77 | static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new(); | ||
| 78 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 77 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 79 | let stack = &*STACK.init(Stack::new( | 78 | let (stack, runner) = embassy_net::new( |
| 80 | device, | 79 | device, |
| 81 | embassy_net::Config::dhcpv4(Default::default()), | 80 | embassy_net::Config::dhcpv4(Default::default()), |
| 82 | RESOURCES.init(StackResources::new()), | 81 | RESOURCES.init(StackResources::new()), |
| 83 | seed, | 82 | seed, |
| 84 | )); | 83 | ); |
| 85 | 84 | ||
| 86 | // Launch network task | 85 | // Launch network task |
| 87 | unwrap!(spawner.spawn(net_task(&stack))); | 86 | unwrap!(spawner.spawn(net_task(runner))); |
| 88 | 87 | ||
| 89 | info!("Waiting for DHCP..."); | 88 | info!("Waiting for DHCP..."); |
| 90 | let cfg = wait_for_config(stack).await; | 89 | let cfg = wait_for_config(stack).await; |
| @@ -119,7 +118,7 @@ async fn main(spawner: Spawner) { | |||
| 119 | } | 118 | } |
| 120 | } | 119 | } |
| 121 | 120 | ||
| 122 | async fn wait_for_config(stack: &'static Stack<Device<'static>>) -> embassy_net::StaticConfigV4 { | 121 | async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { |
| 123 | loop { | 122 | loop { |
| 124 | if let Some(config) = stack.config_v4() { | 123 | if let Some(config) = stack.config_v4() { |
| 125 | return config.clone(); | 124 | return config.clone(); |
diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index 40736bf3c..97d9bd4c9 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs | |||
| @@ -37,8 +37,8 @@ async fn ethernet_task( | |||
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | #[embassy_executor::task] | 39 | #[embassy_executor::task] |
| 40 | async fn net_task(stack: &'static Stack<Device<'static>>) -> ! { | 40 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { |
| 41 | stack.run().await | 41 | runner.run().await |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | #[embassy_executor::main] | 44 | #[embassy_executor::main] |
| @@ -73,17 +73,16 @@ async fn main(spawner: Spawner) { | |||
| 73 | let seed = rng.next_u64(); | 73 | let seed = rng.next_u64(); |
| 74 | 74 | ||
| 75 | // Init network stack | 75 | // Init network stack |
| 76 | static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new(); | ||
| 77 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 76 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 78 | let stack = &*STACK.init(Stack::new( | 77 | let (stack, runner) = embassy_net::new( |
| 79 | device, | 78 | device, |
| 80 | embassy_net::Config::dhcpv4(Default::default()), | 79 | embassy_net::Config::dhcpv4(Default::default()), |
| 81 | RESOURCES.init(StackResources::new()), | 80 | RESOURCES.init(StackResources::new()), |
| 82 | seed, | 81 | seed, |
| 83 | )); | 82 | ); |
| 84 | 83 | ||
| 85 | // Launch network task | 84 | // Launch network task |
| 86 | unwrap!(spawner.spawn(net_task(&stack))); | 85 | unwrap!(spawner.spawn(net_task(runner))); |
| 87 | 86 | ||
| 88 | info!("Waiting for DHCP..."); | 87 | info!("Waiting for DHCP..."); |
| 89 | let cfg = wait_for_config(stack).await; | 88 | let cfg = wait_for_config(stack).await; |
| @@ -128,7 +127,7 @@ async fn main(spawner: Spawner) { | |||
| 128 | } | 127 | } |
| 129 | } | 128 | } |
| 130 | 129 | ||
| 131 | async fn wait_for_config(stack: &'static Stack<Device<'static>>) -> embassy_net::StaticConfigV4 { | 130 | async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { |
| 132 | loop { | 131 | loop { |
| 133 | if let Some(config) = stack.config_v4() { | 132 | if let Some(config) = stack.config_v4() { |
| 134 | return config.clone(); | 133 | return config.clone(); |
diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index c79f01538..b1b5f9758 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs | |||
| @@ -36,8 +36,8 @@ async fn ethernet_task( | |||
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | #[embassy_executor::task] | 38 | #[embassy_executor::task] |
| 39 | async fn net_task(stack: &'static Stack<Device<'static>>) -> ! { | 39 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { |
| 40 | stack.run().await | 40 | runner.run().await |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | #[embassy_executor::main] | 43 | #[embassy_executor::main] |
| @@ -71,17 +71,16 @@ async fn main(spawner: Spawner) { | |||
| 71 | let seed = rng.next_u64(); | 71 | let seed = rng.next_u64(); |
| 72 | 72 | ||
| 73 | // Init network stack | 73 | // Init network stack |
| 74 | static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new(); | ||
| 75 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 74 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 76 | let stack = &*STACK.init(Stack::new( | 75 | let (stack, runner) = embassy_net::new( |
| 77 | device, | 76 | device, |
| 78 | embassy_net::Config::dhcpv4(Default::default()), | 77 | embassy_net::Config::dhcpv4(Default::default()), |
| 79 | RESOURCES.init(StackResources::new()), | 78 | RESOURCES.init(StackResources::new()), |
| 80 | seed, | 79 | seed, |
| 81 | )); | 80 | ); |
| 82 | 81 | ||
| 83 | // Launch network task | 82 | // Launch network task |
| 84 | unwrap!(spawner.spawn(net_task(&stack))); | 83 | unwrap!(spawner.spawn(net_task(runner))); |
| 85 | 84 | ||
| 86 | info!("Waiting for DHCP..."); | 85 | info!("Waiting for DHCP..."); |
| 87 | let cfg = wait_for_config(stack).await; | 86 | let cfg = wait_for_config(stack).await; |
| @@ -108,7 +107,7 @@ async fn main(spawner: Spawner) { | |||
| 108 | } | 107 | } |
| 109 | } | 108 | } |
| 110 | 109 | ||
| 111 | async fn wait_for_config(stack: &'static Stack<Device<'static>>) -> embassy_net::StaticConfigV4 { | 110 | async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { |
| 112 | loop { | 111 | loop { |
| 113 | if let Some(config) = stack.config_v4() { | 112 | if let Some(config) = stack.config_v4() { |
| 114 | return config.clone(); | 113 | return config.clone(); |
diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 03c510f37..9a15125d4 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_net::tcp::TcpSocket; | 10 | use embassy_net::tcp::TcpSocket; |
| 11 | use embassy_net::{Stack, StackResources}; | 11 | use embassy_net::StackResources; |
| 12 | use embassy_rp::clocks::RoscRng; | 12 | use embassy_rp::clocks::RoscRng; |
| 13 | use embassy_rp::peripherals::USB; | 13 | use embassy_rp::peripherals::USB; |
| 14 | use embassy_rp::usb::{Driver, InterruptHandler}; | 14 | use embassy_rp::usb::{Driver, InterruptHandler}; |
| @@ -40,8 +40,8 @@ async fn usb_ncm_task(class: Runner<'static, MyDriver, MTU>) -> ! { | |||
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | #[embassy_executor::task] | 42 | #[embassy_executor::task] |
| 43 | async fn net_task(stack: &'static Stack<Device<'static, MTU>>) -> ! { | 43 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static, MTU>>) -> ! { |
| 44 | stack.run().await | 44 | runner.run().await |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | #[embassy_executor::main] | 47 | #[embassy_executor::main] |
| @@ -108,11 +108,10 @@ async fn main(spawner: Spawner) { | |||
| 108 | let seed = rng.next_u64(); | 108 | let seed = rng.next_u64(); |
| 109 | 109 | ||
| 110 | // Init network stack | 110 | // Init network stack |
| 111 | static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new(); | ||
| 112 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 111 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 113 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 112 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 114 | 113 | ||
| 115 | unwrap!(spawner.spawn(net_task(stack))); | 114 | unwrap!(spawner.spawn(net_task(runner))); |
| 116 | 115 | ||
| 117 | // And now we can use it! | 116 | // And now we can use it! |
| 118 | 117 | ||
diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index 00f404a9b..4c9651433 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs | |||
| @@ -11,7 +11,7 @@ use cyw43_pio::PioSpi; | |||
| 11 | use defmt::*; | 11 | use defmt::*; |
| 12 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 13 | use embassy_net::tcp::TcpSocket; | 13 | use embassy_net::tcp::TcpSocket; |
| 14 | use embassy_net::{Config, Stack, StackResources}; | 14 | use embassy_net::{Config, StackResources}; |
| 15 | use embassy_rp::bind_interrupts; | 15 | use embassy_rp::bind_interrupts; |
| 16 | use embassy_rp::clocks::RoscRng; | 16 | use embassy_rp::clocks::RoscRng; |
| 17 | use embassy_rp::gpio::{Level, Output}; | 17 | use embassy_rp::gpio::{Level, Output}; |
| @@ -33,8 +33,8 @@ async fn cyw43_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'stat | |||
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | #[embassy_executor::task] | 35 | #[embassy_executor::task] |
| 36 | async fn net_task(stack: &'static Stack<cyw43::NetDriver<'static>>) -> ! { | 36 | async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'static>>) -> ! { |
| 37 | stack.run().await | 37 | runner.run().await |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | #[embassy_executor::main] | 40 | #[embassy_executor::main] |
| @@ -80,16 +80,10 @@ async fn main(spawner: Spawner) { | |||
| 80 | let seed = rng.next_u64(); | 80 | let seed = rng.next_u64(); |
| 81 | 81 | ||
| 82 | // Init network stack | 82 | // Init network stack |
| 83 | static STACK: StaticCell<Stack<cyw43::NetDriver<'static>>> = StaticCell::new(); | ||
| 84 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 83 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 85 | let stack = &*STACK.init(Stack::new( | 84 | let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed); |
| 86 | net_device, | 85 | |
| 87 | config, | 86 | unwrap!(spawner.spawn(net_task(runner))); |
| 88 | RESOURCES.init(StackResources::new()), | ||
| 89 | seed, | ||
| 90 | )); | ||
| 91 | |||
| 92 | unwrap!(spawner.spawn(net_task(stack))); | ||
| 93 | 87 | ||
| 94 | //control.start_ap_open("cyw43", 5).await; | 88 | //control.start_ap_open("cyw43", 5).await; |
| 95 | control.start_ap_wpa2("cyw43", "password", 5).await; | 89 | control.start_ap_wpa2("cyw43", "password", 5).await; |
diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs index ab3529112..434f0074c 100644 --- a/examples/rp/src/bin/wifi_scan.rs +++ b/examples/rp/src/bin/wifi_scan.rs | |||
| @@ -10,7 +10,6 @@ use core::str; | |||
| 10 | use cyw43_pio::PioSpi; | 10 | use cyw43_pio::PioSpi; |
| 11 | use defmt::*; | 11 | use defmt::*; |
| 12 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 13 | use embassy_net::Stack; | ||
| 14 | use embassy_rp::bind_interrupts; | 13 | use embassy_rp::bind_interrupts; |
| 15 | use embassy_rp::gpio::{Level, Output}; | 14 | use embassy_rp::gpio::{Level, Output}; |
| 16 | use embassy_rp::peripherals::{DMA_CH0, PIO0}; | 15 | use embassy_rp::peripherals::{DMA_CH0, PIO0}; |
| @@ -28,8 +27,8 @@ async fn cyw43_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'stat | |||
| 28 | } | 27 | } |
| 29 | 28 | ||
| 30 | #[embassy_executor::task] | 29 | #[embassy_executor::task] |
| 31 | async fn net_task(stack: &'static Stack<cyw43::NetDriver<'static>>) -> ! { | 30 | async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'static>>) -> ! { |
| 32 | stack.run().await | 31 | runner.run().await |
| 33 | } | 32 | } |
| 34 | 33 | ||
| 35 | #[embassy_executor::main] | 34 | #[embassy_executor::main] |
diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index b2950d98a..7bf546e01 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs | |||
| @@ -12,7 +12,7 @@ use cyw43_pio::PioSpi; | |||
| 12 | use defmt::*; | 12 | use defmt::*; |
| 13 | use embassy_executor::Spawner; | 13 | use embassy_executor::Spawner; |
| 14 | use embassy_net::tcp::TcpSocket; | 14 | use embassy_net::tcp::TcpSocket; |
| 15 | use embassy_net::{Config, Stack, StackResources}; | 15 | use embassy_net::{Config, StackResources}; |
| 16 | use embassy_rp::bind_interrupts; | 16 | use embassy_rp::bind_interrupts; |
| 17 | use embassy_rp::clocks::RoscRng; | 17 | use embassy_rp::clocks::RoscRng; |
| 18 | use embassy_rp::gpio::{Level, Output}; | 18 | use embassy_rp::gpio::{Level, Output}; |
| @@ -37,8 +37,8 @@ async fn cyw43_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'stat | |||
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | #[embassy_executor::task] | 39 | #[embassy_executor::task] |
| 40 | async fn net_task(stack: &'static Stack<cyw43::NetDriver<'static>>) -> ! { | 40 | async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'static>>) -> ! { |
| 41 | stack.run().await | 41 | runner.run().await |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | #[embassy_executor::main] | 44 | #[embassy_executor::main] |
| @@ -84,16 +84,10 @@ async fn main(spawner: Spawner) { | |||
| 84 | let seed = rng.next_u64(); | 84 | let seed = rng.next_u64(); |
| 85 | 85 | ||
| 86 | // Init network stack | 86 | // Init network stack |
| 87 | static STACK: StaticCell<Stack<cyw43::NetDriver<'static>>> = StaticCell::new(); | ||
| 88 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 87 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 89 | let stack = &*STACK.init(Stack::new( | 88 | let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed); |
| 90 | net_device, | 89 | |
| 91 | config, | 90 | unwrap!(spawner.spawn(net_task(runner))); |
| 92 | RESOURCES.init(StackResources::new()), | ||
| 93 | seed, | ||
| 94 | )); | ||
| 95 | |||
| 96 | unwrap!(spawner.spawn(net_task(stack))); | ||
| 97 | 91 | ||
| 98 | loop { | 92 | loop { |
| 99 | match control | 93 | match control |
diff --git a/examples/rp/src/bin/wifi_webrequest.rs b/examples/rp/src/bin/wifi_webrequest.rs index b43be8905..1ae909917 100644 --- a/examples/rp/src/bin/wifi_webrequest.rs +++ b/examples/rp/src/bin/wifi_webrequest.rs | |||
| @@ -13,7 +13,7 @@ use defmt::*; | |||
| 13 | use embassy_executor::Spawner; | 13 | use embassy_executor::Spawner; |
| 14 | use embassy_net::dns::DnsSocket; | 14 | use embassy_net::dns::DnsSocket; |
| 15 | use embassy_net::tcp::client::{TcpClient, TcpClientState}; | 15 | use embassy_net::tcp::client::{TcpClient, TcpClientState}; |
| 16 | use embassy_net::{Config, Stack, StackResources}; | 16 | use embassy_net::{Config, StackResources}; |
| 17 | use embassy_rp::bind_interrupts; | 17 | use embassy_rp::bind_interrupts; |
| 18 | use embassy_rp::clocks::RoscRng; | 18 | use embassy_rp::clocks::RoscRng; |
| 19 | use embassy_rp::gpio::{Level, Output}; | 19 | use embassy_rp::gpio::{Level, Output}; |
| @@ -40,8 +40,8 @@ async fn cyw43_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'stat | |||
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | #[embassy_executor::task] | 42 | #[embassy_executor::task] |
| 43 | async fn net_task(stack: &'static Stack<cyw43::NetDriver<'static>>) -> ! { | 43 | async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'static>>) -> ! { |
| 44 | stack.run().await | 44 | runner.run().await |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | #[embassy_executor::main] | 47 | #[embassy_executor::main] |
| @@ -87,16 +87,10 @@ async fn main(spawner: Spawner) { | |||
| 87 | let seed = rng.next_u64(); | 87 | let seed = rng.next_u64(); |
| 88 | 88 | ||
| 89 | // Init network stack | 89 | // Init network stack |
| 90 | static STACK: StaticCell<Stack<cyw43::NetDriver<'static>>> = StaticCell::new(); | ||
| 91 | static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new(); | 90 | static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new(); |
| 92 | let stack = &*STACK.init(Stack::new( | 91 | let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed); |
| 93 | net_device, | 92 | |
| 94 | config, | 93 | unwrap!(spawner.spawn(net_task(runner))); |
| 95 | RESOURCES.init(StackResources::new()), | ||
| 96 | seed, | ||
| 97 | )); | ||
| 98 | |||
| 99 | unwrap!(spawner.spawn(net_task(stack))); | ||
| 100 | 94 | ||
| 101 | loop { | 95 | loop { |
| 102 | match control | 96 | match control |
diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs index 310e7264d..cefa5448c 100644 --- a/examples/std/src/bin/net.rs +++ b/examples/std/src/bin/net.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | use clap::Parser; | 1 | use clap::Parser; |
| 2 | use embassy_executor::{Executor, Spawner}; | 2 | use embassy_executor::{Executor, Spawner}; |
| 3 | use embassy_net::tcp::TcpSocket; | 3 | use embassy_net::tcp::TcpSocket; |
| 4 | use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; | 4 | use embassy_net::{Config, Ipv4Address, Ipv4Cidr, StackResources}; |
| 5 | use embassy_net_tuntap::TunTapDevice; | 5 | use embassy_net_tuntap::TunTapDevice; |
| 6 | use embassy_time::Duration; | 6 | use embassy_time::Duration; |
| 7 | use embedded_io_async::Write; | 7 | use embedded_io_async::Write; |
| @@ -22,8 +22,8 @@ struct Opts { | |||
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | #[embassy_executor::task] | 24 | #[embassy_executor::task] |
| 25 | async fn net_task(stack: &'static Stack<TunTapDevice>) -> ! { | 25 | async fn net_task(mut runner: embassy_net::Runner<'static, TunTapDevice>) -> ! { |
| 26 | stack.run().await | 26 | runner.run().await |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | #[embassy_executor::task] | 29 | #[embassy_executor::task] |
| @@ -50,12 +50,11 @@ async fn main_task(spawner: Spawner) { | |||
| 50 | let seed = u64::from_le_bytes(seed); | 50 | let seed = u64::from_le_bytes(seed); |
| 51 | 51 | ||
| 52 | // Init network stack | 52 | // Init network stack |
| 53 | static STACK: StaticCell<Stack<TunTapDevice>> = StaticCell::new(); | ||
| 54 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 53 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 55 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 54 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 56 | 55 | ||
| 57 | // Launch network task | 56 | // Launch network task |
| 58 | spawner.spawn(net_task(stack)).unwrap(); | 57 | spawner.spawn(net_task(runner)).unwrap(); |
| 59 | 58 | ||
| 60 | // Then we can use it! | 59 | // Then we can use it! |
| 61 | let mut rx_buffer = [0; 4096]; | 60 | let mut rx_buffer = [0; 4096]; |
diff --git a/examples/std/src/bin/net_dns.rs b/examples/std/src/bin/net_dns.rs index c9615ef35..a42c5dbb7 100644 --- a/examples/std/src/bin/net_dns.rs +++ b/examples/std/src/bin/net_dns.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | use clap::Parser; | 1 | use clap::Parser; |
| 2 | use embassy_executor::{Executor, Spawner}; | 2 | use embassy_executor::{Executor, Spawner}; |
| 3 | use embassy_net::dns::DnsQueryType; | 3 | use embassy_net::dns::DnsQueryType; |
| 4 | use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; | 4 | use embassy_net::{Config, Ipv4Address, Ipv4Cidr, StackResources}; |
| 5 | use embassy_net_tuntap::TunTapDevice; | 5 | use embassy_net_tuntap::TunTapDevice; |
| 6 | use heapless::Vec; | 6 | use heapless::Vec; |
| 7 | use log::*; | 7 | use log::*; |
| @@ -20,8 +20,8 @@ struct Opts { | |||
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | #[embassy_executor::task] | 22 | #[embassy_executor::task] |
| 23 | async fn net_task(stack: &'static Stack<TunTapDevice>) -> ! { | 23 | async fn net_task(mut runner: embassy_net::Runner<'static, TunTapDevice>) -> ! { |
| 24 | stack.run().await | 24 | runner.run().await |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | #[embassy_executor::task] | 27 | #[embassy_executor::task] |
| @@ -49,12 +49,11 @@ async fn main_task(spawner: Spawner) { | |||
| 49 | let seed = u64::from_le_bytes(seed); | 49 | let seed = u64::from_le_bytes(seed); |
| 50 | 50 | ||
| 51 | // Init network stack | 51 | // Init network stack |
| 52 | static STACK: StaticCell<Stack<TunTapDevice>> = StaticCell::new(); | ||
| 53 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 52 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 54 | let stack: &Stack<_> = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 53 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 55 | 54 | ||
| 56 | // Launch network task | 55 | // Launch network task |
| 57 | spawner.spawn(net_task(stack)).unwrap(); | 56 | spawner.spawn(net_task(runner)).unwrap(); |
| 58 | 57 | ||
| 59 | let host = "example.com"; | 58 | let host = "example.com"; |
| 60 | info!("querying host {:?}...", host); | 59 | info!("querying host {:?}...", host); |
diff --git a/examples/std/src/bin/net_ppp.rs b/examples/std/src/bin/net_ppp.rs index c5c27c4a3..7d0f1327f 100644 --- a/examples/std/src/bin/net_ppp.rs +++ b/examples/std/src/bin/net_ppp.rs | |||
| @@ -37,16 +37,12 @@ struct Opts { | |||
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | #[embassy_executor::task] | 39 | #[embassy_executor::task] |
| 40 | async fn net_task(stack: &'static Stack<embassy_net_ppp::Device<'static>>) -> ! { | 40 | async fn net_task(mut runner: embassy_net::Runner<'static, embassy_net_ppp::Device<'static>>) -> ! { |
| 41 | stack.run().await | 41 | runner.run().await |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | #[embassy_executor::task] | 44 | #[embassy_executor::task] |
| 45 | async fn ppp_task( | 45 | async fn ppp_task(stack: Stack<'static>, mut runner: Runner<'static>, port: SerialPort) -> ! { |
| 46 | stack: &'static Stack<embassy_net_ppp::Device<'static>>, | ||
| 47 | mut runner: Runner<'static>, | ||
| 48 | port: SerialPort, | ||
| 49 | ) -> ! { | ||
| 50 | let port = Async::new(port).unwrap(); | 46 | let port = Async::new(port).unwrap(); |
| 51 | let port = BufReader::new(port); | 47 | let port = BufReader::new(port); |
| 52 | let port = adapter::FromFutures::new(port); | 48 | let port = adapter::FromFutures::new(port); |
| @@ -97,17 +93,16 @@ async fn main_task(spawner: Spawner) { | |||
| 97 | let seed = u64::from_le_bytes(seed); | 93 | let seed = u64::from_le_bytes(seed); |
| 98 | 94 | ||
| 99 | // Init network stack | 95 | // Init network stack |
| 100 | static STACK: StaticCell<Stack<embassy_net_ppp::Device<'static>>> = StaticCell::new(); | ||
| 101 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 96 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 102 | let stack = &*STACK.init(Stack::new( | 97 | let (stack, net_runner) = embassy_net::new( |
| 103 | device, | 98 | device, |
| 104 | Config::default(), // don't configure IP yet | 99 | Config::default(), // don't configure IP yet |
| 105 | RESOURCES.init(StackResources::new()), | 100 | RESOURCES.init(StackResources::new()), |
| 106 | seed, | 101 | seed, |
| 107 | )); | 102 | ); |
| 108 | 103 | ||
| 109 | // Launch network task | 104 | // Launch network task |
| 110 | spawner.spawn(net_task(stack)).unwrap(); | 105 | spawner.spawn(net_task(net_runner)).unwrap(); |
| 111 | spawner.spawn(ppp_task(stack, runner, port)).unwrap(); | 106 | spawner.spawn(ppp_task(stack, runner, port)).unwrap(); |
| 112 | 107 | ||
| 113 | // Then we can use it! | 108 | // Then we can use it! |
diff --git a/examples/std/src/bin/net_udp.rs b/examples/std/src/bin/net_udp.rs index b2ba4915a..02d4d3efb 100644 --- a/examples/std/src/bin/net_udp.rs +++ b/examples/std/src/bin/net_udp.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | use clap::Parser; | 1 | use clap::Parser; |
| 2 | use embassy_executor::{Executor, Spawner}; | 2 | use embassy_executor::{Executor, Spawner}; |
| 3 | use embassy_net::udp::{PacketMetadata, UdpSocket}; | 3 | use embassy_net::udp::{PacketMetadata, UdpSocket}; |
| 4 | use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; | 4 | use embassy_net::{Config, Ipv4Address, Ipv4Cidr, StackResources}; |
| 5 | use embassy_net_tuntap::TunTapDevice; | 5 | use embassy_net_tuntap::TunTapDevice; |
| 6 | use heapless::Vec; | 6 | use heapless::Vec; |
| 7 | use log::*; | 7 | use log::*; |
| @@ -20,8 +20,8 @@ struct Opts { | |||
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | #[embassy_executor::task] | 22 | #[embassy_executor::task] |
| 23 | async fn net_task(stack: &'static Stack<TunTapDevice>) -> ! { | 23 | async fn net_task(mut runner: embassy_net::Runner<'static, TunTapDevice>) -> ! { |
| 24 | stack.run().await | 24 | runner.run().await |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | #[embassy_executor::task] | 27 | #[embassy_executor::task] |
| @@ -48,12 +48,11 @@ async fn main_task(spawner: Spawner) { | |||
| 48 | let seed = u64::from_le_bytes(seed); | 48 | let seed = u64::from_le_bytes(seed); |
| 49 | 49 | ||
| 50 | // Init network stack | 50 | // Init network stack |
| 51 | static STACK: StaticCell<Stack<TunTapDevice>> = StaticCell::new(); | ||
| 52 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 51 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 53 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 52 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 54 | 53 | ||
| 55 | // Launch network task | 54 | // Launch network task |
| 56 | spawner.spawn(net_task(stack)).unwrap(); | 55 | spawner.spawn(net_task(runner)).unwrap(); |
| 57 | 56 | ||
| 58 | // Then we can use it! | 57 | // Then we can use it! |
| 59 | let mut rx_meta = [PacketMetadata::EMPTY; 16]; | 58 | let mut rx_meta = [PacketMetadata::EMPTY; 16]; |
diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs index 39b29a449..5d36b739d 100644 --- a/examples/std/src/bin/tcp_accept.rs +++ b/examples/std/src/bin/tcp_accept.rs | |||
| @@ -3,7 +3,7 @@ use core::fmt::Write as _; | |||
| 3 | use clap::Parser; | 3 | use clap::Parser; |
| 4 | use embassy_executor::{Executor, Spawner}; | 4 | use embassy_executor::{Executor, Spawner}; |
| 5 | use embassy_net::tcp::TcpSocket; | 5 | use embassy_net::tcp::TcpSocket; |
| 6 | use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; | 6 | use embassy_net::{Config, Ipv4Address, Ipv4Cidr, StackResources}; |
| 7 | use embassy_net_tuntap::TunTapDevice; | 7 | use embassy_net_tuntap::TunTapDevice; |
| 8 | use embassy_time::{Duration, Timer}; | 8 | use embassy_time::{Duration, Timer}; |
| 9 | use embedded_io_async::Write as _; | 9 | use embedded_io_async::Write as _; |
| @@ -24,8 +24,8 @@ struct Opts { | |||
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | #[embassy_executor::task] | 26 | #[embassy_executor::task] |
| 27 | async fn net_task(stack: &'static Stack<TunTapDevice>) -> ! { | 27 | async fn net_task(mut runner: embassy_net::Runner<'static, TunTapDevice>) -> ! { |
| 28 | stack.run().await | 28 | runner.run().await |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | #[derive(Default)] | 31 | #[derive(Default)] |
| @@ -62,12 +62,11 @@ async fn main_task(spawner: Spawner) { | |||
| 62 | let seed = u64::from_le_bytes(seed); | 62 | let seed = u64::from_le_bytes(seed); |
| 63 | 63 | ||
| 64 | // Init network stack | 64 | // Init network stack |
| 65 | static STACK: StaticCell<Stack<TunTapDevice>> = StaticCell::new(); | ||
| 66 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 65 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 67 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 66 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 68 | 67 | ||
| 69 | // Launch network task | 68 | // Launch network task |
| 70 | spawner.spawn(net_task(stack)).unwrap(); | 69 | spawner.spawn(net_task(runner)).unwrap(); |
| 71 | 70 | ||
| 72 | // Then we can use it! | 71 | // Then we can use it! |
| 73 | let mut rx_buffer = [0; 4096]; | 72 | let mut rx_buffer = [0; 4096]; |
diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs index 9388c64bf..baed96449 100644 --- a/examples/stm32f4/src/bin/eth.rs +++ b/examples/stm32f4/src/bin/eth.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | 6 | use embassy_net::tcp::TcpSocket; |
| 7 | use embassy_net::{Ipv4Address, Stack, StackResources}; | 7 | use embassy_net::{Ipv4Address, StackResources}; |
| 8 | use embassy_stm32::eth::generic_smi::GenericSMI; | 8 | use embassy_stm32::eth::generic_smi::GenericSMI; |
| 9 | use embassy_stm32::eth::{Ethernet, PacketQueue}; | 9 | use embassy_stm32::eth::{Ethernet, PacketQueue}; |
| 10 | use embassy_stm32::peripherals::ETH; | 10 | use embassy_stm32::peripherals::ETH; |
| @@ -24,8 +24,8 @@ bind_interrupts!(struct Irqs { | |||
| 24 | type Device = Ethernet<'static, ETH, GenericSMI>; | 24 | type Device = Ethernet<'static, ETH, GenericSMI>; |
| 25 | 25 | ||
| 26 | #[embassy_executor::task] | 26 | #[embassy_executor::task] |
| 27 | async fn net_task(stack: &'static Stack<Device>) -> ! { | 27 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { |
| 28 | stack.run().await | 28 | runner.run().await |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | #[embassy_executor::main] | 31 | #[embassy_executor::main] |
| @@ -88,12 +88,11 @@ async fn main(spawner: Spawner) -> ! { | |||
| 88 | //}); | 88 | //}); |
| 89 | 89 | ||
| 90 | // Init network stack | 90 | // Init network stack |
| 91 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | ||
| 92 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 91 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 93 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 92 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 94 | 93 | ||
| 95 | // Launch network task | 94 | // Launch network task |
| 96 | unwrap!(spawner.spawn(net_task(stack))); | 95 | unwrap!(spawner.spawn(net_task(runner))); |
| 97 | 96 | ||
| 98 | // Ensure DHCP configuration is up before trying connect | 97 | // Ensure DHCP configuration is up before trying connect |
| 99 | stack.wait_config_up().await; | 98 | stack.wait_config_up().await; |
| @@ -105,7 +104,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 105 | let mut tx_buffer = [0; 4096]; | 104 | let mut tx_buffer = [0; 4096]; |
| 106 | 105 | ||
| 107 | loop { | 106 | loop { |
| 108 | let mut socket = TcpSocket::new(&stack, &mut rx_buffer, &mut tx_buffer); | 107 | let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); |
| 109 | 108 | ||
| 110 | socket.set_timeout(Some(embassy_time::Duration::from_secs(10))); | 109 | socket.set_timeout(Some(embassy_time::Duration::from_secs(10))); |
| 111 | 110 | ||
diff --git a/examples/stm32f4/src/bin/eth_w5500.rs b/examples/stm32f4/src/bin/eth_w5500.rs index 5c3c6c3ba..6e6bef08c 100644 --- a/examples/stm32f4/src/bin/eth_w5500.rs +++ b/examples/stm32f4/src/bin/eth_w5500.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | 6 | use embassy_net::tcp::TcpSocket; |
| 7 | use embassy_net::{Ipv4Address, Stack, StackResources}; | 7 | use embassy_net::{Ipv4Address, StackResources}; |
| 8 | use embassy_net_wiznet::chip::W5500; | 8 | use embassy_net_wiznet::chip::W5500; |
| 9 | use embassy_net_wiznet::{Device, Runner, State}; | 9 | use embassy_net_wiznet::{Device, Runner, State}; |
| 10 | use embassy_stm32::exti::ExtiInput; | 10 | use embassy_stm32::exti::ExtiInput; |
| @@ -31,8 +31,8 @@ async fn ethernet_task(runner: Runner<'static, W5500, EthernetSPI, ExtiInput<'st | |||
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | #[embassy_executor::task] | 33 | #[embassy_executor::task] |
| 34 | async fn net_task(stack: &'static Stack<Device<'static>>) -> ! { | 34 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { |
| 35 | stack.run().await | 35 | runner.run().await |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | #[embassy_executor::main] | 38 | #[embassy_executor::main] |
| @@ -92,12 +92,11 @@ async fn main(spawner: Spawner) -> ! { | |||
| 92 | // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), | 92 | // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), |
| 93 | //}); | 93 | //}); |
| 94 | 94 | ||
| 95 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | ||
| 96 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 95 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 97 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 96 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 98 | 97 | ||
| 99 | // Launch network task | 98 | // Launch network task |
| 100 | unwrap!(spawner.spawn(net_task(stack))); | 99 | unwrap!(spawner.spawn(net_task(runner))); |
| 101 | 100 | ||
| 102 | // Ensure DHCP configuration is up before trying connect | 101 | // Ensure DHCP configuration is up before trying connect |
| 103 | stack.wait_config_up().await; | 102 | stack.wait_config_up().await; |
diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs index 94e51c338..a9504ec04 100644 --- a/examples/stm32f4/src/bin/usb_ethernet.rs +++ b/examples/stm32f4/src/bin/usb_ethernet.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | 6 | use embassy_net::tcp::TcpSocket; |
| 7 | use embassy_net::{Stack, StackResources}; | 7 | use embassy_net::StackResources; |
| 8 | use embassy_stm32::rng::{self, Rng}; | 8 | use embassy_stm32::rng::{self, Rng}; |
| 9 | use embassy_stm32::time::Hertz; | 9 | use embassy_stm32::time::Hertz; |
| 10 | use embassy_stm32::usb::Driver; | 10 | use embassy_stm32::usb::Driver; |
| @@ -31,8 +31,8 @@ async fn usb_ncm_task(class: Runner<'static, UsbDriver, MTU>) -> ! { | |||
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | #[embassy_executor::task] | 33 | #[embassy_executor::task] |
| 34 | async fn net_task(stack: &'static Stack<Device<'static, MTU>>) -> ! { | 34 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static, MTU>>) -> ! { |
| 35 | stack.run().await | 35 | runner.run().await |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | bind_interrupts!(struct Irqs { | 38 | bind_interrupts!(struct Irqs { |
| @@ -144,11 +144,10 @@ async fn main(spawner: Spawner) { | |||
| 144 | let seed = u64::from_le_bytes(seed); | 144 | let seed = u64::from_le_bytes(seed); |
| 145 | 145 | ||
| 146 | // Init network stack | 146 | // Init network stack |
| 147 | static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new(); | ||
| 148 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 147 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 149 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 148 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 150 | 149 | ||
| 151 | unwrap!(spawner.spawn(net_task(stack))); | 150 | unwrap!(spawner.spawn(net_task(runner))); |
| 152 | 151 | ||
| 153 | // And now we can use it! | 152 | // And now we can use it! |
| 154 | 153 | ||
diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index 2fd10c8fb..1f1eadf37 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | 6 | use embassy_net::tcp::TcpSocket; |
| 7 | use embassy_net::{Ipv4Address, Stack, StackResources}; | 7 | use embassy_net::{Ipv4Address, StackResources}; |
| 8 | use embassy_stm32::eth::generic_smi::GenericSMI; | 8 | use embassy_stm32::eth::generic_smi::GenericSMI; |
| 9 | use embassy_stm32::eth::{Ethernet, PacketQueue}; | 9 | use embassy_stm32::eth::{Ethernet, PacketQueue}; |
| 10 | use embassy_stm32::peripherals::ETH; | 10 | use embassy_stm32::peripherals::ETH; |
| @@ -25,8 +25,8 @@ bind_interrupts!(struct Irqs { | |||
| 25 | type Device = Ethernet<'static, ETH, GenericSMI>; | 25 | type Device = Ethernet<'static, ETH, GenericSMI>; |
| 26 | 26 | ||
| 27 | #[embassy_executor::task] | 27 | #[embassy_executor::task] |
| 28 | async fn net_task(stack: &'static Stack<Device>) -> ! { | 28 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { |
| 29 | stack.run().await | 29 | runner.run().await |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | #[embassy_executor::main] | 32 | #[embassy_executor::main] |
| @@ -89,12 +89,11 @@ async fn main(spawner: Spawner) -> ! { | |||
| 89 | //}); | 89 | //}); |
| 90 | 90 | ||
| 91 | // Init network stack | 91 | // Init network stack |
| 92 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | ||
| 93 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 92 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 94 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 93 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 95 | 94 | ||
| 96 | // Launch network task | 95 | // Launch network task |
| 97 | unwrap!(spawner.spawn(net_task(stack))); | 96 | unwrap!(spawner.spawn(net_task(runner))); |
| 98 | 97 | ||
| 99 | // Ensure DHCP configuration is up before trying connect | 98 | // Ensure DHCP configuration is up before trying connect |
| 100 | stack.wait_config_up().await; | 99 | stack.wait_config_up().await; |
| @@ -106,7 +105,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 106 | let mut tx_buffer = [0; 4096]; | 105 | let mut tx_buffer = [0; 4096]; |
| 107 | 106 | ||
| 108 | loop { | 107 | loop { |
| 109 | let mut socket = TcpSocket::new(&stack, &mut rx_buffer, &mut tx_buffer); | 108 | let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); |
| 110 | 109 | ||
| 111 | socket.set_timeout(Some(embassy_time::Duration::from_secs(10))); | 110 | socket.set_timeout(Some(embassy_time::Duration::from_secs(10))); |
| 112 | 111 | ||
diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 65cfad8c9..eee1632f5 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | 6 | use embassy_net::tcp::TcpSocket; |
| 7 | use embassy_net::{Ipv4Address, Stack, StackResources}; | 7 | use embassy_net::{Ipv4Address, StackResources}; |
| 8 | use embassy_stm32::eth::generic_smi::GenericSMI; | 8 | use embassy_stm32::eth::generic_smi::GenericSMI; |
| 9 | use embassy_stm32::eth::{Ethernet, PacketQueue}; | 9 | use embassy_stm32::eth::{Ethernet, PacketQueue}; |
| 10 | use embassy_stm32::peripherals::ETH; | 10 | use embassy_stm32::peripherals::ETH; |
| @@ -28,8 +28,8 @@ bind_interrupts!(struct Irqs { | |||
| 28 | type Device = Ethernet<'static, ETH, GenericSMI>; | 28 | type Device = Ethernet<'static, ETH, GenericSMI>; |
| 29 | 29 | ||
| 30 | #[embassy_executor::task] | 30 | #[embassy_executor::task] |
| 31 | async fn net_task(stack: &'static Stack<Device>) -> ! { | 31 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { |
| 32 | stack.run().await | 32 | runner.run().await |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | #[embassy_executor::main] | 35 | #[embassy_executor::main] |
| @@ -92,12 +92,11 @@ async fn main(spawner: Spawner) -> ! { | |||
| 92 | //}); | 92 | //}); |
| 93 | 93 | ||
| 94 | // Init network stack | 94 | // Init network stack |
| 95 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | ||
| 96 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 95 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 97 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 96 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 98 | 97 | ||
| 99 | // Launch network task | 98 | // Launch network task |
| 100 | unwrap!(spawner.spawn(net_task(&stack))); | 99 | unwrap!(spawner.spawn(net_task(runner))); |
| 101 | 100 | ||
| 102 | // Ensure DHCP configuration is up before trying connect | 101 | // Ensure DHCP configuration is up before trying connect |
| 103 | stack.wait_config_up().await; | 102 | stack.wait_config_up().await; |
| @@ -109,7 +108,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 109 | let mut tx_buffer = [0; 1024]; | 108 | let mut tx_buffer = [0; 1024]; |
| 110 | 109 | ||
| 111 | loop { | 110 | loop { |
| 112 | let mut socket = TcpSocket::new(&stack, &mut rx_buffer, &mut tx_buffer); | 111 | let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); |
| 113 | 112 | ||
| 114 | socket.set_timeout(Some(embassy_time::Duration::from_secs(10))); | 113 | socket.set_timeout(Some(embassy_time::Duration::from_secs(10))); |
| 115 | 114 | ||
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index b2f8ed91e..ec3f2c000 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | 6 | use embassy_net::tcp::TcpSocket; |
| 7 | use embassy_net::{Ipv4Address, Stack, StackResources}; | 7 | use embassy_net::{Ipv4Address, StackResources}; |
| 8 | use embassy_stm32::eth::generic_smi::GenericSMI; | 8 | use embassy_stm32::eth::generic_smi::GenericSMI; |
| 9 | use embassy_stm32::eth::{Ethernet, PacketQueue}; | 9 | use embassy_stm32::eth::{Ethernet, PacketQueue}; |
| 10 | use embassy_stm32::peripherals::ETH; | 10 | use embassy_stm32::peripherals::ETH; |
| @@ -24,8 +24,8 @@ bind_interrupts!(struct Irqs { | |||
| 24 | type Device = Ethernet<'static, ETH, GenericSMI>; | 24 | type Device = Ethernet<'static, ETH, GenericSMI>; |
| 25 | 25 | ||
| 26 | #[embassy_executor::task] | 26 | #[embassy_executor::task] |
| 27 | async fn net_task(stack: &'static Stack<Device>) -> ! { | 27 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { |
| 28 | stack.run().await | 28 | runner.run().await |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | #[embassy_executor::main] | 31 | #[embassy_executor::main] |
| @@ -91,12 +91,11 @@ async fn main(spawner: Spawner) -> ! { | |||
| 91 | //}); | 91 | //}); |
| 92 | 92 | ||
| 93 | // Init network stack | 93 | // Init network stack |
| 94 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | ||
| 95 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 94 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 96 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 95 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 97 | 96 | ||
| 98 | // Launch network task | 97 | // Launch network task |
| 99 | unwrap!(spawner.spawn(net_task(&stack))); | 98 | unwrap!(spawner.spawn(net_task(runner))); |
| 100 | 99 | ||
| 101 | // Ensure DHCP configuration is up before trying connect | 100 | // Ensure DHCP configuration is up before trying connect |
| 102 | stack.wait_config_up().await; | 101 | stack.wait_config_up().await; |
| @@ -108,7 +107,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 108 | let mut tx_buffer = [0; 1024]; | 107 | let mut tx_buffer = [0; 1024]; |
| 109 | 108 | ||
| 110 | loop { | 109 | loop { |
| 111 | let mut socket = TcpSocket::new(&stack, &mut rx_buffer, &mut tx_buffer); | 110 | let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); |
| 112 | 111 | ||
| 113 | socket.set_timeout(Some(embassy_time::Duration::from_secs(10))); | 112 | socket.set_timeout(Some(embassy_time::Duration::from_secs(10))); |
| 114 | 113 | ||
diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 274c24ab1..24983ca85 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::client::{TcpClient, TcpClientState}; | 6 | use embassy_net::tcp::client::{TcpClient, TcpClientState}; |
| 7 | use embassy_net::{Stack, StackResources}; | 7 | use embassy_net::StackResources; |
| 8 | use embassy_stm32::eth::generic_smi::GenericSMI; | 8 | use embassy_stm32::eth::generic_smi::GenericSMI; |
| 9 | use embassy_stm32::eth::{Ethernet, PacketQueue}; | 9 | use embassy_stm32::eth::{Ethernet, PacketQueue}; |
| 10 | use embassy_stm32::peripherals::ETH; | 10 | use embassy_stm32::peripherals::ETH; |
| @@ -25,8 +25,8 @@ bind_interrupts!(struct Irqs { | |||
| 25 | type Device = Ethernet<'static, ETH, GenericSMI>; | 25 | type Device = Ethernet<'static, ETH, GenericSMI>; |
| 26 | 26 | ||
| 27 | #[embassy_executor::task] | 27 | #[embassy_executor::task] |
| 28 | async fn net_task(stack: &'static Stack<Device>) -> ! { | 28 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { |
| 29 | stack.run().await | 29 | runner.run().await |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | #[embassy_executor::main] | 32 | #[embassy_executor::main] |
| @@ -91,12 +91,11 @@ async fn main(spawner: Spawner) -> ! { | |||
| 91 | //}); | 91 | //}); |
| 92 | 92 | ||
| 93 | // Init network stack | 93 | // Init network stack |
| 94 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | ||
| 95 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 94 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 96 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 95 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 97 | 96 | ||
| 98 | // Launch network task | 97 | // Launch network task |
| 99 | unwrap!(spawner.spawn(net_task(stack))); | 98 | unwrap!(spawner.spawn(net_task(runner))); |
| 100 | 99 | ||
| 101 | // Ensure DHCP configuration is up before trying connect | 100 | // Ensure DHCP configuration is up before trying connect |
| 102 | stack.wait_config_up().await; | 101 | stack.wait_config_up().await; |
| @@ -104,7 +103,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 104 | info!("Network task initialized"); | 103 | info!("Network task initialized"); |
| 105 | 104 | ||
| 106 | let state: TcpClientState<1, 1024, 1024> = TcpClientState::new(); | 105 | let state: TcpClientState<1, 1024, 1024> = TcpClientState::new(); |
| 107 | let client = TcpClient::new(&stack, &state); | 106 | let client = TcpClient::new(stack, &state); |
| 108 | 107 | ||
| 109 | loop { | 108 | loop { |
| 110 | // You need to start a server on the host machine, for example: `nc -l 8000` | 109 | // You need to start a server on the host machine, for example: `nc -l 8000` |
diff --git a/examples/stm32h7/src/bin/eth_client_mii.rs b/examples/stm32h7/src/bin/eth_client_mii.rs index aa6544f41..768d85993 100644 --- a/examples/stm32h7/src/bin/eth_client_mii.rs +++ b/examples/stm32h7/src/bin/eth_client_mii.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::client::{TcpClient, TcpClientState}; | 6 | use embassy_net::tcp::client::{TcpClient, TcpClientState}; |
| 7 | use embassy_net::{Stack, StackResources}; | 7 | use embassy_net::StackResources; |
| 8 | use embassy_stm32::eth::generic_smi::GenericSMI; | 8 | use embassy_stm32::eth::generic_smi::GenericSMI; |
| 9 | use embassy_stm32::eth::{Ethernet, PacketQueue}; | 9 | use embassy_stm32::eth::{Ethernet, PacketQueue}; |
| 10 | use embassy_stm32::peripherals::ETH; | 10 | use embassy_stm32::peripherals::ETH; |
| @@ -25,8 +25,8 @@ bind_interrupts!(struct Irqs { | |||
| 25 | type Device = Ethernet<'static, ETH, GenericSMI>; | 25 | type Device = Ethernet<'static, ETH, GenericSMI>; |
| 26 | 26 | ||
| 27 | #[embassy_executor::task] | 27 | #[embassy_executor::task] |
| 28 | async fn net_task(stack: &'static Stack<Device>) -> ! { | 28 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { |
| 29 | stack.run().await | 29 | runner.run().await |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | #[embassy_executor::main] | 32 | #[embassy_executor::main] |
| @@ -97,12 +97,11 @@ async fn main(spawner: Spawner) -> ! { | |||
| 97 | //}); | 97 | //}); |
| 98 | 98 | ||
| 99 | // Init network stack | 99 | // Init network stack |
| 100 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | ||
| 101 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 100 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 102 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 101 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 103 | 102 | ||
| 104 | // Launch network task | 103 | // Launch network task |
| 105 | unwrap!(spawner.spawn(net_task(stack))); | 104 | unwrap!(spawner.spawn(net_task(runner))); |
| 106 | 105 | ||
| 107 | // Ensure DHCP configuration is up before trying connect | 106 | // Ensure DHCP configuration is up before trying connect |
| 108 | stack.wait_config_up().await; | 107 | stack.wait_config_up().await; |
| @@ -110,7 +109,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 110 | info!("Network task initialized"); | 109 | info!("Network task initialized"); |
| 111 | 110 | ||
| 112 | let state: TcpClientState<1, 1024, 1024> = TcpClientState::new(); | 111 | let state: TcpClientState<1, 1024, 1024> = TcpClientState::new(); |
| 113 | let client = TcpClient::new(&stack, &state); | 112 | let client = TcpClient::new(stack, &state); |
| 114 | 113 | ||
| 115 | loop { | 114 | loop { |
| 116 | // You need to start a server on the host machine, for example: `nc -l 8000` | 115 | // You need to start a server on the host machine, for example: `nc -l 8000` |
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index bd633cecb..be4270ada 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs | |||
| @@ -206,12 +206,11 @@ async fn main(spawner: Spawner) { | |||
| 206 | }; | 206 | }; |
| 207 | 207 | ||
| 208 | // Init network stack | 208 | // Init network stack |
| 209 | static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new(); | ||
| 210 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 209 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 211 | let stack = &*STACK.init(Stack::new(device, ip_cfg, RESOURCES.init(StackResources::new()), seed)); | 210 | let (stack, runner) = embassy_net::new(device, ip_cfg, RESOURCES.init(StackResources::new()), seed); |
| 212 | 211 | ||
| 213 | // Launch network task | 212 | // Launch network task |
| 214 | unwrap!(spawner.spawn(net_task(stack))); | 213 | unwrap!(spawner.spawn(net_task(runner))); |
| 215 | 214 | ||
| 216 | let cfg = wait_for_config(stack).await; | 215 | let cfg = wait_for_config(stack).await; |
| 217 | let local_addr = cfg.address.address(); | 216 | let local_addr = cfg.address.address(); |
| @@ -274,7 +273,7 @@ async fn main(spawner: Spawner) { | |||
| 274 | } | 273 | } |
| 275 | } | 274 | } |
| 276 | 275 | ||
| 277 | async fn wait_for_config(stack: &'static Stack<Device<'static>>) -> embassy_net::StaticConfigV4 { | 276 | async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { |
| 278 | loop { | 277 | loop { |
| 279 | if let Some(config) = stack.config_v4() { | 278 | if let Some(config) = stack.config_v4() { |
| 280 | return config; | 279 | return config; |
| @@ -323,8 +322,8 @@ async fn ethernet_task(runner: Runner<'static, SpeSpiCs, SpeInt, SpeRst>) -> ! { | |||
| 323 | } | 322 | } |
| 324 | 323 | ||
| 325 | #[embassy_executor::task] | 324 | #[embassy_executor::task] |
| 326 | async fn net_task(stack: &'static Stack<Device<'static>>) -> ! { | 325 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { |
| 327 | stack.run().await | 326 | runner.run().await |
| 328 | } | 327 | } |
| 329 | 328 | ||
| 330 | // same panicking *behavior* as `panic-probe` but doesn't print a panic message | 329 | // same panicking *behavior* as `panic-probe` but doesn't print a panic message |
diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs index d02bac91d..095d50c73 100644 --- a/examples/stm32l5/src/bin/usb_ethernet.rs +++ b/examples/stm32l5/src/bin/usb_ethernet.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | 6 | use embassy_net::tcp::TcpSocket; |
| 7 | use embassy_net::{Stack, StackResources}; | 7 | use embassy_net::StackResources; |
| 8 | use embassy_stm32::rng::Rng; | 8 | use embassy_stm32::rng::Rng; |
| 9 | use embassy_stm32::usb::Driver; | 9 | use embassy_stm32::usb::Driver; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, rng, usb, Config}; | 10 | use embassy_stm32::{bind_interrupts, peripherals, rng, usb, Config}; |
| @@ -36,8 +36,8 @@ async fn usb_ncm_task(class: Runner<'static, MyDriver, MTU>) -> ! { | |||
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | #[embassy_executor::task] | 38 | #[embassy_executor::task] |
| 39 | async fn net_task(stack: &'static Stack<Device<'static, MTU>>) -> ! { | 39 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static, MTU>>) -> ! { |
| 40 | stack.run().await | 40 | runner.run().await |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | #[embassy_executor::main] | 43 | #[embassy_executor::main] |
| @@ -121,11 +121,10 @@ async fn main(spawner: Spawner) { | |||
| 121 | let seed = rng.next_u64(); | 121 | let seed = rng.next_u64(); |
| 122 | 122 | ||
| 123 | // Init network stack | 123 | // Init network stack |
| 124 | static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new(); | ||
| 125 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 124 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 126 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 125 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 127 | 126 | ||
| 128 | unwrap!(spawner.spawn(net_task(stack))); | 127 | unwrap!(spawner.spawn(net_task(runner))); |
| 129 | 128 | ||
| 130 | // And now we can use it! | 129 | // And now we can use it! |
| 131 | 130 | ||
diff --git a/tests/nrf/src/bin/ethernet_enc28j60_perf.rs b/tests/nrf/src/bin/ethernet_enc28j60_perf.rs index 304754c0e..ed58627f1 100644 --- a/tests/nrf/src/bin/ethernet_enc28j60_perf.rs +++ b/tests/nrf/src/bin/ethernet_enc28j60_perf.rs | |||
| @@ -6,7 +6,7 @@ teleprobe_meta::timeout!(120); | |||
| 6 | 6 | ||
| 7 | use defmt::{info, unwrap}; | 7 | use defmt::{info, unwrap}; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_net::{Stack, StackResources}; | 9 | use embassy_net::StackResources; |
| 10 | use embassy_net_enc28j60::Enc28j60; | 10 | use embassy_net_enc28j60::Enc28j60; |
| 11 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; | 11 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; |
| 12 | use embassy_nrf::rng::Rng; | 12 | use embassy_nrf::rng::Rng; |
| @@ -25,8 +25,8 @@ bind_interrupts!(struct Irqs { | |||
| 25 | type MyDriver = Enc28j60<ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static>, Delay>, Output<'static>>; | 25 | type MyDriver = Enc28j60<ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static>, Delay>, Output<'static>>; |
| 26 | 26 | ||
| 27 | #[embassy_executor::task] | 27 | #[embassy_executor::task] |
| 28 | async fn net_task(stack: &'static Stack<MyDriver>) -> ! { | 28 | async fn net_task(mut runner: embassy_net::Runner<'static, MyDriver>) -> ! { |
| 29 | stack.run().await | 29 | runner.run().await |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | #[embassy_executor::main] | 32 | #[embassy_executor::main] |
| @@ -65,11 +65,10 @@ async fn main(spawner: Spawner) { | |||
| 65 | let seed = u64::from_le_bytes(seed); | 65 | let seed = u64::from_le_bytes(seed); |
| 66 | 66 | ||
| 67 | // Init network stack | 67 | // Init network stack |
| 68 | static STACK: StaticCell<Stack<MyDriver>> = StaticCell::new(); | ||
| 69 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 68 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); |
| 70 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 69 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 71 | 70 | ||
| 72 | unwrap!(spawner.spawn(net_task(stack))); | 71 | unwrap!(spawner.spawn(net_task(runner))); |
| 73 | 72 | ||
| 74 | perf_client::run( | 73 | perf_client::run( |
| 75 | stack, | 74 | stack, |
diff --git a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs index 6632442f1..34fb8103b 100644 --- a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs +++ b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs | |||
| @@ -6,7 +6,7 @@ teleprobe_meta::timeout!(120); | |||
| 6 | 6 | ||
| 7 | use defmt::{info, unwrap}; | 7 | use defmt::{info, unwrap}; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_net::{Config, Stack, StackResources}; | 9 | use embassy_net::{Config, StackResources}; |
| 10 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; | 10 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; |
| 11 | use embassy_nrf::rng::Rng; | 11 | use embassy_nrf::rng::Rng; |
| 12 | use embassy_nrf::spim::{self, Spim}; | 12 | use embassy_nrf::spim::{self, Spim}; |
| @@ -40,8 +40,8 @@ async fn wifi_task( | |||
| 40 | type MyDriver = hosted::NetDriver<'static>; | 40 | type MyDriver = hosted::NetDriver<'static>; |
| 41 | 41 | ||
| 42 | #[embassy_executor::task] | 42 | #[embassy_executor::task] |
| 43 | async fn net_task(stack: &'static Stack<MyDriver>) -> ! { | 43 | async fn net_task(mut runner: embassy_net::Runner<'static, MyDriver>) -> ! { |
| 44 | stack.run().await | 44 | runner.run().await |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | #[embassy_executor::main] | 47 | #[embassy_executor::main] |
| @@ -86,16 +86,15 @@ async fn main(spawner: Spawner) { | |||
| 86 | let seed = u64::from_le_bytes(seed); | 86 | let seed = u64::from_le_bytes(seed); |
| 87 | 87 | ||
| 88 | // Init network stack | 88 | // Init network stack |
| 89 | static STACK: StaticCell<Stack<MyDriver>> = StaticCell::new(); | ||
| 90 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 89 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); |
| 91 | let stack = &*STACK.init(Stack::new( | 90 | let (stack, runner) = embassy_net::new( |
| 92 | device, | 91 | device, |
| 93 | Config::dhcpv4(Default::default()), | 92 | Config::dhcpv4(Default::default()), |
| 94 | RESOURCES.init(StackResources::new()), | 93 | RESOURCES.init(StackResources::new()), |
| 95 | seed, | 94 | seed, |
| 96 | )); | 95 | ); |
| 97 | 96 | ||
| 98 | unwrap!(spawner.spawn(net_task(stack))); | 97 | unwrap!(spawner.spawn(net_task(runner))); |
| 99 | 98 | ||
| 100 | perf_client::run( | 99 | perf_client::run( |
| 101 | stack, | 100 | stack, |
diff --git a/tests/perf-client/src/lib.rs b/tests/perf-client/src/lib.rs index 54762379a..4bd9e5674 100644 --- a/tests/perf-client/src/lib.rs +++ b/tests/perf-client/src/lib.rs | |||
| @@ -2,7 +2,6 @@ | |||
| 2 | 2 | ||
| 3 | use defmt::{assert, *}; | 3 | use defmt::{assert, *}; |
| 4 | use embassy_futures::join::join; | 4 | use embassy_futures::join::join; |
| 5 | use embassy_net::driver::Driver; | ||
| 6 | use embassy_net::tcp::TcpSocket; | 5 | use embassy_net::tcp::TcpSocket; |
| 7 | use embassy_net::{Ipv4Address, Stack}; | 6 | use embassy_net::{Ipv4Address, Stack}; |
| 8 | use embassy_time::{with_timeout, Duration, Timer}; | 7 | use embassy_time::{with_timeout, Duration, Timer}; |
| @@ -13,7 +12,7 @@ pub struct Expected { | |||
| 13 | pub updown_kbps: usize, | 12 | pub updown_kbps: usize, |
| 14 | } | 13 | } |
| 15 | 14 | ||
| 16 | pub async fn run<D: Driver>(stack: &Stack<D>, expected: Expected) { | 15 | pub async fn run(stack: Stack<'_>, expected: Expected) { |
| 17 | info!("Waiting for DHCP up..."); | 16 | info!("Waiting for DHCP up..."); |
| 18 | while stack.config_v4().is_none() { | 17 | while stack.config_v4().is_none() { |
| 19 | Timer::after_millis(100).await; | 18 | Timer::after_millis(100).await; |
| @@ -38,7 +37,7 @@ const DOWNLOAD_PORT: u16 = 4321; | |||
| 38 | const UPLOAD_PORT: u16 = 4322; | 37 | const UPLOAD_PORT: u16 = 4322; |
| 39 | const UPLOAD_DOWNLOAD_PORT: u16 = 4323; | 38 | const UPLOAD_DOWNLOAD_PORT: u16 = 4323; |
| 40 | 39 | ||
| 41 | async fn test_download<D: Driver>(stack: &Stack<D>) -> usize { | 40 | async fn test_download(stack: Stack<'_>) -> usize { |
| 42 | info!("Testing download..."); | 41 | info!("Testing download..."); |
| 43 | 42 | ||
| 44 | let mut rx_buffer = [0; RX_BUFFER_SIZE]; | 43 | let mut rx_buffer = [0; RX_BUFFER_SIZE]; |
| @@ -78,7 +77,7 @@ async fn test_download<D: Driver>(stack: &Stack<D>) -> usize { | |||
| 78 | kbps | 77 | kbps |
| 79 | } | 78 | } |
| 80 | 79 | ||
| 81 | async fn test_upload<D: Driver>(stack: &Stack<D>) -> usize { | 80 | async fn test_upload(stack: Stack<'_>) -> usize { |
| 82 | info!("Testing upload..."); | 81 | info!("Testing upload..."); |
| 83 | 82 | ||
| 84 | let mut rx_buffer = [0; RX_BUFFER_SIZE]; | 83 | let mut rx_buffer = [0; RX_BUFFER_SIZE]; |
| @@ -118,7 +117,7 @@ async fn test_upload<D: Driver>(stack: &Stack<D>) -> usize { | |||
| 118 | kbps | 117 | kbps |
| 119 | } | 118 | } |
| 120 | 119 | ||
| 121 | async fn test_upload_download<D: Driver>(stack: &Stack<D>) -> usize { | 120 | async fn test_upload_download(stack: Stack<'_>) -> usize { |
| 122 | info!("Testing upload+download..."); | 121 | info!("Testing upload+download..."); |
| 123 | 122 | ||
| 124 | let mut rx_buffer = [0; RX_BUFFER_SIZE]; | 123 | let mut rx_buffer = [0; RX_BUFFER_SIZE]; |
diff --git a/tests/rp/src/bin/cyw43-perf.rs b/tests/rp/src/bin/cyw43-perf.rs index 11c8aa58c..30e4afb07 100644 --- a/tests/rp/src/bin/cyw43-perf.rs +++ b/tests/rp/src/bin/cyw43-perf.rs | |||
| @@ -6,7 +6,7 @@ use cyw43::JoinOptions; | |||
| 6 | use cyw43_pio::PioSpi; | 6 | use cyw43_pio::PioSpi; |
| 7 | use defmt::{panic, *}; | 7 | use defmt::{panic, *}; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_net::{Config, Stack, StackResources}; | 9 | use embassy_net::{Config, StackResources}; |
| 10 | use embassy_rp::gpio::{Level, Output}; | 10 | use embassy_rp::gpio::{Level, Output}; |
| 11 | use embassy_rp::peripherals::{DMA_CH0, PIO0}; | 11 | use embassy_rp::peripherals::{DMA_CH0, PIO0}; |
| 12 | use embassy_rp::pio::{InterruptHandler, Pio}; | 12 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| @@ -30,8 +30,8 @@ async fn wifi_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'stati | |||
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | #[embassy_executor::task] | 32 | #[embassy_executor::task] |
| 33 | async fn net_task(stack: &'static Stack<cyw43::NetDriver<'static>>) -> ! { | 33 | async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'static>>) -> ! { |
| 34 | stack.run().await | 34 | runner.run().await |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | #[embassy_executor::main] | 37 | #[embassy_executor::main] |
| @@ -70,16 +70,15 @@ async fn main(spawner: Spawner) { | |||
| 70 | let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random. | 70 | let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random. |
| 71 | 71 | ||
| 72 | // Init network stack | 72 | // Init network stack |
| 73 | static STACK: StaticCell<Stack<cyw43::NetDriver<'static>>> = StaticCell::new(); | ||
| 74 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 73 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); |
| 75 | let stack = &*STACK.init(Stack::new( | 74 | let (stack, runner) = embassy_net::new( |
| 76 | net_device, | 75 | net_device, |
| 77 | Config::dhcpv4(Default::default()), | 76 | Config::dhcpv4(Default::default()), |
| 78 | RESOURCES.init(StackResources::new()), | 77 | RESOURCES.init(StackResources::new()), |
| 79 | seed, | 78 | seed, |
| 80 | )); | 79 | ); |
| 81 | 80 | ||
| 82 | unwrap!(spawner.spawn(net_task(stack))); | 81 | unwrap!(spawner.spawn(net_task(runner))); |
| 83 | 82 | ||
| 84 | loop { | 83 | loop { |
| 85 | match control | 84 | match control |
diff --git a/tests/rp/src/bin/ethernet_w5100s_perf.rs b/tests/rp/src/bin/ethernet_w5100s_perf.rs index f15f33743..ae2adfa55 100644 --- a/tests/rp/src/bin/ethernet_w5100s_perf.rs +++ b/tests/rp/src/bin/ethernet_w5100s_perf.rs | |||
| @@ -5,7 +5,7 @@ teleprobe_meta::timeout!(120); | |||
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_net::{Stack, StackResources}; | 8 | use embassy_net::StackResources; |
| 9 | use embassy_net_wiznet::chip::W5100S; | 9 | use embassy_net_wiznet::chip::W5100S; |
| 10 | use embassy_net_wiznet::*; | 10 | use embassy_net_wiznet::*; |
| 11 | use embassy_rp::clocks::RoscRng; | 11 | use embassy_rp::clocks::RoscRng; |
| @@ -32,8 +32,8 @@ async fn ethernet_task( | |||
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | #[embassy_executor::task] | 34 | #[embassy_executor::task] |
| 35 | async fn net_task(stack: &'static Stack<Device<'static>>) -> ! { | 35 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { |
| 36 | stack.run().await | 36 | runner.run().await |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | #[embassy_executor::main] | 39 | #[embassy_executor::main] |
| @@ -67,17 +67,16 @@ async fn main(spawner: Spawner) { | |||
| 67 | let seed = rng.next_u64(); | 67 | let seed = rng.next_u64(); |
| 68 | 68 | ||
| 69 | // Init network stack | 69 | // Init network stack |
| 70 | static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new(); | ||
| 71 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 70 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); |
| 72 | let stack = &*STACK.init(Stack::new( | 71 | let (stack, runner) = embassy_net::new( |
| 73 | device, | 72 | device, |
| 74 | embassy_net::Config::dhcpv4(Default::default()), | 73 | embassy_net::Config::dhcpv4(Default::default()), |
| 75 | RESOURCES.init(StackResources::new()), | 74 | RESOURCES.init(StackResources::new()), |
| 76 | seed, | 75 | seed, |
| 77 | )); | 76 | ); |
| 78 | 77 | ||
| 79 | // Launch network task | 78 | // Launch network task |
| 80 | unwrap!(spawner.spawn(net_task(&stack))); | 79 | unwrap!(spawner.spawn(net_task(runner))); |
| 81 | 80 | ||
| 82 | perf_client::run( | 81 | perf_client::run( |
| 83 | stack, | 82 | stack, |
diff --git a/tests/stm32/src/bin/eth.rs b/tests/stm32/src/bin/eth.rs index 9da514881..bf1922dde 100644 --- a/tests/stm32/src/bin/eth.rs +++ b/tests/stm32/src/bin/eth.rs | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | mod common; | 6 | mod common; |
| 7 | use common::*; | 7 | use common::*; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_net::{Stack, StackResources}; | 9 | use embassy_net::StackResources; |
| 10 | use embassy_stm32::eth::generic_smi::GenericSMI; | 10 | use embassy_stm32::eth::generic_smi::GenericSMI; |
| 11 | use embassy_stm32::eth::{Ethernet, PacketQueue}; | 11 | use embassy_stm32::eth::{Ethernet, PacketQueue}; |
| 12 | use embassy_stm32::peripherals::ETH; | 12 | use embassy_stm32::peripherals::ETH; |
| @@ -32,8 +32,8 @@ bind_interrupts!(struct Irqs { | |||
| 32 | type Device = Ethernet<'static, ETH, GenericSMI>; | 32 | type Device = Ethernet<'static, ETH, GenericSMI>; |
| 33 | 33 | ||
| 34 | #[embassy_executor::task] | 34 | #[embassy_executor::task] |
| 35 | async fn net_task(stack: &'static Stack<Device>) -> ! { | 35 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { |
| 36 | stack.run().await | 36 | runner.run().await |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | #[embassy_executor::main] | 39 | #[embassy_executor::main] |
| @@ -99,12 +99,11 @@ async fn main(spawner: Spawner) { | |||
| 99 | //}); | 99 | //}); |
| 100 | 100 | ||
| 101 | // Init network stack | 101 | // Init network stack |
| 102 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | ||
| 103 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 102 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); |
| 104 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 103 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 105 | 104 | ||
| 106 | // Launch network task | 105 | // Launch network task |
| 107 | unwrap!(spawner.spawn(net_task(&stack))); | 106 | unwrap!(spawner.spawn(net_task(runner))); |
| 108 | 107 | ||
| 109 | perf_client::run( | 108 | perf_client::run( |
| 110 | stack, | 109 | stack, |
