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 c2575267c..8289ecddf 100644
--- a/embassy-net/src/lib.rs
+++ b/embassy-net/src/lib.rs
@@ -226,6 +226,7 @@ struct Inner<D: Driver> {
     static_v6: Option<StaticConfigV6>,
     #[cfg(feature = "dhcpv4")]
     dhcp_socket: Option<SocketHandle>,
+    config_waker: WakerRegistration,
     #[cfg(feature = "dns")]
     dns_socket: SocketHandle,
     #[cfg(feature = "dns")]
@@ -297,6 +298,7 @@ impl<D: Driver + 'static> Stack<D> {
             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<D: Driver + 'static> Stack<D> {
         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<D: Driver + 'static> Inner<D> {
         s.sockets
             .get_mut::<smoltcp::socket::dns::Socket>(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 8289ecddf..9eea8cb4e 100644
--- a/embassy-net/src/lib.rs
+++ b/embassy-net/src/lib.rs
@@ -365,7 +365,7 @@ impl<D: Driver + 'static> Stack<D> {
         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 9eea8cb4e..4922490d9 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<D: Driver + 'static> Stack<D> {
         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<D: Driver + 'static> Inner<D> {
             .get_mut::<smoltcp::socket::dns::Socket>(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 393e60b73..5f1e62d0a 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 f0e280c35..01c38106e 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 763520ab8..c32e0fdb5 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 26a386e49..e691c6d06 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 6664410c8..ebef54c3c 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 4922490d9..87247c8e1 100644
--- a/embassy-net/src/lib.rs
+++ b/embassy-net/src/lib.rs
@@ -367,13 +367,12 @@ impl<D: Driver + 'static> Stack<D> {
     }
 
     /// 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<D: Driver + 'static> Stack<D> {
     ///    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 <dirbaio@dirbaio.net>
---
 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 87247c8e1..de32edc2f 100644
--- a/embassy-net/src/lib.rs
+++ b/embassy-net/src/lib.rs
@@ -371,7 +371,7 @@ impl<D: Driver + 'static> Stack<D> {
     /// ## 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