Skip to content

Commit 1d16f3f

Browse files
committed
Improve error diagnostics when kernel clocks are stopped
* More helpful panic messages that name the consumer and the stopped clock * Expose more of these methods in the public API * Standardise around `kernel_clk`/`kernel_clk_unwrap` naming (excluding timers)
1 parent 946d54b commit 1d16f3f

File tree

15 files changed

+237
-74
lines changed

15 files changed

+237
-74
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
* Rename the PeripheralREC object for BDMA2 on 7B3, 7B0, 7A3 parts from BDMA to BDMA2
1414
* pac: Upgrade to stm32-rs v0.14.0
1515
* Add "rt" to the default features
16+
* **Breaking**: `qspi` flag renamed to `xspi`
17+
* **Breaking**: SAI `sai_[ab]_ker_ck` methods now return `Hertz` rather than
18+
`Option<Hertz>` and if the clock is stopped they panic with a message.
1619

1720
* ethernet: `ethernet::DesRing` and `ethernet::EthernetDMA` require generic
1821
constants to specify how many transmit / receive buffers to include in

src/adc.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -330,12 +330,17 @@ pub struct StoredConfig(AdcSampleTime, Resolution, AdcLshift);
330330
fn check_clock(prec: &impl AdcClkSelGetter, clocks: &CoreClocks) -> Hertz {
331331
// Select Kernel Clock
332332
let adc_clock = match prec.get_kernel_clk_mux() {
333-
Some(rec::AdcClkSel::PLL2_P) => clocks.pll2_p_ck(),
334-
Some(rec::AdcClkSel::PLL3_R) => clocks.pll3_r_ck(),
335-
Some(rec::AdcClkSel::PER) => clocks.per_ck(),
333+
Some(rec::AdcClkSel::PLL2_P) => {
334+
clocks.pll2_p_ck().expect("ADC: PLL2_P must be enabled")
335+
}
336+
Some(rec::AdcClkSel::PLL3_R) => {
337+
clocks.pll3_r_ck().expect("ADC: PLL3_R must be enabled")
338+
}
339+
Some(rec::AdcClkSel::PER) => {
340+
clocks.per_ck().expect("ADC: PER clock must be enabled")
341+
}
336342
_ => unreachable!(),
337-
}
338-
.expect("adc_ker_ck_input is not running!");
343+
};
339344

340345
// Check against datasheet requirements
341346
assert!(

src/fmc.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ use crate::gpio::{Alternate, AF12, AF9};
7070
/// AHB access to the FMC peripheral must be enabled
7171
pub struct FMC {
7272
fmc: stm32::FMC,
73-
fmc_ker_ck: Option<Hertz>,
73+
fmc_ker_ck: Hertz,
7474
}
7575

7676
/// Extension trait for FMC controller
@@ -114,10 +114,18 @@ impl FmcExt for stm32::FMC {
114114

115115
// Calculate kernel clock
116116
let fmc_ker_ck = match clk_sel {
117-
rec::FmcClkSel::RCC_HCLK3 => Some(clocks.hclk()),
118-
rec::FmcClkSel::PLL1_Q => clocks.pll1_q_ck(),
119-
rec::FmcClkSel::PLL2_R => clocks.pll2_r_ck(),
120-
rec::FmcClkSel::PER => clocks.per_ck(),
117+
rec::FmcClkSel::RCC_HCLK3 => {
118+
Some(clocks.hclk()).expect("FMC: HCLK must be enabled")
119+
}
120+
rec::FmcClkSel::PLL1_Q => {
121+
clocks.pll1_q_ck().expect("FMC: PLL1_Q must be enabled")
122+
}
123+
rec::FmcClkSel::PLL2_R => {
124+
clocks.pll2_r_ck().expect("FMC: PLL2_R must be enabled")
125+
}
126+
rec::FmcClkSel::PER => {
127+
clocks.per_ck().expect("FMC: PER clock must be enabled")
128+
}
121129
};
122130

123131
// Enable AHB access and reset peripheral
@@ -144,8 +152,7 @@ unsafe impl FmcPeripheral for FMC {
144152
}
145153

146154
fn source_clock_hz(&self) -> u32 {
147-
// Check that it runs
148-
self.fmc_ker_ck.expect("FMC kernel clock is not running!").0
155+
self.fmc_ker_ck.0
149156
}
150157
}
151158

src/pwm.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,7 +1052,7 @@ macro_rules! tim_hal {
10521052
prec.enable().reset();
10531053

10541054
let clk = $TIMX::get_clk(clocks)
1055-
.expect("Timer input clock not running!");
1055+
.expect("$TIMX: Input clock not running!");
10561056

10571057
let (period, prescale) = match $bits {
10581058
16 => calculate_frequency_16bit(clk, freq, Alignment::Left),
@@ -1096,7 +1096,7 @@ macro_rules! tim_hal {
10961096
prec.enable().reset();
10971097

10981098
let clk = $TIMX::get_clk(clocks)
1099-
.expect("Timer input clock not running!")
1099+
.expect("$TIMX: Input clock not running!")
11001100
.0;
11011101

11021102
PwmBuilder {
@@ -1645,7 +1645,8 @@ macro_rules! lptim_hal {
16451645
{
16461646
prec.enable().reset();
16471647

1648-
let clk = $TIMX::get_clk(clocks).unwrap().0;
1648+
let clk = $TIMX::get_clk(clocks)
1649+
.expect("$TIMX: Input clock not running").0;
16491650
let freq = freq.0;
16501651
let reload = clk / freq;
16511652
assert!(reload < 128 * (1 << 16));

src/rng.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,24 @@ pub enum ErrorKind {
1919
SeedError = 1,
2020
}
2121

22-
trait KerClk {
23-
fn kernel_clk(prec: rec::Rng, clocks: &CoreClocks) -> Option<Hertz>;
22+
pub trait KerClk {
23+
/// Return the kernel clock for the Random Number Generator
24+
///
25+
/// # Panics
26+
///
27+
/// Panics if the kernel clock is not running
28+
fn kernel_clk_unwrap(prec: rec::Rng, clocks: &CoreClocks) -> Hertz;
2429
}
2530

2631
impl KerClk for RNG {
27-
fn kernel_clk(prec: rec::Rng, clocks: &CoreClocks) -> Option<Hertz> {
32+
fn kernel_clk_unwrap(prec: rec::Rng, clocks: &CoreClocks) -> Hertz {
2833
match prec.get_kernel_clk_mux() {
29-
RngClkSel::HSI48 => clocks.hsi48_ck(),
30-
RngClkSel::PLL1_Q => clocks.pll1_q_ck(),
34+
RngClkSel::HSI48 => {
35+
clocks.hsi48_ck().expect("RNG: HSI48 must be enabled")
36+
}
37+
RngClkSel::PLL1_Q => {
38+
clocks.pll1_q_ck().expect("RNG: PLL1_Q must be enabled")
39+
}
3140
RngClkSel::LSE => unimplemented!(),
3241
RngClkSel::LSI => unimplemented!(),
3342
}
@@ -43,12 +52,11 @@ impl RngExt for RNG {
4352
let prec = prec.enable().reset();
4453

4554
let hclk = clocks.hclk();
46-
let rng_clk = Self::kernel_clk(prec, clocks)
47-
.expect("RNG input clock not running!");
55+
let rng_clk = Self::kernel_clk_unwrap(prec, clocks);
4856

4957
// Otherwise clock checker will always flag an error
5058
// See RM0433 Rev 6 Section 33.3.6
51-
assert!(rng_clk.0 > hclk.0 / 32);
59+
assert!(rng_clk.0 > hclk.0 / 32, "RNG: Clock too slow");
5260

5361
self.cr.modify(|_, w| w.ced().enabled().rngen().enabled());
5462

src/sai/i2s.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,7 @@ macro_rules! i2s {
457457
}
458458

459459
// Clock config
460-
let ker_ck_a = $SAIX::sai_a_ker_ck(&prec, clocks)
461-
.expect("SAI kernel clock must run!");
460+
let ker_ck_a = $SAIX::sai_a_ker_ck(&prec, clocks);
462461
let clock_ratio = if users.master.oversampling {
463462
512
464463
} else {
@@ -468,7 +467,7 @@ macro_rules! i2s {
468467
(ker_ck_a.0) / (audio_freq.0 * clock_ratio);
469468
let mclk_div: u8 = mclk_div
470469
.try_into()
471-
.expect("SAI kernel clock is out of range for required MCLK");
470+
.expect("$SAIX A: Kernel clock is out of range for required MCLK");
472471

473472
// Configure SAI peripheral
474473
let mut per_sai = Sai {
@@ -523,8 +522,7 @@ macro_rules! i2s {
523522
}
524523

525524
// Clock config
526-
let ker_ck_a = $SAIX::sai_b_ker_ck(&prec, clocks)
527-
.expect("SAI kernel clock must run!");
525+
let ker_ck_a = $SAIX::sai_b_ker_ck(&prec, clocks);
528526
let clock_ratio = if users.master.oversampling {
529527
512
530528
} else {
@@ -534,7 +532,7 @@ macro_rules! i2s {
534532
(ker_ck_a.0) / (audio_freq.0 * clock_ratio);
535533
let mclk_div: u8 = mclk_div
536534
.try_into()
537-
.expect("SAI kernel clock is out of range for required MCLK");
535+
.expect("$SAIX B: Kernel clock is out of range for required MCLK");
538536

539537
// Configure SAI peripheral
540538
let mut per_sai = Sai {

src/sai/mod.rs

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,18 @@ pub use i2s::{
4545
pub trait GetClkSAI {
4646
type Rec: ResetEnable;
4747

48-
fn sai_a_ker_ck(prec: &Self::Rec, clocks: &CoreClocks) -> Option<Hertz>;
49-
fn sai_b_ker_ck(prec: &Self::Rec, clocks: &CoreClocks) -> Option<Hertz>;
48+
/// Return the kernel clock for the SAI - A
49+
///
50+
/// # Panics
51+
///
52+
/// Panics if the kernel clock is not running
53+
fn sai_a_ker_ck(prec: &Self::Rec, clocks: &CoreClocks) -> Hertz;
54+
/// Return the kernel clock for the SAI - B
55+
///
56+
/// # Panics
57+
///
58+
/// Panics if the kernel clock is not running
59+
fn sai_b_ker_ck(prec: &Self::Rec, clocks: &CoreClocks) -> Hertz;
5060
}
5161

5262
// Return kernel clocks for this SAI
@@ -59,24 +69,40 @@ macro_rules! impl_sai_ker_ck {
5969
type Rec = rec::$Rec;
6070

6171
/// Current kernel clock - A
62-
fn sai_a_ker_ck(prec: &Self::Rec, clocks: &CoreClocks) -> Option<Hertz> {
72+
fn sai_a_ker_ck(prec: &Self::Rec, clocks: &CoreClocks) -> Hertz {
6373
match prec.$get_mux_A() {
64-
Some(rec::$AccessA::PLL1_Q) => clocks.pll1_q_ck(),
65-
Some(rec::$AccessA::PLL2_P) => clocks.pll2_p_ck(),
66-
Some(rec::$AccessA::PLL3_P) => clocks.pll3_p_ck(),
74+
Some(rec::$AccessA::PLL1_Q) => {
75+
clocks.pll1_q_ck().expect("$SAIX A: PLL1_Q must be enabled")
76+
}
77+
Some(rec::$AccessA::PLL2_P) => {
78+
clocks.pll2_p_ck().expect("$SAIX A: PLL2_P must be enabled")
79+
}
80+
Some(rec::$AccessA::PLL3_P) => {
81+
clocks.pll3_p_ck().expect("$SAIX A: PLL3_P must be enabled")
82+
}
6783
Some(rec::$AccessA::I2S_CKIN) => unimplemented!(),
68-
Some(rec::$AccessA::PER) => clocks.per_ck(),
84+
Some(rec::$AccessA::PER) => {
85+
clocks.per_ck().expect("$SAIX A: PER clock must be enabled")
86+
}
6987
_ => unreachable!(),
7088
}
7189
}
7290
/// Current kernel clock - B
73-
fn sai_b_ker_ck(prec: &Self::Rec, clocks: &CoreClocks) -> Option<Hertz> {
91+
fn sai_b_ker_ck(prec: &Self::Rec, clocks: &CoreClocks) -> Hertz {
7492
match prec.$get_mux_B() {
75-
Some(rec::$AccessB::PLL1_Q) => clocks.pll1_q_ck(),
76-
Some(rec::$AccessB::PLL2_P) => clocks.pll2_p_ck(),
77-
Some(rec::$AccessB::PLL3_P) => clocks.pll3_p_ck(),
93+
Some(rec::$AccessB::PLL1_Q) => {
94+
clocks.pll1_q_ck().expect("$SAIX B: PLL1_Q must be enabled")
95+
}
96+
Some(rec::$AccessB::PLL2_P) => {
97+
clocks.pll2_p_ck().expect("$SAIX B: PLL2_P must be enabled")
98+
}
99+
Some(rec::$AccessB::PLL3_P) => {
100+
clocks.pll3_p_ck().expect("$SAIX B: PLL3_P must be enabled")
101+
}
78102
Some(rec::$AccessB::I2S_CKIN) => unimplemented!(),
79-
Some(rec::$AccessB::PER) => clocks.per_ck(),
103+
Some(rec::$AccessB::PER) => {
104+
clocks.per_ck().expect("$SAIX B: PER clock must be enabled")
105+
}
80106
_ => unreachable!(),
81107
}
82108
}

src/sai/pdm.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,10 @@ macro_rules! hal {
250250
let mclk_a_hz = sck_a_hz; // For NODIV = 1, SCK_a = MCLK_a
251251

252252
// Calculate divider
253-
let ker_ck_a =
254-
$SAIX::sai_a_ker_ck(&prec, clocks).expect("SAI kernel clock must run!");
253+
let ker_ck_a = $SAIX::sai_a_ker_ck(&prec, clocks);
255254
let kernel_clock_divider: u8 = (ker_ck_a.0 / mclk_a_hz)
256255
.try_into()
257-
.expect("SAI kernel clock is out of range for required MCLK");
256+
.expect("$SAIX: Kernel clock is out of range for required MCLK");
258257

259258
// Configure SAI peripeheral
260259
let mut s = Sai {

src/sdmmc.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -454,10 +454,14 @@ macro_rules! sdmmc {
454454

455455
let hclk = clocks.hclk();
456456
let ker_ck = match prec.get_kernel_clk_mux() {
457-
rec::SdmmcClkSel::PLL1_Q => clocks.pll1_q_ck(),
458-
rec::SdmmcClkSel::PLL2_R => clocks.pll2_r_ck(),
459-
}
460-
.expect("sdmmc_ker_ck not running!");
457+
rec::SdmmcClkSel::PLL1_Q => {
458+
clocks.pll1_q_ck().expect("SDMMC: PLL1_Q must be enabled")
459+
}
460+
rec::SdmmcClkSel::PLL2_R => {
461+
clocks.pll2_r_ck().expect("SDMMC: PLL2_R must be enabled")
462+
}
463+
};
464+
461465

462466
// For tuning the phase of the receive sampling clock, a
463467
// DLYB block can be connected between sdmmc_io_in_ck and

src/serial.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -514,10 +514,7 @@ macro_rules! usart {
514514
prec.enable().reset();
515515

516516
// Get kernel clock
517-
let usart_ker_ck = match Self::kernel_clk(clocks) {
518-
Some(ker_hz) => ker_hz.0,
519-
_ => panic!("$USARTX kernel clock not running!")
520-
};
517+
let usart_ker_ck = Self::kernel_clk_unwrap(clocks).0;
521518

522519
// Prescaler not used for now
523520
let usart_ker_ck_presc = usart_ker_ck;
@@ -954,7 +951,7 @@ macro_rules! usart_sel {
954951
impl Serial<$USARTX> {
955952
/// Returns the frequency of the current kernel clock for
956953
#[doc=$doc]
957-
fn kernel_clk(clocks: &CoreClocks) -> Option<Hertz> {
954+
pub fn kernel_clk(clocks: &CoreClocks) -> Option<Hertz> {
958955
// unsafe: read only
959956
let ccip = unsafe { (*stm32::RCC::ptr()).$ccip.read() };
960957

@@ -968,6 +965,34 @@ macro_rules! usart_sel {
968965
_ => unreachable!(),
969966
}
970967
}
968+
/// Returns the frequency of the current kernel clock for
969+
#[doc=$doc]
970+
///
971+
/// # Panics
972+
///
973+
/// Panics if the kernel clock is not running
974+
pub fn kernel_clk_unwrap(clocks: &CoreClocks) -> Hertz {
975+
// unsafe: read only
976+
let ccip = unsafe { (*stm32::RCC::ptr()).$ccip.read() };
977+
978+
match ccip.$sel().variant() {
979+
Some($SEL::$PCLK) => clocks.$pclk(),
980+
Some($SEL::PLL2_Q) => {
981+
clocks.pll2_q_ck().expect("$USARTX: PLL2_Q must be enabled")
982+
}
983+
Some($SEL::PLL3_Q) => {
984+
clocks.pll3_q_ck().expect("$USARTX: PLL3_Q must be enabled")
985+
}
986+
Some($SEL::HSI_KER) => {
987+
clocks.hsi_ck().expect("$USARTX: HSI clock must be enabled")
988+
}
989+
Some($SEL::CSI_KER) => {
990+
clocks.csi_ck().expect("$USARTX: CSI clock must be enabled")
991+
}
992+
Some($SEL::LSE) => unimplemented!(),
993+
_ => unreachable!(),
994+
}
995+
}
971996
}
972997
)+
973998
}

0 commit comments

Comments
 (0)