Compare commits

...

17 Commits

Author SHA1 Message Date
c8aa9c3b98 wip 2023-10-11 20:53:33 -05:00
7810ef1c5e wip 2023-10-11 20:22:00 -05:00
c1dc1741f6 wip 2023-10-11 20:21:32 -05:00
6deec1b853 wip 2023-10-11 20:17:47 -05:00
ba5b5e98fe wip 2023-10-11 20:15:43 -05:00
158aeac438 wip 2023-10-11 20:12:13 -05:00
f27c929cb8 wip 2023-10-11 19:59:42 -05:00
0d0fbe957e Merge branch 'rcc-mux' of github.com:xoviat/embassy; branch 'main' of github.com:embassy-rs/embassy into rcc-mux 2023-10-11 19:58:38 -05:00
e1a1c51d00 remove disable variant 2023-10-11 19:35:45 -05:00
ac84631a2a Merge pull request #2046 from embassy-rs/stm32-remove-polyfill
stm32: remove atomic-polyfill.
2023-10-12 00:14:02 +00:00
70a91945fc stm32: remove atomic-polyfill. 2023-10-12 02:07:26 +02:00
32b89eeba1 net: remove atomic-polyfill. 2023-10-12 02:07:26 +02:00
e25c7c23d0 wip 2023-10-09 20:49:44 -05:00
4ee39f6dce Merge branch 'main' of github.com:embassy-rs/embassy into rcc-mux 2023-10-09 20:10:16 -05:00
a4b6bc31f8 wip 2023-10-08 18:26:27 -05:00
2ae9d28d47 wip 2023-10-07 09:34:12 -05:00
1457b53e48 wip 2023-10-07 09:31:09 -05:00
13 changed files with 280 additions and 51 deletions

View File

@ -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 }

View File

@ -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" }

View File

@ -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);
}
}
}

View File

@ -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"

View File

@ -5,9 +5,36 @@ use std::{env, fs};
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote};
use stm32_metapac::metadata::{MemoryRegionKind, METADATA};
use stm32_metapac::metadata::ir::{BlockItemInner, Enum};
use stm32_metapac::metadata::{MemoryRegionKind, PeripheralRccRegister, 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"))
@ -361,6 +388,51 @@ fn main() {
});
}
// ========
// Generate rcc fieldset and enum maps
let rcc_enum_map: HashMap<&str, HashMap<&str, &Enum>> = {
let rcc_registers = METADATA
.peripherals
.iter()
.filter_map(|p| p.registers.as_ref())
.find(|r| r.kind == "rcc")
.unwrap()
.ir;
let rcc_blocks = rcc_registers.blocks.iter().find(|b| b.name == "Rcc").unwrap().items;
let rcc_block_item_map: HashMap<&str, &str> = rcc_blocks
.iter()
.filter_map(|b| match &b.inner {
BlockItemInner::Register(register) => register.fieldset.map(|f| (f, b.name)),
_ => None,
})
.collect();
let rcc_enum_map: HashMap<&str, &Enum> = rcc_registers.enums.iter().map(|e| (e.name, e)).collect();
rcc_registers
.fieldsets
.iter()
.filter_map(|f| {
rcc_block_item_map.get(f.name).map(|b| {
(
*b,
f.fields
.iter()
.filter_map(|f| {
let enumm = f.enumm?;
let enumm = rcc_enum_map.get(enumm)?;
Some((f.name, *enumm))
})
.collect(),
)
})
})
.collect()
};
// ========
// Generate RccPeripheral impls
@ -428,26 +500,77 @@ fn main() {
(TokenStream::new(), TokenStream::new())
};
let mux_for = |mux: Option<&'static PeripheralRccRegister>| {
// temporary hack to restrict the scope of the implementation to h5
if !&chip_name.starts_with("stm32h5") {
return None;
}
let mux = mux?;
let fieldset = rcc_enum_map.get(mux.register)?;
let enumm = fieldset.get(mux.field)?;
Some((mux, *enumm))
};
let clock_frequency = match mux_for(rcc.mux.as_ref()) {
Some((mux, rcc_enumm)) => {
let fieldset_name = format_ident!("{}", mux.register);
let field_name = format_ident!("{}", mux.field);
let enum_name = format_ident!("{}", rcc_enumm.name);
let match_arms: TokenStream = rcc_enumm
.variants
.iter()
.filter(|v| v.name != "DISABLE")
.map(|v| {
let variant_name = format_ident!("{}", v.name);
// temporary hack to restrict the scope of the implementation until clock names can be stabilized
let clock_name = format_ident!("mux_{}", v.name.to_ascii_lowercase());
quote! {
#enum_name::#variant_name => unsafe { crate::rcc::get_freqs().#clock_name.unwrap() },
}
})
.collect();
quote! {
use crate::pac::rcc::vals::#enum_name;
#[allow(unreachable_patterns)]
match crate::pac::RCC.#fieldset_name().read().#field_name() {
#match_arms
_ => unreachable!(),
}
}
}
None => quote! {
unsafe { crate::rcc::get_freqs().#clk }
},
};
g.extend(quote! {
impl crate::rcc::sealed::RccPeripheral for peripherals::#pname {
fn frequency() -> crate::time::Hertz {
unsafe { crate::rcc::get_freqs().#clk }
#clock_frequency
}
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() {
@ -460,12 +583,14 @@ fn main() {
}
}
let mut refcount_mod = TokenStream::new();
for refcount_static in refcount_statics {
refcount_mod.extend(quote! {
pub(crate) static mut #refcount_static: u8 = 0;
});
}
let refcount_mod: TokenStream = refcount_statics
.iter()
.map(|refcount_static| {
quote! {
pub(crate) static mut #refcount_static: u8 = 0;
}
})
.collect();
g.extend(quote! {
mod refcount_statics {

View File

@ -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) {

View File

@ -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);
});
}
}

View File

@ -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::*;

View File

@ -388,7 +388,7 @@ pub(crate) unsafe fn init(config: Config) {
let pll1 = init_pll(0, config.pll1, &pll_input);
let pll2 = init_pll(1, config.pll2, &pll_input);
#[cfg(any(rcc_h5, stm32h7))]
let _pll3 = init_pll(2, config.pll3, &pll_input);
let pll3 = init_pll(2, config.pll3, &pll_input);
// Configure sysclk
let (sys, sw) = match config.sys {
@ -447,7 +447,7 @@ pub(crate) unsafe fn init(config: Config) {
#[cfg(stm32h7)]
let adc = match config.adc_clock_source {
AdcClockSource::PLL2_P => pll2.p,
AdcClockSource::PLL3_R => _pll3.r,
AdcClockSource::PLL3_R => pll3.r,
AdcClockSource::PER => _per_ck,
_ => unreachable!(),
};
@ -545,6 +545,53 @@ pub(crate) unsafe fn init(config: Config) {
apb2_tim,
adc,
rtc,
#[cfg(stm32h5)]
mux_rcc_pclk1: Some(apb1),
#[cfg(stm32h5)]
mux_pll2_q: None,
#[cfg(stm32h5)]
mux_pll3_q: None,
#[cfg(stm32h5)]
mux_hsi_ker: None,
#[cfg(stm32h5)]
mux_csi_ker: None,
#[cfg(stm32h5)]
mux_lse: None,
#[cfg(stm32h5)]
mux_pll1_q: pll1.q,
#[cfg(stm32h5)]
mux_pll2_p: pll2.p,
#[cfg(rcc_h5)]
mux_pll3_p: pll3.p,
#[cfg(stm32h5)]
mux_audioclk: None,
#[cfg(stm32h5)]
mux_per: None,
#[cfg(rcc_h5)]
mux_pll3_r: pll3.r,
#[cfg(all(not(rcc_h5), stm32h5))]
mux_pll3_r: None,
#[cfg(stm32h5)]
mux_rcc_pclk3: Some(apb3),
#[cfg(stm32h5)]
mux_pll3_1: None,
#[cfg(stm32h5)]
mux_hsi48_ker: None,
#[cfg(stm32h5)]
mux_lsi_ker: None,
#[cfg(stm32h5)]
mux_pll2_r: pll2.r,
#[cfg(stm32h5)]
mux_rcc_pclk2: Some(apb2),
#[cfg(stm32h5)]
mux_rcc_pclk4: None,
#[cfg(stm32h5)]
mux_hse: hse,
#[cfg(stm32h5)]
mux_hsi48: None,
});
}

View File

@ -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
//
@ -133,6 +134,52 @@ pub struct Clocks {
pub hrtim: Option<Hertz>,
pub rtc: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_rcc_pclk1: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_pll2_q: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_pll3_q: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_hsi_ker: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_csi_ker: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_lse: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_pll1_q: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_pll2_p: Option<Hertz>,
#[cfg(rcc_h5)]
pub mux_pll3_p: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_audioclk: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_per: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_pll3_r: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_rcc_pclk3: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_pll3_1: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_hsi48_ker: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_lsi_ker: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_pll2_r: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_rcc_pclk2: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_rcc_pclk4: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_hse: Option<Hertz>,
#[cfg(stm32h5)]
pub mux_hsi48: Option<Hertz>,
}
#[cfg(feature = "low-power")]
@ -145,14 +192,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

View File

@ -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 ()) {

View File

@ -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"

View File

@ -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));