Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
eba55543be |
@ -15,6 +15,7 @@ embassy-time = { version = "0.1.3", path = "../embassy-time"}
|
|||||||
embassy-sync = { version = "0.3.0", path = "../embassy-sync"}
|
embassy-sync = { version = "0.3.0", path = "../embassy-sync"}
|
||||||
embassy-futures = { version = "0.1.0", path = "../embassy-futures"}
|
embassy-futures = { version = "0.1.0", path = "../embassy-futures"}
|
||||||
embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"}
|
embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"}
|
||||||
|
atomic-polyfill = "0.1.5"
|
||||||
|
|
||||||
defmt = { version = "0.3", optional = true }
|
defmt = { version = "0.3", optional = true }
|
||||||
log = { version = "0.4.17", optional = true }
|
log = { version = "0.4.17", optional = true }
|
||||||
|
@ -64,3 +64,4 @@ stable_deref_trait = { version = "1.2.0", default-features = false }
|
|||||||
futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] }
|
futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] }
|
||||||
atomic-pool = "1.0"
|
atomic-pool = "1.0"
|
||||||
embedded-nal-async = { version = "0.6.0", optional = true }
|
embedded-nal-async = { version = "0.6.0", optional = true }
|
||||||
|
atomic-polyfill = { version = "1.0" }
|
||||||
|
@ -579,10 +579,11 @@ mod embedded_io_impls {
|
|||||||
/// TCP client compatible with `embedded-nal-async` traits.
|
/// TCP client compatible with `embedded-nal-async` traits.
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
pub mod client {
|
pub mod client {
|
||||||
use core::cell::{Cell, UnsafeCell};
|
use core::cell::UnsafeCell;
|
||||||
use core::mem::MaybeUninit;
|
use core::mem::MaybeUninit;
|
||||||
use core::ptr::NonNull;
|
use core::ptr::NonNull;
|
||||||
|
|
||||||
|
use atomic_polyfill::{AtomicBool, Ordering};
|
||||||
use embedded_nal_async::IpAddr;
|
use embedded_nal_async::IpAddr;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -701,13 +702,15 @@ 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> {
|
struct Pool<T, const N: usize> {
|
||||||
used: [Cell<bool>; N],
|
used: [AtomicBool; N],
|
||||||
data: [UnsafeCell<MaybeUninit<T>>; N],
|
data: [UnsafeCell<MaybeUninit<T>>; N],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, const N: usize> Pool<T, N> {
|
impl<T, const N: usize> Pool<T, N> {
|
||||||
const VALUE: Cell<bool> = Cell::new(false);
|
const VALUE: AtomicBool = AtomicBool::new(false);
|
||||||
const UNINIT: UnsafeCell<MaybeUninit<T>> = UnsafeCell::new(MaybeUninit::uninit());
|
const UNINIT: UnsafeCell<MaybeUninit<T>> = UnsafeCell::new(MaybeUninit::uninit());
|
||||||
|
|
||||||
const fn new() -> Self {
|
const fn new() -> Self {
|
||||||
@ -721,9 +724,7 @@ pub mod client {
|
|||||||
impl<T, const N: usize> Pool<T, N> {
|
impl<T, const N: usize> Pool<T, N> {
|
||||||
fn alloc(&self) -> Option<NonNull<T>> {
|
fn alloc(&self) -> Option<NonNull<T>> {
|
||||||
for n in 0..N {
|
for n in 0..N {
|
||||||
// this can't race because Pool is not Sync.
|
if self.used[n].swap(true, Ordering::SeqCst) == false {
|
||||||
if !self.used[n].get() {
|
|
||||||
self.used[n].set(true);
|
|
||||||
let p = self.data[n].get() as *mut T;
|
let p = self.data[n].get() as *mut T;
|
||||||
return Some(unsafe { NonNull::new_unchecked(p) });
|
return Some(unsafe { NonNull::new_unchecked(p) });
|
||||||
}
|
}
|
||||||
@ -737,7 +738,7 @@ pub mod client {
|
|||||||
let n = p.as_ptr().offset_from(origin);
|
let n = p.as_ptr().offset_from(origin);
|
||||||
assert!(n >= 0);
|
assert!(n >= 0);
|
||||||
assert!((n as usize) < N);
|
assert!((n as usize) < N);
|
||||||
self.used[n as usize].set(false);
|
self.used[n as usize].store(false, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,7 @@ rand_core = "0.6.3"
|
|||||||
sdio-host = "0.5.0"
|
sdio-host = "0.5.0"
|
||||||
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
|
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
|
||||||
critical-section = "1.1"
|
critical-section = "1.1"
|
||||||
|
atomic-polyfill = "1.0.1"
|
||||||
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-6bfa5a0dcec6a9bd42cea94ba11eeae1a17a7f2c" }
|
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-6bfa5a0dcec6a9bd42cea94ba11eeae1a17a7f2c" }
|
||||||
vcell = "0.1.3"
|
vcell = "0.1.3"
|
||||||
bxcan = "0.7.0"
|
bxcan = "0.7.0"
|
||||||
|
@ -5,36 +5,9 @@ use std::{env, fs};
|
|||||||
|
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use stm32_metapac::metadata::ir::{BlockItemInner, Enum};
|
use stm32_metapac::metadata::{MemoryRegionKind, METADATA};
|
||||||
use stm32_metapac::metadata::{MemoryRegionKind, PeripheralRccRegister, METADATA};
|
|
||||||
|
|
||||||
fn main() {
|
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()
|
let chip_name = match env::vars()
|
||||||
.map(|(a, _)| a)
|
.map(|(a, _)| a)
|
||||||
.filter(|x| x.starts_with("CARGO_FEATURE_STM32"))
|
.filter(|x| x.starts_with("CARGO_FEATURE_STM32"))
|
||||||
@ -388,51 +361,6 @@ 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
|
// Generate RccPeripheral impls
|
||||||
|
|
||||||
@ -500,77 +428,26 @@ fn main() {
|
|||||||
(TokenStream::new(), TokenStream::new())
|
(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! {
|
g.extend(quote! {
|
||||||
impl crate::rcc::sealed::RccPeripheral for peripherals::#pname {
|
impl crate::rcc::sealed::RccPeripheral for peripherals::#pname {
|
||||||
fn frequency() -> crate::time::Hertz {
|
fn frequency() -> crate::time::Hertz {
|
||||||
#clock_frequency
|
unsafe { crate::rcc::get_freqs().#clk }
|
||||||
}
|
}
|
||||||
fn enable() {
|
fn enable() {
|
||||||
critical_section::with(|_cs| {
|
critical_section::with(|_| {
|
||||||
#before_enable
|
#before_enable
|
||||||
#[cfg(feature = "low-power")]
|
#[cfg(feature = "low-power")]
|
||||||
crate::rcc::clock_refcount_add(_cs);
|
crate::rcc::clock_refcount_add();
|
||||||
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
|
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
|
||||||
#after_enable
|
#after_enable
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn disable() {
|
fn disable() {
|
||||||
critical_section::with(|_cs| {
|
critical_section::with(|_| {
|
||||||
#before_disable
|
#before_disable
|
||||||
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
|
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
|
||||||
#[cfg(feature = "low-power")]
|
#[cfg(feature = "low-power")]
|
||||||
crate::rcc::clock_refcount_sub(_cs);
|
crate::rcc::clock_refcount_sub();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn reset() {
|
fn reset() {
|
||||||
@ -583,14 +460,12 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let refcount_mod: TokenStream = refcount_statics
|
let mut refcount_mod = TokenStream::new();
|
||||||
.iter()
|
for refcount_static in refcount_statics {
|
||||||
.map(|refcount_static| {
|
refcount_mod.extend(quote! {
|
||||||
quote! {
|
pub(crate) static mut #refcount_static: u8 = 0;
|
||||||
pub(crate) static mut #refcount_static: u8 = 0;
|
});
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
g.extend(quote! {
|
g.extend(quote! {
|
||||||
mod refcount_statics {
|
mod refcount_statics {
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
use core::pin::Pin;
|
use core::pin::Pin;
|
||||||
use core::sync::atomic::{fence, AtomicUsize, Ordering};
|
use core::sync::atomic::{fence, Ordering};
|
||||||
use core::task::{Context, Poll, Waker};
|
use core::task::{Context, Poll, Waker};
|
||||||
|
|
||||||
|
use atomic_polyfill::AtomicUsize;
|
||||||
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
|
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
|
||||||
use embassy_sync::waitqueue::AtomicWaker;
|
use embassy_sync::waitqueue::AtomicWaker;
|
||||||
|
|
||||||
@ -126,13 +127,7 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: usize, index
|
|||||||
} else if isr.tcif(channel_num) && cr.read().tcie() {
|
} else if isr.tcif(channel_num) && cr.read().tcie() {
|
||||||
// Acknowledge transfer complete interrupt
|
// Acknowledge transfer complete interrupt
|
||||||
dma.ifcr().write(|w| w.set_tcif(channel_num, true));
|
dma.ifcr().write(|w| w.set_tcif(channel_num, true));
|
||||||
#[cfg(not(armv6m))]
|
|
||||||
STATE.complete_count[index].fetch_add(1, Ordering::Release);
|
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 {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -396,14 +391,7 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn reset_complete_count(&mut self) -> usize {
|
fn reset_complete_count(&mut self) -> usize {
|
||||||
#[cfg(not(armv6m))]
|
STATE.complete_count[self.0.index()].swap(0, Ordering::AcqRel)
|
||||||
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) {
|
fn set_waker(&mut self, waker: &Waker) {
|
||||||
|
@ -225,9 +225,7 @@ pub fn init(config: Config) -> Peripherals {
|
|||||||
|
|
||||||
#[cfg(feature = "low-power")]
|
#[cfg(feature = "low-power")]
|
||||||
while !crate::rcc::low_power_ready() {
|
while !crate::rcc::low_power_ready() {
|
||||||
critical_section::with(|cs| {
|
crate::rcc::clock_refcount_sub();
|
||||||
crate::rcc::clock_refcount_sub(cs);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::sync::atomic::{compiler_fence, Ordering};
|
|
||||||
|
|
||||||
|
use atomic_polyfill::{compiler_fence, Ordering};
|
||||||
use cortex_m::peripheral::SCB;
|
use cortex_m::peripheral::SCB;
|
||||||
use embassy_executor::*;
|
use embassy_executor::*;
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
let pll1 = init_pll(0, config.pll1, &pll_input);
|
let pll1 = init_pll(0, config.pll1, &pll_input);
|
||||||
let pll2 = init_pll(1, config.pll2, &pll_input);
|
let pll2 = init_pll(1, config.pll2, &pll_input);
|
||||||
#[cfg(any(rcc_h5, stm32h7))]
|
#[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
|
// Configure sysclk
|
||||||
let (sys, sw) = match config.sys {
|
let (sys, sw) = match config.sys {
|
||||||
@ -447,7 +447,7 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
#[cfg(stm32h7)]
|
#[cfg(stm32h7)]
|
||||||
let adc = match config.adc_clock_source {
|
let adc = match config.adc_clock_source {
|
||||||
AdcClockSource::PLL2_P => pll2.p,
|
AdcClockSource::PLL2_P => pll2.p,
|
||||||
AdcClockSource::PLL3_R => pll3.r,
|
AdcClockSource::PLL3_R => _pll3.r,
|
||||||
AdcClockSource::PER => _per_ck,
|
AdcClockSource::PER => _per_ck,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
@ -545,53 +545,6 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
apb2_tim,
|
apb2_tim,
|
||||||
adc,
|
adc,
|
||||||
rtc,
|
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,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,10 +27,9 @@ pub use mco::*;
|
|||||||
#[cfg_attr(rcc_wba, path = "wba.rs")]
|
#[cfg_attr(rcc_wba, path = "wba.rs")]
|
||||||
#[cfg_attr(any(rcc_wl5, rcc_wle), path = "wl.rs")]
|
#[cfg_attr(any(rcc_wl5, rcc_wle), path = "wl.rs")]
|
||||||
mod _version;
|
mod _version;
|
||||||
#[cfg(feature = "low-power")]
|
|
||||||
use core::sync::atomic::{AtomicU32, Ordering};
|
|
||||||
|
|
||||||
pub use _version::*;
|
pub use _version::*;
|
||||||
|
#[cfg(feature = "low-power")]
|
||||||
|
use atomic_polyfill::{AtomicU32, Ordering};
|
||||||
|
|
||||||
// Model Clock Configuration
|
// Model Clock Configuration
|
||||||
//
|
//
|
||||||
@ -134,52 +133,6 @@ pub struct Clocks {
|
|||||||
pub hrtim: Option<Hertz>,
|
pub hrtim: Option<Hertz>,
|
||||||
|
|
||||||
pub rtc: 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")]
|
#[cfg(feature = "low-power")]
|
||||||
@ -192,17 +145,14 @@ pub fn low_power_ready() -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "low-power")]
|
#[cfg(feature = "low-power")]
|
||||||
pub(crate) fn clock_refcount_add(_cs: critical_section::CriticalSection) {
|
pub(crate) fn clock_refcount_add() {
|
||||||
// We don't check for overflow because constructing more than u32 peripherals is unlikely
|
// We don't check for overflow because constructing more than u32 peripherals is unlikely
|
||||||
let n = CLOCK_REFCOUNT.load(Ordering::Relaxed);
|
CLOCK_REFCOUNT.fetch_add(1, Ordering::Relaxed);
|
||||||
CLOCK_REFCOUNT.store(n + 1, Ordering::Relaxed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "low-power")]
|
#[cfg(feature = "low-power")]
|
||||||
pub(crate) fn clock_refcount_sub(_cs: critical_section::CriticalSection) {
|
pub(crate) fn clock_refcount_sub() {
|
||||||
let n = CLOCK_REFCOUNT.load(Ordering::Relaxed);
|
assert!(CLOCK_REFCOUNT.fetch_sub(1, Ordering::Relaxed) != 0);
|
||||||
assert!(n != 0);
|
|
||||||
CLOCK_REFCOUNT.store(n - 1, Ordering::Relaxed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Frozen clock frequencies
|
/// Frozen clock frequencies
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
use core::sync::atomic::{compiler_fence, AtomicU32, AtomicU8, Ordering};
|
use core::sync::atomic::{compiler_fence, Ordering};
|
||||||
use core::{mem, ptr};
|
use core::{mem, ptr};
|
||||||
|
|
||||||
|
use atomic_polyfill::{AtomicU32, AtomicU8};
|
||||||
use critical_section::CriticalSection;
|
use critical_section::CriticalSection;
|
||||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
use embassy_sync::blocking_mutex::Mutex;
|
use embassy_sync::blocking_mutex::Mutex;
|
||||||
@ -228,9 +229,7 @@ impl RtcDriver {
|
|||||||
fn next_period(&self) {
|
fn next_period(&self) {
|
||||||
let r = T::regs_gp16();
|
let r = T::regs_gp16();
|
||||||
|
|
||||||
// We only modify the period from the timer interrupt, so we know this can't race.
|
let period = self.period.fetch_add(1, Ordering::Relaxed) + 1;
|
||||||
let period = self.period.load(Ordering::Relaxed) + 1;
|
|
||||||
self.period.store(period, Ordering::Relaxed);
|
|
||||||
let t = (period as u64) << 15;
|
let t = (period as u64) << 15;
|
||||||
|
|
||||||
critical_section::with(move |cs| {
|
critical_section::with(move |cs| {
|
||||||
@ -404,15 +403,18 @@ impl Driver for RtcDriver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> {
|
unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> {
|
||||||
critical_section::with(|_| {
|
let id = self.alarm_count.fetch_update(Ordering::AcqRel, Ordering::Acquire, |x| {
|
||||||
let id = self.alarm_count.load(Ordering::Relaxed);
|
if x < ALARM_COUNT as u8 {
|
||||||
if id < ALARM_COUNT as u8 {
|
Some(x + 1)
|
||||||
self.alarm_count.store(id + 1, Ordering::Relaxed);
|
|
||||||
Some(AlarmHandle::new(id))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
|
match id {
|
||||||
|
Ok(id) => Some(AlarmHandle::new(id)),
|
||||||
|
Err(_) => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_alarm_callback(&self, alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) {
|
fn set_alarm_callback(&self, alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) {
|
||||||
|
@ -218,6 +218,7 @@ embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1", optional =
|
|||||||
embedded-hal-async = { version = "=1.0.0-rc.1", optional = true}
|
embedded-hal-async = { version = "=1.0.0-rc.1", optional = true}
|
||||||
|
|
||||||
futures-util = { version = "0.3.17", default-features = false }
|
futures-util = { version = "0.3.17", default-features = false }
|
||||||
|
atomic-polyfill = "1.0.1"
|
||||||
critical-section = "1.1"
|
critical-section = "1.1"
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
heapless = "0.7"
|
heapless = "0.7"
|
||||||
|
@ -1,3 +1,18 @@
|
|||||||
|
[unstable]
|
||||||
|
# enabling these breaks the float tests during linking, with intrinsics
|
||||||
|
# duplicated between embassy-rp and compilter_builtins
|
||||||
|
build-std = ["core"]
|
||||||
|
build-std-features = ["panic_immediate_abort"]
|
||||||
|
|
||||||
|
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
||||||
|
runner = "teleprobe client run"
|
||||||
|
#runner = "teleprobe local run --chip RP2040 --elf"
|
||||||
|
|
||||||
|
rustflags = [
|
||||||
|
# Code-size optimizations.
|
||||||
|
"-Z", "trap-unreachable=no",
|
||||||
|
]
|
||||||
|
|
||||||
[target.thumbv6m-none-eabi]
|
[target.thumbv6m-none-eabi]
|
||||||
runner = 'probe-rs run --chip STM32F091RCTX'
|
runner = 'probe-rs run --chip STM32F091RCTX'
|
||||||
|
|
||||||
|
@ -8,16 +8,16 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Change stm32f091rc to your chip name, if necessary.
|
# Change stm32f091rc to your chip name, if necessary.
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "memory-x", "stm32f091rc", "time-driver-any", "exti", "unstable-pac"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "memory-x", "stm32f091rc", "time-driver-any", "unstable-pac"] }
|
||||||
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
|
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
|
||||||
cortex-m-rt = "0.7.0"
|
cortex-m-rt = "0.7.0"
|
||||||
defmt = "0.3"
|
embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = [] }
|
||||||
defmt-rtt = "0.4"
|
embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "integrated-timers"] }
|
||||||
panic-probe = "0.3"
|
embassy-time = { version = "0.1.3", path = "../../embassy-time", features = [ "tick-hz-32_768"] }
|
||||||
embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
|
|
||||||
embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
|
|
||||||
embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
|
||||||
static_cell = { version = "1.1", features = ["nightly"]}
|
static_cell = { version = "1.1", features = ["nightly"]}
|
||||||
|
panic-halt = "0.2.0"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
debug = 2
|
debug = 2
|
||||||
|
opt-level = 's'
|
||||||
|
lto = 'fat'
|
@ -1,5 +1,4 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
println!("cargo:rustc-link-arg-bins=--nmagic");
|
println!("cargo:rustc-link-arg-bins=--nmagic");
|
||||||
println!("cargo:rustc-link-arg-bins=-Tlink.x");
|
println!("cargo:rustc-link-arg-bins=-Tlink.x");
|
||||||
println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
|
|
||||||
}
|
}
|
||||||
|
@ -2,26 +2,21 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
use defmt::*;
|
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use panic_halt as _;
|
||||||
|
|
||||||
// main is itself an async function.
|
// main is itself an async function.
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
info!("Hello World!");
|
|
||||||
//PA5 is the onboard LED on the Nucleo F091RC
|
//PA5 is the onboard LED on the Nucleo F091RC
|
||||||
let mut led = Output::new(p.PA5, Level::High, Speed::Low);
|
let mut led = Output::new(p.PA5, Level::High, Speed::Low);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
info!("high");
|
|
||||||
led.set_high();
|
led.set_high();
|
||||||
Timer::after(Duration::from_millis(300)).await;
|
Timer::after(Duration::from_millis(300)).await;
|
||||||
|
|
||||||
info!("low");
|
|
||||||
led.set_low();
|
led.set_low();
|
||||||
Timer::after(Duration::from_millis(300)).await;
|
Timer::after(Duration::from_millis(300)).await;
|
||||||
}
|
}
|
||||||
|
@ -105,8 +105,8 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
|
|
||||||
info!("Network task initialized");
|
info!("Network task initialized");
|
||||||
|
|
||||||
let state: TcpClientState<1, 1024, 1024> = TcpClientState::new();
|
static STATE: TcpClientState<1, 1024, 1024> = TcpClientState::new();
|
||||||
let client = TcpClient::new(&stack, &state);
|
let client = TcpClient::new(&stack, &STATE);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(10, 42, 0, 1), 8000));
|
let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(10, 42, 0, 1), 8000));
|
||||||
|
Reference in New Issue
Block a user