From 32b89eeba18d2d0a9c3705212768d4ade3f4948d Mon Sep 17 00:00:00 2001
From: Dario Nieuwenhuis <dirbaio@dirbaio.net>
Date: Thu, 12 Oct 2023 01:35:23 +0200
Subject: [PATCH 1/2] net: remove atomic-polyfill.

---
 cyw43/Cargo.toml                       |  1 -
 embassy-net/Cargo.toml                 |  1 -
 embassy-net/src/tcp.rs                 | 15 +++++++--------
 examples/stm32h7/src/bin/eth_client.rs |  4 ++--
 4 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml
index dae7419c1..c201405e7 100644
--- a/cyw43/Cargo.toml
+++ b/cyw43/Cargo.toml
@@ -15,7 +15,6 @@ embassy-time = { version = "0.1.3", path = "../embassy-time"}
 embassy-sync = { version = "0.3.0", path = "../embassy-sync"}
 embassy-futures = { version = "0.1.0", path = "../embassy-futures"}
 embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"}
-atomic-polyfill = "0.1.5"
 
 defmt = { version = "0.3", optional = true }
 log = { version = "0.4.17", optional = true }
diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml
index c2fffba84..a3c18046e 100644
--- a/embassy-net/Cargo.toml
+++ b/embassy-net/Cargo.toml
@@ -64,4 +64,3 @@ stable_deref_trait = { version = "1.2.0", default-features = false }
 futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] }
 atomic-pool = "1.0"
 embedded-nal-async = { version = "0.6.0", optional = true }
-atomic-polyfill = { version = "1.0" }
diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs
index a12fd382a..b5615cb66 100644
--- a/embassy-net/src/tcp.rs
+++ b/embassy-net/src/tcp.rs
@@ -579,11 +579,10 @@ mod embedded_io_impls {
 /// TCP client compatible with `embedded-nal-async` traits.
 #[cfg(feature = "nightly")]
 pub mod client {
-    use core::cell::UnsafeCell;
+    use core::cell::{Cell, UnsafeCell};
     use core::mem::MaybeUninit;
     use core::ptr::NonNull;
 
-    use atomic_polyfill::{AtomicBool, Ordering};
     use embedded_nal_async::IpAddr;
 
     use super::*;
@@ -702,15 +701,13 @@ pub mod client {
         }
     }
 
-    unsafe impl<const N: usize, const TX_SZ: usize, const RX_SZ: usize> Sync for TcpClientState<N, TX_SZ, RX_SZ> {}
-
     struct Pool<T, const N: usize> {
-        used: [AtomicBool; N],
+        used: [Cell<bool>; N],
         data: [UnsafeCell<MaybeUninit<T>>; N],
     }
 
     impl<T, const N: usize> Pool<T, N> {
-        const VALUE: AtomicBool = AtomicBool::new(false);
+        const VALUE: Cell<bool> = Cell::new(false);
         const UNINIT: UnsafeCell<MaybeUninit<T>> = UnsafeCell::new(MaybeUninit::uninit());
 
         const fn new() -> Self {
@@ -724,7 +721,9 @@ pub mod client {
     impl<T, const N: usize> Pool<T, N> {
         fn alloc(&self) -> Option<NonNull<T>> {
             for n in 0..N {
-                if self.used[n].swap(true, Ordering::SeqCst) == false {
+                // this can't race because Pool is not Sync.
+                if !self.used[n].get() {
+                    self.used[n].set(true);
                     let p = self.data[n].get() as *mut T;
                     return Some(unsafe { NonNull::new_unchecked(p) });
                 }
@@ -738,7 +737,7 @@ pub mod client {
             let n = p.as_ptr().offset_from(origin);
             assert!(n >= 0);
             assert!((n as usize) < N);
-            self.used[n as usize].store(false, Ordering::SeqCst);
+            self.used[n as usize].set(false);
         }
     }
 }
diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs
index 4db7aa252..09d27cdbd 100644
--- a/examples/stm32h7/src/bin/eth_client.rs
+++ b/examples/stm32h7/src/bin/eth_client.rs
@@ -105,8 +105,8 @@ async fn main(spawner: Spawner) -> ! {
 
     info!("Network task initialized");
 
-    static STATE: TcpClientState<1, 1024, 1024> = TcpClientState::new();
-    let client = TcpClient::new(&stack, &STATE);
+    let state: TcpClientState<1, 1024, 1024> = TcpClientState::new();
+    let client = TcpClient::new(&stack, &state);
 
     loop {
         let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(10, 42, 0, 1), 8000));

From 70a91945fca97229518f4f8f011233650448771d Mon Sep 17 00:00:00 2001
From: Dario Nieuwenhuis <dirbaio@dirbaio.net>
Date: Thu, 12 Oct 2023 01:16:42 +0200
Subject: [PATCH 2/2] stm32: remove atomic-polyfill.

---
 embassy-stm32/Cargo.toml         |  1 -
 embassy-stm32/build.rs           | 34 ++++++++++++++++++++++++++++----
 embassy-stm32/src/dma/bdma.rs    | 18 ++++++++++++++---
 embassy-stm32/src/lib.rs         |  4 +++-
 embassy-stm32/src/low_power.rs   |  2 +-
 embassy-stm32/src/rcc/mod.rs     | 16 +++++++++------
 embassy-stm32/src/time_driver.rs | 22 ++++++++++-----------
 embassy-time/Cargo.toml          |  1 -
 8 files changed, 69 insertions(+), 29 deletions(-)

diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 33583d22b..a2c5da2bc 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -58,7 +58,6 @@ rand_core = "0.6.3"
 sdio-host = "0.5.0"
 embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
 critical-section = "1.1"
-atomic-polyfill = "1.0.1"
 stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-6bfa5a0dcec6a9bd42cea94ba11eeae1a17a7f2c" }
 vcell = "0.1.3"
 bxcan = "0.7.0"
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 810da37e9..fa10b7f77 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -8,6 +8,32 @@ use quote::{format_ident, quote};
 use stm32_metapac::metadata::{MemoryRegionKind, METADATA};
 
 fn main() {
+    let target = env::var("TARGET").unwrap();
+
+    if target.starts_with("thumbv6m-") {
+        println!("cargo:rustc-cfg=cortex_m");
+        println!("cargo:rustc-cfg=armv6m");
+    } else if target.starts_with("thumbv7m-") {
+        println!("cargo:rustc-cfg=cortex_m");
+        println!("cargo:rustc-cfg=armv7m");
+    } else if target.starts_with("thumbv7em-") {
+        println!("cargo:rustc-cfg=cortex_m");
+        println!("cargo:rustc-cfg=armv7m");
+        println!("cargo:rustc-cfg=armv7em"); // (not currently used)
+    } else if target.starts_with("thumbv8m.base") {
+        println!("cargo:rustc-cfg=cortex_m");
+        println!("cargo:rustc-cfg=armv8m");
+        println!("cargo:rustc-cfg=armv8m_base");
+    } else if target.starts_with("thumbv8m.main") {
+        println!("cargo:rustc-cfg=cortex_m");
+        println!("cargo:rustc-cfg=armv8m");
+        println!("cargo:rustc-cfg=armv8m_main");
+    }
+
+    if target.ends_with("-eabihf") {
+        println!("cargo:rustc-cfg=has_fpu");
+    }
+
     let chip_name = match env::vars()
         .map(|(a, _)| a)
         .filter(|x| x.starts_with("CARGO_FEATURE_STM32"))
@@ -434,20 +460,20 @@ fn main() {
                         unsafe { crate::rcc::get_freqs().#clk }
                     }
                     fn enable() {
-                        critical_section::with(|_| {
+                        critical_section::with(|_cs| {
                             #before_enable
                             #[cfg(feature = "low-power")]
-                            crate::rcc::clock_refcount_add();
+                            crate::rcc::clock_refcount_add(_cs);
                             crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
                             #after_enable
                         })
                     }
                     fn disable() {
-                        critical_section::with(|_| {
+                        critical_section::with(|_cs| {
                             #before_disable
                             crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
                             #[cfg(feature = "low-power")]
-                            crate::rcc::clock_refcount_sub();
+                            crate::rcc::clock_refcount_sub(_cs);
                         })
                     }
                     fn reset() {
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs
index 20ff29bef..62eb65b1c 100644
--- a/embassy-stm32/src/dma/bdma.rs
+++ b/embassy-stm32/src/dma/bdma.rs
@@ -2,10 +2,9 @@
 
 use core::future::Future;
 use core::pin::Pin;
-use core::sync::atomic::{fence, Ordering};
+use core::sync::atomic::{fence, AtomicUsize, Ordering};
 use core::task::{Context, Poll, Waker};
 
-use atomic_polyfill::AtomicUsize;
 use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
 use embassy_sync::waitqueue::AtomicWaker;
 
@@ -127,7 +126,13 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: usize, index
     } else if isr.tcif(channel_num) && cr.read().tcie() {
         // Acknowledge transfer complete interrupt
         dma.ifcr().write(|w| w.set_tcif(channel_num, true));
+        #[cfg(not(armv6m))]
         STATE.complete_count[index].fetch_add(1, Ordering::Release);
+        #[cfg(armv6m)]
+        critical_section::with(|_| {
+            let x = STATE.complete_count[index].load(Ordering::Relaxed);
+            STATE.complete_count[index].store(x + 1, Ordering::Release);
+        })
     } else {
         return;
     }
@@ -391,7 +396,14 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> {
     }
 
     fn reset_complete_count(&mut self) -> usize {
-        STATE.complete_count[self.0.index()].swap(0, Ordering::AcqRel)
+        #[cfg(not(armv6m))]
+        return STATE.complete_count[self.0.index()].swap(0, Ordering::AcqRel);
+        #[cfg(armv6m)]
+        return critical_section::with(|_| {
+            let x = STATE.complete_count[self.0.index()].load(Ordering::Acquire);
+            STATE.complete_count[self.0.index()].store(0, Ordering::Release);
+            x
+        });
     }
 
     fn set_waker(&mut self, waker: &Waker) {
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index e883678b5..37c94f827 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -225,7 +225,9 @@ pub fn init(config: Config) -> Peripherals {
 
         #[cfg(feature = "low-power")]
         while !crate::rcc::low_power_ready() {
-            crate::rcc::clock_refcount_sub();
+            critical_section::with(|cs| {
+                crate::rcc::clock_refcount_sub(cs);
+            });
         }
     }
 
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index bb714b8ca..861a59d7b 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -1,7 +1,7 @@
 use core::arch::asm;
 use core::marker::PhantomData;
+use core::sync::atomic::{compiler_fence, Ordering};
 
-use atomic_polyfill::{compiler_fence, Ordering};
 use cortex_m::peripheral::SCB;
 use embassy_executor::*;
 
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index a9e53d424..abb53fd10 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -27,9 +27,10 @@ pub use mco::*;
 #[cfg_attr(rcc_wba, path = "wba.rs")]
 #[cfg_attr(any(rcc_wl5, rcc_wle), path = "wl.rs")]
 mod _version;
-pub use _version::*;
 #[cfg(feature = "low-power")]
-use atomic_polyfill::{AtomicU32, Ordering};
+use core::sync::atomic::{AtomicU32, Ordering};
+
+pub use _version::*;
 
 //  Model Clock Configuration
 //
@@ -145,14 +146,17 @@ pub fn low_power_ready() -> bool {
 }
 
 #[cfg(feature = "low-power")]
-pub(crate) fn clock_refcount_add() {
+pub(crate) fn clock_refcount_add(_cs: critical_section::CriticalSection) {
     // We don't check for overflow because constructing more than u32 peripherals is unlikely
-    CLOCK_REFCOUNT.fetch_add(1, Ordering::Relaxed);
+    let n = CLOCK_REFCOUNT.load(Ordering::Relaxed);
+    CLOCK_REFCOUNT.store(n + 1, Ordering::Relaxed);
 }
 
 #[cfg(feature = "low-power")]
-pub(crate) fn clock_refcount_sub() {
-    assert!(CLOCK_REFCOUNT.fetch_sub(1, Ordering::Relaxed) != 0);
+pub(crate) fn clock_refcount_sub(_cs: critical_section::CriticalSection) {
+    let n = CLOCK_REFCOUNT.load(Ordering::Relaxed);
+    assert!(n != 0);
+    CLOCK_REFCOUNT.store(n - 1, Ordering::Relaxed);
 }
 
 /// Frozen clock frequencies
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index 917502412..e88198e6f 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -1,9 +1,8 @@
 use core::cell::Cell;
 use core::convert::TryInto;
-use core::sync::atomic::{compiler_fence, Ordering};
+use core::sync::atomic::{compiler_fence, AtomicU32, AtomicU8, Ordering};
 use core::{mem, ptr};
 
-use atomic_polyfill::{AtomicU32, AtomicU8};
 use critical_section::CriticalSection;
 use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
 use embassy_sync::blocking_mutex::Mutex;
@@ -229,7 +228,9 @@ impl RtcDriver {
     fn next_period(&self) {
         let r = T::regs_gp16();
 
-        let period = self.period.fetch_add(1, Ordering::Relaxed) + 1;
+        // We only modify the period from the timer interrupt, so we know this can't race.
+        let period = self.period.load(Ordering::Relaxed) + 1;
+        self.period.store(period, Ordering::Relaxed);
         let t = (period as u64) << 15;
 
         critical_section::with(move |cs| {
@@ -403,18 +404,15 @@ impl Driver for RtcDriver {
     }
 
     unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> {
-        let id = self.alarm_count.fetch_update(Ordering::AcqRel, Ordering::Acquire, |x| {
-            if x < ALARM_COUNT as u8 {
-                Some(x + 1)
+        critical_section::with(|_| {
+            let id = self.alarm_count.load(Ordering::Relaxed);
+            if id < ALARM_COUNT as u8 {
+                self.alarm_count.store(id + 1, Ordering::Relaxed);
+                Some(AlarmHandle::new(id))
             } else {
                 None
             }
-        });
-
-        match id {
-            Ok(id) => Some(AlarmHandle::new(id)),
-            Err(_) => None,
-        }
+        })
     }
 
     fn set_alarm_callback(&self, alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) {
diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml
index 8f034a9de..e4b88d784 100644
--- a/embassy-time/Cargo.toml
+++ b/embassy-time/Cargo.toml
@@ -218,7 +218,6 @@ embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1", optional =
 embedded-hal-async = { version = "=1.0.0-rc.1", optional = true}
 
 futures-util = { version = "0.3.17", default-features = false }
-atomic-polyfill = "1.0.1"
 critical-section = "1.1"
 cfg-if = "1.0.0"
 heapless = "0.7"