Skip to content

Commit 0dee1a4

Browse files
committed
move PllSetup in pll mod
1 parent 513c806 commit 0dee1a4

File tree

2 files changed

+150
-171
lines changed

2 files changed

+150
-171
lines changed

src/rcc/f4/mod.rs

Lines changed: 0 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,6 @@ use super::{BusClock, BusTimerClock, RccBus};
66
use fugit::HertzU32 as Hertz;
77
use fugit::RateExtU32;
88

9-
#[cfg(not(feature = "gpio-f410"))]
10-
use pll::I2sPll;
11-
use pll::MainPll;
12-
#[cfg(feature = "sai")]
13-
#[cfg(not(feature = "gpio-f413"))]
14-
use pll::SaiPll;
15-
169
mod pll;
1710

1811
mod enable;
@@ -449,148 +442,6 @@ impl CFGR {
449442
}
450443
}
451444

452-
impl CFGR {
453-
#[cfg(feature = "gpio-f410")]
454-
#[inline(always)]
455-
fn pll_setup(&self, pllsrcclk: u32, pllsysclk: Option<u32>) -> PllSetup {
456-
let i2s_clocks = self.i2s_clocks();
457-
458-
let main_pll = if let Some(i2s_clk) = i2s_clocks.pll_i2s_clk {
459-
// The I2S frequency is generated by the main PLL. The frequency needs to be accurate,
460-
// so we need an expensive full PLL configuration search.
461-
MainPll::setup_with_i2s(
462-
pllsrcclk,
463-
self.hse.is_some(),
464-
pllsysclk,
465-
self.pll48clk,
466-
i2s_clk,
467-
)
468-
} else {
469-
MainPll::fast_setup(pllsrcclk, self.hse.is_some(), pllsysclk, self.pll48clk)
470-
};
471-
472-
PllSetup {
473-
use_pll: main_pll.use_pll,
474-
pllsysclk: main_pll.pllsysclk,
475-
pll48clk: main_pll.pll48clk,
476-
i2s: i2s_clocks.real(main_pll.plli2sclk, self.i2s_ckin),
477-
}
478-
}
479-
480-
#[cfg(feature = "gpio-f413")]
481-
#[inline(always)]
482-
fn pll_setup(&self, pllsrcclk: u32, pllsysclk: Option<u32>) -> PllSetup {
483-
let rcc = unsafe { &*RCC::ptr() };
484-
485-
let i2s_clocks = self.i2s_clocks();
486-
let sai_clocks = self.sai_clocks();
487-
488-
let main_pll = MainPll::fast_setup(pllsrcclk, self.hse.is_some(), pllsysclk, self.pll48clk);
489-
490-
let (i2s_pll, real_sai_clk) = if let Some(i2s_clk) = i2s_clocks.pll_i2s_clk {
491-
// Currently, we only support generating SAI/PLL clocks with the I2S PLL. This is only
492-
// really usable when the frequencies are identical or the I2S frequency is a multiple of
493-
// the SAI frequency. Therefore, we just optimize the PLL for the I2S frequency and then
494-
// derive the SAI frequency from the I2S frequency.
495-
let i2s_pll = I2sPll::setup(pllsrcclk, Some(i2s_clk));
496-
497-
if let Some(sai_clk) = sai_clocks.pll_sai_clk {
498-
let div = u32::min(
499-
u32::max((i2s_pll.plli2sclk.unwrap() + (sai_clk >> 1)) / sai_clk, 1),
500-
31,
501-
);
502-
rcc.dckcfgr().modify(|_, w| w.plli2sdivr().set(div as u8));
503-
let real_sai_clk = sai_clk / div;
504-
(i2s_pll, Some(real_sai_clk))
505-
} else {
506-
(i2s_pll, None)
507-
}
508-
} else if let Some(pll_sai_clk) = sai_clocks.pll_sai_clk {
509-
// We try all divider values to get the best approximation of the requested frequency.
510-
// NOTE: STM32F413/423 have a different divider range than other models!
511-
let (i2s_pll, real_sai_clk, div) = (1..31)
512-
.map(|div| {
513-
let i2s_pll = I2sPll::setup(pllsrcclk, Some(pll_sai_clk * div));
514-
let real_clk = i2s_pll.plli2sclk.unwrap() / div;
515-
(i2s_pll, real_clk, div)
516-
})
517-
.min_by_key(|(_, real_clk, _)| (*real_clk as i32 - pll_sai_clk as i32).abs())
518-
.unwrap();
519-
rcc.dckcfgr().modify(|_, w| w.plli2sdivr().set(div as u8));
520-
(i2s_pll, Some(real_sai_clk))
521-
} else {
522-
(I2sPll::unused(), None)
523-
};
524-
525-
PllSetup {
526-
use_pll: main_pll.use_pll,
527-
use_i2spll: i2s_pll.use_pll,
528-
pllsysclk: main_pll.pllsysclk,
529-
pll48clk: main_pll.pll48clk,
530-
i2s: i2s_clocks.real(i2s_pll.plli2sclk, self.i2s_ckin),
531-
sai: sai_clocks.real(real_sai_clk, self.i2s_ckin),
532-
}
533-
}
534-
535-
#[cfg(any(feature = "gpio-f411", feature = "gpio-f412", feature = "gpio-f446"))]
536-
#[inline(always)]
537-
fn pll_setup(&self, pllsrcclk: u32, pllsysclk: Option<u32>) -> PllSetup {
538-
let i2s_clocks = self.i2s_clocks();
539-
#[cfg(feature = "sai")]
540-
let sai_clocks = self.sai_clocks();
541-
542-
// All PLLs are completely independent.
543-
let main_pll = MainPll::fast_setup(pllsrcclk, self.hse.is_some(), pllsysclk, self.pll48clk);
544-
let i2s_pll = I2sPll::setup(pllsrcclk, i2s_clocks.pll_i2s_clk);
545-
#[cfg(feature = "sai")]
546-
let sai_pll = SaiPll::setup(pllsrcclk, sai_clocks.pll_sai_clk);
547-
548-
PllSetup {
549-
use_pll: main_pll.use_pll,
550-
use_i2spll: i2s_pll.use_pll,
551-
#[cfg(feature = "sai")]
552-
use_saipll: sai_pll.use_pll,
553-
pllsysclk: main_pll.pllsysclk,
554-
pll48clk: main_pll.pll48clk,
555-
i2s: i2s_clocks.real(i2s_pll.plli2sclk, self.i2s_ckin),
556-
#[cfg(feature = "sai")]
557-
sai: sai_clocks.real(sai_pll.sai_clk, self.i2s_ckin),
558-
}
559-
}
560-
561-
#[cfg(any(
562-
feature = "gpio-f401",
563-
feature = "gpio-f417",
564-
feature = "gpio-f427",
565-
feature = "gpio-f469",
566-
))]
567-
#[inline(always)]
568-
fn pll_setup(&self, pllsrcclk: u32, pllsysclk: Option<u32>) -> PllSetup {
569-
let i2s_clocks = self.i2s_clocks();
570-
#[cfg(any(feature = "gpio-f427", feature = "gpio-f469"))]
571-
let sai_clocks = self.sai_clocks();
572-
573-
// We have separate PLLs, but they share the "M" divider.
574-
let main_pll = MainPll::fast_setup(pllsrcclk, self.hse.is_some(), pllsysclk, self.pll48clk);
575-
let i2s_pll = I2sPll::setup_shared_m(pllsrcclk, main_pll.m, i2s_clocks.pll_i2s_clk);
576-
#[cfg(feature = "sai")]
577-
let sai_pll =
578-
SaiPll::setup_shared_m(pllsrcclk, main_pll.m.or(i2s_pll.m), sai_clocks.pll_sai_clk);
579-
580-
PllSetup {
581-
use_pll: main_pll.use_pll,
582-
use_i2spll: i2s_pll.use_pll,
583-
#[cfg(feature = "sai")]
584-
use_saipll: sai_pll.use_pll,
585-
pllsysclk: main_pll.pllsysclk,
586-
pll48clk: main_pll.pll48clk,
587-
i2s: i2s_clocks.real(i2s_pll.plli2sclk, self.i2s_ckin),
588-
#[cfg(feature = "sai")]
589-
sai: sai_clocks.real(sai_pll.sai_clk, self.i2s_ckin),
590-
}
591-
}
592-
}
593-
594445
#[cfg(feature = "sai")]
595446
impl CFGR {
596447
fn sai_clocks(&self) -> SaiClocks {
@@ -703,7 +554,6 @@ impl CFGR {
703554
fn freeze_internal(self, unchecked: bool) -> Clocks {
704555
let rcc = unsafe { &*RCC::ptr() };
705556

706-
//let (use_pll, sysclk_on_pll, sysclk, pll48clk) = self.pll_setup();
707557
let pllsrcclk = self.hse.unwrap_or(HSI);
708558
let sysclk = self.sysclk.unwrap_or(pllsrcclk);
709559
let sysclk_on_pll = sysclk != pllsrcclk;
@@ -893,25 +743,6 @@ impl CFGR {
893743
}
894744
}
895745

896-
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
897-
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
898-
struct PllSetup {
899-
use_pll: bool,
900-
#[cfg(not(feature = "gpio-f410"))]
901-
use_i2spll: bool,
902-
#[cfg(feature = "sai")]
903-
#[cfg(not(feature = "gpio-f413"))]
904-
use_saipll: bool,
905-
906-
pllsysclk: Option<u32>,
907-
pll48clk: Option<u32>,
908-
909-
i2s: RealI2sClocks,
910-
911-
#[cfg(feature = "sai")]
912-
sai: RealSaiClocks,
913-
}
914-
915746
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
916747
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
917748
struct I2sClocks {

src/rcc/f4/pll.rs

Lines changed: 150 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,152 @@
11
use crate::pac::RCC;
22

3+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
4+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
5+
pub struct PllSetup {
6+
pub use_pll: bool,
7+
pub pllsysclk: Option<u32>,
8+
pub pll48clk: Option<u32>,
9+
10+
#[cfg(not(feature = "gpio-f410"))]
11+
pub use_i2spll: bool,
12+
pub(super) i2s: super::RealI2sClocks,
13+
14+
#[cfg(feature = "sai")]
15+
#[cfg(not(feature = "gpio-f413"))]
16+
pub use_saipll: bool,
17+
#[cfg(feature = "sai")]
18+
pub(super) sai: super::RealSaiClocks,
19+
}
20+
21+
impl super::CFGR {
22+
#[cfg(feature = "gpio-f410")]
23+
#[inline(always)]
24+
pub fn pll_setup(&self, pllsrcclk: u32, pllsysclk: Option<u32>) -> PllSetup {
25+
let i2s_clocks = self.i2s_clocks();
26+
27+
let main_pll = if let Some(i2s_clk) = i2s_clocks.pll_i2s_clk {
28+
// The I2S frequency is generated by the main PLL. The frequency needs to be accurate,
29+
// so we need an expensive full PLL configuration search.
30+
MainPll::setup_with_i2s(
31+
pllsrcclk,
32+
self.hse.is_some(),
33+
pllsysclk,
34+
self.pll48clk,
35+
i2s_clk,
36+
)
37+
} else {
38+
MainPll::fast_setup(pllsrcclk, self.hse.is_some(), pllsysclk, self.pll48clk)
39+
};
40+
41+
PllSetup {
42+
use_pll: main_pll.use_pll,
43+
pllsysclk: main_pll.pllsysclk,
44+
pll48clk: main_pll.pll48clk,
45+
46+
i2s: i2s_clocks.real(main_pll.plli2sclk, self.i2s_ckin),
47+
}
48+
}
49+
50+
#[cfg(feature = "gpio-f413")]
51+
#[inline(always)]
52+
pub fn pll_setup(&self, pllsrcclk: u32, pllsysclk: Option<u32>) -> PllSetup {
53+
let rcc = unsafe { &*RCC::ptr() };
54+
55+
let i2s_clocks = self.i2s_clocks();
56+
let sai_clocks = self.sai_clocks();
57+
58+
let main_pll = MainPll::fast_setup(pllsrcclk, self.hse.is_some(), pllsysclk, self.pll48clk);
59+
60+
let (i2s_pll, real_sai_clk) = if let Some(i2s_clk) = i2s_clocks.pll_i2s_clk {
61+
// Currently, we only support generating SAI/PLL clocks with the I2S PLL. This is only
62+
// really usable when the frequencies are identical or the I2S frequency is a multiple of
63+
// the SAI frequency. Therefore, we just optimize the PLL for the I2S frequency and then
64+
// derive the SAI frequency from the I2S frequency.
65+
let i2s_pll = I2sPll::setup(pllsrcclk, Some(i2s_clk));
66+
67+
if let Some(sai_clk) = sai_clocks.pll_sai_clk {
68+
let div = u32::min(
69+
u32::max((i2s_pll.plli2sclk.unwrap() + (sai_clk >> 1)) / sai_clk, 1),
70+
31,
71+
);
72+
rcc.dckcfgr().modify(|_, w| w.plli2sdivr().set(div as u8));
73+
let real_sai_clk = sai_clk / div;
74+
(i2s_pll, Some(real_sai_clk))
75+
} else {
76+
(i2s_pll, None)
77+
}
78+
} else if let Some(pll_sai_clk) = sai_clocks.pll_sai_clk {
79+
// We try all divider values to get the best approximation of the requested frequency.
80+
// NOTE: STM32F413/423 have a different divider range than other models!
81+
let (i2s_pll, real_sai_clk, div) = (1..31)
82+
.map(|div| {
83+
let i2s_pll = I2sPll::setup(pllsrcclk, Some(pll_sai_clk * div));
84+
let real_clk = i2s_pll.plli2sclk.unwrap() / div;
85+
(i2s_pll, real_clk, div)
86+
})
87+
.min_by_key(|(_, real_clk, _)| (*real_clk as i32 - pll_sai_clk as i32).abs())
88+
.unwrap();
89+
rcc.dckcfgr().modify(|_, w| w.plli2sdivr().set(div as u8));
90+
(i2s_pll, Some(real_sai_clk))
91+
} else {
92+
(I2sPll::unused(), None)
93+
};
94+
95+
PllSetup {
96+
use_pll: main_pll.use_pll,
97+
pllsysclk: main_pll.pllsysclk,
98+
pll48clk: main_pll.pll48clk,
99+
100+
use_i2spll: i2s_pll.use_pll,
101+
i2s: i2s_clocks.real(i2s_pll.plli2sclk, self.i2s_ckin),
102+
103+
sai: sai_clocks.real(real_sai_clk, self.i2s_ckin),
104+
}
105+
}
106+
107+
#[cfg(not(any(feature = "gpio-f410", feature = "gpio-f413")))]
108+
#[inline(always)]
109+
pub fn pll_setup(&self, pllsrcclk: u32, pllsysclk: Option<u32>) -> PllSetup {
110+
let i2s_clocks = self.i2s_clocks();
111+
#[cfg(feature = "sai")]
112+
let sai_clocks = self.sai_clocks();
113+
114+
// All PLLs are completely independent.
115+
let main_pll = MainPll::fast_setup(pllsrcclk, self.hse.is_some(), pllsysclk, self.pll48clk);
116+
117+
#[cfg(any(feature = "gpio-f411", feature = "gpio-f412", feature = "gpio-f446"))]
118+
let i2s_pll = I2sPll::setup(pllsrcclk, i2s_clocks.pll_i2s_clk);
119+
#[cfg(any(
120+
feature = "gpio-f401",
121+
feature = "gpio-f417",
122+
feature = "gpio-f427",
123+
feature = "gpio-f469",
124+
))]
125+
// We have separate PLLs, but they share the "M" divider.
126+
let i2s_pll = I2sPll::setup_shared_m(pllsrcclk, main_pll.m, i2s_clocks.pll_i2s_clk);
127+
128+
#[cfg(any(feature = "gpio-f446"))]
129+
let sai_pll = SaiPll::setup(pllsrcclk, sai_clocks.pll_sai_clk);
130+
#[cfg(any(feature = "gpio-f427", feature = "gpio-f469"))]
131+
let sai_pll =
132+
SaiPll::setup_shared_m(pllsrcclk, main_pll.m.or(i2s_pll.m), sai_clocks.pll_sai_clk);
133+
134+
PllSetup {
135+
use_pll: main_pll.use_pll,
136+
pllsysclk: main_pll.pllsysclk,
137+
pll48clk: main_pll.pll48clk,
138+
139+
use_i2spll: i2s_pll.use_pll,
140+
i2s: i2s_clocks.real(i2s_pll.plli2sclk, self.i2s_ckin),
141+
142+
#[cfg(feature = "sai")]
143+
use_saipll: sai_pll.use_pll,
144+
#[cfg(feature = "sai")]
145+
sai: sai_clocks.real(sai_pll.sai_clk, self.i2s_ckin),
146+
}
147+
}
148+
}
149+
3150
pub struct MainPll {
4151
pub use_pll: bool,
5152
pub pllsysclk: Option<u32>,
@@ -102,8 +249,10 @@ impl MainPll {
102249
plli2sclk: None,
103250
}
104251
}
252+
}
105253

106-
#[cfg(feature = "gpio-f410")]
254+
#[cfg(feature = "gpio-f410")]
255+
impl MainPll {
107256
pub fn setup_with_i2s(
108257
pllsrcclk: u32,
109258
use_hse: bool,
@@ -191,7 +340,6 @@ impl MainPll {
191340
}
192341
}
193342

194-
#[cfg(feature = "gpio-f410")]
195343
fn best_divider(
196344
vco_out: u32,
197345
min: u32,

0 commit comments

Comments
 (0)