From a4f8d82ef51b7c0c775168472829ecd18d8f84d8 Mon Sep 17 00:00:00 2001 From: JuliDi <20155974+JuliDi@users.noreply.github.com> Date: Fri, 8 Sep 2023 15:58:47 +0200 Subject: [PATCH 1/6] wait_config_up first steps --- embassy-net/src/lib.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index c2575267..8289ecdd 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -226,6 +226,7 @@ struct Inner { static_v6: Option, #[cfg(feature = "dhcpv4")] dhcp_socket: Option, + config_waker: WakerRegistration, #[cfg(feature = "dns")] dns_socket: SocketHandle, #[cfg(feature = "dns")] @@ -297,6 +298,7 @@ impl Stack { static_v6: None, #[cfg(feature = "dhcpv4")] dhcp_socket: None, + config_waker: WakerRegistration::new(), #[cfg(feature = "dns")] dns_socket: socket.sockets.add(dns::Socket::new( &[], @@ -363,6 +365,28 @@ impl Stack { v4_up || v6_up } + /// Get for the network stack to obtainer a valid IP configuration. + pub async fn wait_config_up(&self) { + if self.is_config_up() { + return; + } + + poll_fn(|cx| { + self.with_mut(|_, i| { + debug!("poll_fn called"); + if self.is_config_up() { + debug!("poll_fn ready"); + Poll::Ready(()) + } else { + debug!("poll_fn pending"); + i.config_waker.register(cx.waker()); + Poll::Pending + } + }) + }) + .await; + } + /// Get the current IPv4 configuration. /// /// If using DHCP, this will be None if DHCP hasn't been able to @@ -706,6 +730,8 @@ impl Inner { s.sockets .get_mut::(self.dns_socket) .update_servers(&dns_servers[..]); + + s.waker.wake(); } fn poll(&mut self, cx: &mut Context<'_>, s: &mut SocketStack) { From 6070d61d8ce2d9ce416467ac6aac8ffdd89a59b9 Mon Sep 17 00:00:00 2001 From: JuliDi <20155974+JuliDi@users.noreply.github.com> Date: Fri, 8 Sep 2023 15:59:46 +0200 Subject: [PATCH 2/6] fix typos --- embassy-net/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 8289ecdd..9eea8cb4 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -365,7 +365,7 @@ impl Stack { v4_up || v6_up } - /// Get for the network stack to obtainer a valid IP configuration. + /// Wait for the network stack to obtaine a valid IP configuration. pub async fn wait_config_up(&self) { if self.is_config_up() { return; From 3e0b752befd492229bfb4c6f9fd3213cfd69a0fc Mon Sep 17 00:00:00 2001 From: JuliDi <20155974+JuliDi@users.noreply.github.com> Date: Fri, 8 Sep 2023 17:26:01 +0200 Subject: [PATCH 3/6] fix poll_fn, add documentation --- embassy-net/src/lib.rs | 53 ++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 9eea8cb4..4922490d 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -172,6 +172,7 @@ impl Config { /// /// # Example /// ```rust + /// # use embassy_net::Config; /// let _cfg = Config::dhcpv4(Default::default()); /// ``` #[cfg(feature = "dhcpv4")] @@ -365,24 +366,52 @@ impl Stack { v4_up || v6_up } - /// Wait for the network stack to obtaine a valid IP configuration. + /// Wait for the network stack to obtain a valid IP configuration. + /// Returns instantly if [`Stack::is_config_up`] returns `true`. + /// + /// ## Watch out: + /// The Future is polled only when the [`Stack`] is running, + /// e.g. call `spawner.spawn(net_task(stack))`. + /// + /// `await`ing before will never yield! + /// + /// ## Example + /// ```ignore + /// let config = embassy_net::Config::dhcpv4(Default::default()); + ///// Init network stack + /// let stack = &*make_static!(embassy_net::Stack::new( + /// device, + /// config, + /// make_static!(embassy_net::StackResources::<2>::new()), + /// seed + /// )); + /// // Launch network task + /// spawner.spawn(net_task(stack)).unwrap(); + /// // Wait for DHCP config + /// stack.wait_config_up().await; + /// // use the network stack + /// // ... + /// ``` pub async fn wait_config_up(&self) { + // If the config is up already, we can return immediately. if self.is_config_up() { return; } poll_fn(|cx| { - self.with_mut(|_, i| { - debug!("poll_fn called"); - if self.is_config_up() { - debug!("poll_fn ready"); - Poll::Ready(()) - } else { - debug!("poll_fn pending"); + if self.is_config_up() { + Poll::Ready(()) + } else { + // If the config is not up, we register a waker that is woken up + // when a config is applied (static or DHCP). + trace!("Waiting for config up"); + + self.with_mut(|_, i| { i.config_waker.register(cx.waker()); - Poll::Pending - } - }) + }); + + Poll::Pending + } }) .await; } @@ -731,7 +760,7 @@ impl Inner { .get_mut::(self.dns_socket) .update_servers(&dns_servers[..]); - s.waker.wake(); + self.config_waker.wake(); } fn poll(&mut self, cx: &mut Context<'_>, s: &mut SocketStack) { From cf2d4eca7c3a3f53aa57a7d9a53de490962019cf Mon Sep 17 00:00:00 2001 From: JuliDi <20155974+JuliDi@users.noreply.github.com> Date: Fri, 8 Sep 2023 17:40:20 +0200 Subject: [PATCH 4/6] add wait_config_up to examples --- examples/stm32f4/src/bin/eth.rs | 5 ++++- examples/stm32f7/src/bin/eth.rs | 5 ++++- examples/stm32h5/src/bin/eth.rs | 3 +++ examples/stm32h7/src/bin/eth.rs | 3 +++ examples/stm32h7/src/bin/eth_client.rs | 8 ++++---- 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs index 393e60b7..5f1e62d0 100644 --- a/examples/stm32f4/src/bin/eth.rs +++ b/examples/stm32f4/src/bin/eth.rs @@ -79,7 +79,10 @@ async fn main(spawner: Spawner) -> ! { )); // Launch network task - unwrap!(spawner.spawn(net_task(&stack))); + unwrap!(spawner.spawn(net_task(stack))); + + // Ensure DHCP configuration is up before trying connect + stack.wait_config_up().await; info!("Network task initialized"); diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index f0e280c3..01c38106 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs @@ -80,7 +80,10 @@ async fn main(spawner: Spawner) -> ! { )); // Launch network task - unwrap!(spawner.spawn(net_task(&stack))); + unwrap!(spawner.spawn(net_task(stack))); + + // Ensure DHCP configuration is up before trying connect + stack.wait_config_up().await; info!("Network task initialized"); diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 763520ab..c32e0fdb 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs @@ -101,6 +101,9 @@ async fn main(spawner: Spawner) -> ! { // Launch network task unwrap!(spawner.spawn(net_task(&stack))); + // Ensure DHCP configuration is up before trying connect + stack.wait_config_up().await; + info!("Network task initialized"); // Then we can use it! diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 26a386e4..e691c6d0 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -83,6 +83,9 @@ async fn main(spawner: Spawner) -> ! { // Launch network task unwrap!(spawner.spawn(net_task(&stack))); + // Ensure DHCP configuration is up before trying connect + stack.wait_config_up().await; + info!("Network task initialized"); // Then we can use it! diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 6664410c..ebef54c3 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs @@ -82,13 +82,13 @@ async fn main(spawner: Spawner) -> ! { )); // Launch network task - unwrap!(spawner.spawn(net_task(&stack))); + unwrap!(spawner.spawn(net_task(stack))); + + // Ensure DHCP configuration is up before trying connect + stack.wait_config_up().await; info!("Network task initialized"); - // To ensure DHCP configuration before trying connect - Timer::after(Duration::from_secs(20)).await; - static STATE: TcpClientState<1, 1024, 1024> = TcpClientState::new(); let client = TcpClient::new(&stack, &STATE); From 40a18b075dc80048233c54f5cff80658405a9050 Mon Sep 17 00:00:00 2001 From: JuliDi <20155974+JuliDi@users.noreply.github.com> Date: Sat, 9 Sep 2023 09:50:24 +0200 Subject: [PATCH 5/6] improve docstring --- embassy-net/src/lib.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 4922490d..87247c8e 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -367,13 +367,12 @@ impl Stack { } /// Wait for the network stack to obtain a valid IP configuration. - /// Returns instantly if [`Stack::is_config_up`] returns `true`. /// - /// ## Watch out: - /// The Future is polled only when the [`Stack`] is running, - /// e.g. call `spawner.spawn(net_task(stack))`. + /// ## Notes: + /// - Ensure [`Stack::run`] has been called before using this function. /// - /// `await`ing before will never yield! + /// - This function may never yield (e.g. if no configuration is obtained through DHCP). + /// The caller is supposed to handle a timeout for this case. /// /// ## Example /// ```ignore @@ -385,7 +384,7 @@ impl Stack { /// make_static!(embassy_net::StackResources::<2>::new()), /// seed /// )); - /// // Launch network task + /// // Launch network task that runs `stack.run().await` /// spawner.spawn(net_task(stack)).unwrap(); /// // Wait for DHCP config /// stack.wait_config_up().await; From 0e9131fd1465d8fc765c4da05ce63d9dfbf950c7 Mon Sep 17 00:00:00 2001 From: Julian <20155974+JuliDi@users.noreply.github.com> Date: Sat, 9 Sep 2023 12:36:57 +0200 Subject: [PATCH 6/6] yield -> return Co-authored-by: Dario Nieuwenhuis --- embassy-net/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 87247c8e..de32edc2 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -371,7 +371,7 @@ impl Stack { /// ## Notes: /// - Ensure [`Stack::run`] has been called before using this function. /// - /// - This function may never yield (e.g. if no configuration is obtained through DHCP). + /// - This function may never return (e.g. if no configuration is obtained through DHCP). /// The caller is supposed to handle a timeout for this case. /// /// ## Example