From 0289630fe429e0a8b84073b740ae839eb8ef5909 Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 12 Apr 2023 18:04:44 -0500 Subject: [PATCH 1/5] stm32/rcc: add i2s pll on some f4 micros --- embassy-stm32/src/rcc/f4.rs | 67 ++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 2a17eb9b..3e2345c6 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -28,11 +28,65 @@ pub struct Config { pub sys_ck: Option, pub pclk1: Option, pub pclk2: Option, + pub plli2s: Option, pub pll48: bool, } -unsafe fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, pll48clk: bool) -> PllResults { +#[cfg(stm32f410)] +unsafe fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { + None +} + +// Not currently implemented, but will be in the future +#[cfg(any(stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))] +unsafe fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { + None +} + +#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] +unsafe fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { + let min_div = 2; + let max_div = 7; + let target = match plli2s { + Some(target) => target, + None => return None, + }; + + // We loop through the possible divider values to find the best configuration. Looping + // through all possible "N" values would result in more iterations. + let (n, outdiv, output, _error) = (min_div..=max_div) + .filter_map(|outdiv| { + let target_vco_out = match target.checked_mul(outdiv) { + Some(x) => x, + None => return None, + }; + let n = (target_vco_out + (vco_in >> 1)) / vco_in; + let vco_out = vco_in * n; + if !(100_000_000..=432_000_000).contains(&vco_out) { + return None; + } + let output = vco_out / outdiv; + let error = (output as i32 - target as i32).unsigned_abs(); + Some((n, outdiv, output, error)) + }) + .min_by_key(|(_, _, _, error)| *error)?; + + RCC.plli2scfgr().modify(|w| { + w.set_plli2sn(n as u16); + w.set_plli2sr(outdiv as u8); + }); + + Some(output) +} + +unsafe fn setup_pll( + pllsrcclk: u32, + use_hse: bool, + pllsysclk: Option, + plli2s: Option, + pll48clk: bool, +) -> PllResults { use crate::pac::rcc::vals::{Pllp, Pllsrc}; let sysclk = pllsysclk.unwrap_or(pllsrcclk); @@ -43,6 +97,7 @@ unsafe fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, pll48 use_pll: false, pllsysclk: None, pll48clk: None, + plli2sclk: None, }; } // Input divisor from PLL source clock, must result to frequency in @@ -101,6 +156,7 @@ unsafe fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, pll48 use_pll: true, pllsysclk: Some(real_pllsysclk), pll48clk: if pll48clk { Some(real_pll48clk) } else { None }, + plli2sclk: setup_i2s_pll(vco_in, plli2s), } } @@ -286,6 +342,7 @@ pub(crate) unsafe fn init(config: Config) { pllsrcclk, config.hse.is_some(), if sysclk_on_pll { Some(sysclk) } else { None }, + config.plli2s.map(|i2s| i2s.0), config.pll48, ); @@ -376,6 +433,13 @@ pub(crate) unsafe fn init(config: Config) { while !RCC.cr().read().pllrdy() {} } + #[cfg(not(stm32f410))] + if plls.plli2sclk.is_some() { + RCC.cr().modify(|w| w.set_plli2son(true)); + + while !RCC.cr().read().plli2srdy() {} + } + RCC.cfgr().modify(|w| { w.set_ppre2(Ppre(ppre2_bits)); w.set_ppre1(Ppre(ppre1_bits)); @@ -416,6 +480,7 @@ struct PllResults { use_pll: bool, pllsysclk: Option, pll48clk: Option, + plli2sclk: Option, } mod max { From c1d5f868714accd6780913e652d8a884368c60d3 Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 12 Apr 2023 18:11:55 -0500 Subject: [PATCH 2/5] stm32/rcc: fix warnings --- embassy-stm32/src/rcc/f4.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 3e2345c6..e8dfba01 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -34,13 +34,13 @@ pub struct Config { } #[cfg(stm32f410)] -unsafe fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { +unsafe fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { None } // Not currently implemented, but will be in the future #[cfg(any(stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))] -unsafe fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { +unsafe fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { None } @@ -480,6 +480,7 @@ struct PllResults { use_pll: bool, pllsysclk: Option, pll48clk: Option, + #[allow(dead_code)] plli2sclk: Option, } From 6a6c673c5fd1baa1d3ca3eebb55ba430a86b1438 Mon Sep 17 00:00:00 2001 From: Grant Miller Date: Thu, 13 Apr 2023 14:21:41 -0500 Subject: [PATCH 3/5] Executor: Replace unnecessary atomics in runqueue --- embassy-executor/src/raw/run_queue.rs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs index a88174a0..f1ec19ac 100644 --- a/embassy-executor/src/raw/run_queue.rs +++ b/embassy-executor/src/raw/run_queue.rs @@ -4,15 +4,16 @@ use core::ptr::NonNull; use atomic_polyfill::{AtomicPtr, Ordering}; use super::{TaskHeader, TaskRef}; +use crate::raw::util::SyncUnsafeCell; pub(crate) struct RunQueueItem { - next: AtomicPtr, + next: SyncUnsafeCell>, } impl RunQueueItem { pub const fn new() -> Self { Self { - next: AtomicPtr::new(ptr::null_mut()), + next: SyncUnsafeCell::new(None), } } } @@ -51,7 +52,12 @@ impl RunQueue { self.head .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |prev| { was_empty = prev.is_null(); - task.header().run_queue_item.next.store(prev, Ordering::Relaxed); + unsafe { + // safety: the pointer is either null or valid + let prev = NonNull::new(prev).map(|ptr| TaskRef::from_ptr(ptr.as_ptr())); + // safety: there are no concurrent accesses to `next` + task.header().run_queue_item.next.set(prev); + } Some(task.as_ptr() as *mut _) }) .ok(); @@ -64,18 +70,19 @@ impl RunQueue { /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { // Atomically empty the queue. - let mut ptr = self.head.swap(ptr::null_mut(), Ordering::AcqRel); + let ptr = self.head.swap(ptr::null_mut(), Ordering::AcqRel); + + // safety: the pointer is either null or valid + let mut next = unsafe { NonNull::new(ptr).map(|ptr| TaskRef::from_ptr(ptr.as_ptr())) }; // Iterate the linked list of tasks that were previously in the queue. - while let Some(task) = NonNull::new(ptr) { - let task = unsafe { TaskRef::from_ptr(task.as_ptr()) }; + while let Some(task) = next { // If the task re-enqueues itself, the `next` pointer will get overwritten. // Therefore, first read the next pointer, and only then process the task. - let next = task.header().run_queue_item.next.load(Ordering::Relaxed); + // safety: there are no concurrent accesses to `next` + next = unsafe { task.header().run_queue_item.next.get() }; on_task(task); - - ptr = next } } } From 650589ab3f030ed63c129245c89e3056bc5f31e5 Mon Sep 17 00:00:00 2001 From: xoviat Date: Fri, 14 Apr 2023 16:30:36 -0500 Subject: [PATCH 4/5] stm32/rcc: add plli2s to Clocks and cfg directives --- embassy-stm32/src/rcc/f4.rs | 8 ++++++++ embassy-stm32/src/rcc/mod.rs | 3 +++ 2 files changed, 11 insertions(+) diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index e8dfba01..5427d2fb 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -28,6 +28,8 @@ pub struct Config { pub sys_ck: Option, pub pclk1: Option, pub pclk2: Option, + + #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] pub plli2s: Option, pub pll48: bool, @@ -342,7 +344,10 @@ pub(crate) unsafe fn init(config: Config) { pllsrcclk, config.hse.is_some(), if sysclk_on_pll { Some(sysclk) } else { None }, + #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] config.plli2s.map(|i2s| i2s.0), + #[cfg(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))] + None, config.pll48, ); @@ -473,6 +478,9 @@ pub(crate) unsafe fn init(config: Config) { ahb3: Hertz(hclk), pll48: plls.pll48clk.map(Hertz), + + #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] + plli2s: plls.plli2sclk.map(Hertz), }); } diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index d6a31f17..7c1e416f 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -60,6 +60,9 @@ pub struct Clocks { #[cfg(any(rcc_f2, rcc_f4, rcc_f410, rcc_f7))] pub pll48: Option, + #[cfg(all(stm32f4, not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))))] + pub plli2s: Option, + #[cfg(stm32f1)] pub adc: Hertz, From f395ec44e8442a3133b080df96da54da18127b97 Mon Sep 17 00:00:00 2001 From: xoviat Date: Fri, 14 Apr 2023 21:28:27 -0500 Subject: [PATCH 5/5] stm32/rcc: add pllsai clock --- embassy-stm32/src/rcc/f4.rs | 5 ++++- embassy-stm32/src/rcc/mod.rs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 5427d2fb..e0929ca4 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -479,8 +479,11 @@ pub(crate) unsafe fn init(config: Config) { pll48: plls.pll48clk.map(Hertz), - #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] + #[cfg(not(stm32f410))] plli2s: plls.plli2sclk.map(Hertz), + + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] + pllsai: None, }); } diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 7c1e416f..d6816d6a 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -60,9 +60,12 @@ pub struct Clocks { #[cfg(any(rcc_f2, rcc_f4, rcc_f410, rcc_f7))] pub pll48: Option, - #[cfg(all(stm32f4, not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))))] + #[cfg(all(rcc_f4, not(stm32f410)))] pub plli2s: Option, + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] + pub pllsai: Option, + #[cfg(stm32f1)] pub adc: Hertz,