Skip to content

Commit 4b04112

Browse files
bors[bot]Disasm
andauthored
Merge #232
232: Add syscfg driver to enforce clock enable r=therealprof a=Disasm This should prevent terrible user experience when SYSCFG is used without its clock enabled. Note that this is a breaking change. Co-authored-by: Vadim Kaushan <[email protected]>
2 parents d983c32 + 16dc41f commit 4b04112

7 files changed

+54
-11
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2424
- [breaking-change] ADC2 and ADC3 no longer allow access to VREF, VBAT, or the internal
2525
temperature measurement (ADC2 and ADC3 do not have an internal connection for these channels)
2626
- Improved Serial baudrate calculation to be correct for higher baudrates or lower PCLKs
27+
- Added `SysCfg` wrapper to enforce clock enable for `SYSCFG`
28+
- [breaking-change] gpio::ExtiPin now uses `SysCfg` wrapper instead of `SYSCFG`
2729

2830
### Added
2931

examples/analog-stopwatch-with-spi-ssd1306.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ extern crate panic_semihosting;
1313
extern crate stm32f4xx_hal as hal;
1414

1515
use crate::hal::{
16-
gpio::{gpioa::PA0, Edge, ExtiPin, Input, PullDown},
16+
gpio::{gpioa::PA0, Edge, Input, PullDown},
1717
interrupt, pac,
1818
prelude::*,
1919
rcc::{Clocks, Rcc},
@@ -79,11 +79,13 @@ fn main() -> ! {
7979

8080
let clocks = setup_clocks(rcc);
8181

82+
let mut syscfg = dp.SYSCFG.constrain();
83+
8284
let gpioa = dp.GPIOA.split();
8385
let gpioe = dp.GPIOE.split();
8486

8587
let mut board_btn = gpioa.pa0.into_pull_down_input();
86-
board_btn.make_interrupt_source(&mut dp.SYSCFG);
88+
board_btn.make_interrupt_source(&mut syscfg);
8789
board_btn.enable_interrupt(&mut dp.EXTI);
8890
board_btn.trigger_on_edge(&mut dp.EXTI, Edge::FALLING);
8991

examples/stopwatch-with-ssd1306-and-interrupts.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ extern crate stm32f4xx_hal as hal;
2222

2323
use crate::hal::{
2424
delay::Delay,
25-
gpio::{gpioc::PC13, Edge, ExtiPin, Input, PullUp},
25+
gpio::{gpioc::PC13, Edge, Input, PullUp},
2626
i2c::I2c,
2727
interrupt,
2828
prelude::*,
@@ -60,8 +60,6 @@ enum StopwatchState {
6060
#[entry]
6161
fn main() -> ! {
6262
if let (Some(mut dp), Some(cp)) = (stm32::Peripherals::take(), cortex_m::Peripherals::take()) {
63-
dp.RCC.apb2enr.write(|w| w.syscfgen().enabled());
64-
6563
let rcc = dp.RCC.constrain();
6664
let clocks = setup_clocks(rcc);
6765
let gpiob = dp.GPIOB.split();
@@ -75,10 +73,12 @@ fn main() -> ! {
7573
clocks,
7674
);
7775

76+
let mut syscfg = dp.SYSCFG.constrain();
77+
7878
// Create a button input with an interrupt
7979
let gpioc = dp.GPIOC.split();
8080
let mut board_btn = gpioc.pc13.into_pull_up_input();
81-
board_btn.make_interrupt_source(&mut dp.SYSCFG);
81+
board_btn.make_interrupt_source(&mut syscfg);
8282
board_btn.enable_interrupt(&mut dp.EXTI);
8383
board_btn.trigger_on_edge(&mut dp.EXTI, Edge::FALLING);
8484

src/gpio.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
33
use core::marker::PhantomData;
44

5-
use crate::pac::{EXTI, SYSCFG};
5+
use crate::pac::EXTI;
6+
use crate::syscfg::SysCfg;
67

78
/// Extension trait to split a GPIO peripheral in independent pins and registers
89
pub trait GpioExt {
@@ -85,7 +86,7 @@ pub enum Edge {
8586

8687
/// External Interrupt Pin
8788
pub trait ExtiPin {
88-
fn make_interrupt_source(&mut self, syscfg: &mut SYSCFG);
89+
fn make_interrupt_source(&mut self, syscfg: &mut SysCfg);
8990
fn trigger_on_edge(&mut self, exti: &mut EXTI, level: Edge);
9091
fn enable_interrupt(&mut self, exti: &mut EXTI);
9192
fn disable_interrupt(&mut self, exti: &mut EXTI);
@@ -97,7 +98,7 @@ macro_rules! exti_erased {
9798
($PIN:ty, $extigpionr:expr) => {
9899
impl<MODE> ExtiPin for $PIN {
99100
/// Make corresponding EXTI line sensitive to this pin
100-
fn make_interrupt_source(&mut self, syscfg: &mut SYSCFG) {
101+
fn make_interrupt_source(&mut self, syscfg: &mut SysCfg) {
101102
let offset = 4 * (self.i % 4);
102103
match self.i {
103104
0..=3 => {
@@ -177,7 +178,7 @@ macro_rules! exti {
177178
($PIN:ty, $extigpionr:expr, $i:expr, $exticri:ident) => {
178179
impl<MODE> ExtiPin for $PIN {
179180
/// Configure EXTI Line $i to trigger from this pin.
180-
fn make_interrupt_source(&mut self, syscfg: &mut SYSCFG) {
181+
fn make_interrupt_source(&mut self, syscfg: &mut SysCfg) {
181182
let offset = 4 * ($i % 4);
182183
syscfg.$exticri.modify(|r, w| unsafe {
183184
let mut exticr = r.bits();
@@ -247,7 +248,7 @@ macro_rules! gpio {
247248
use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, toggleable};
248249
use crate::pac::$GPIOX;
249250

250-
use crate::{pac::{RCC, EXTI, SYSCFG}, bb};
251+
use crate::{pac::{RCC, EXTI}, bb, syscfg::SysCfg};
251252
use super::{
252253
Alternate, AlternateOD, Floating, GpioExt, Input, OpenDrain, Output, Speed,
253254
PullDown, PullUp, PushPull, AF0, AF1, AF2, AF3, AF4, AF5, AF6, AF7, AF8, AF9, AF10,

src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ pub mod signature;
178178
#[cfg(feature = "device-selected")]
179179
pub mod spi;
180180
#[cfg(feature = "device-selected")]
181+
pub mod syscfg;
182+
#[cfg(feature = "device-selected")]
181183
pub mod time;
182184
#[cfg(feature = "device-selected")]
183185
pub mod timer;

src/prelude.rs

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub use embedded_hal::prelude::*;
99
not(any(feature = "stm32f411", feature = "stm32f412", feature = "stm32f401",))
1010
))]
1111
pub use crate::dac::DacExt as _stm32f4xx_hal_dac_DacExt;
12+
pub use crate::gpio::ExtiPin as _stm32f4xx_hal_gpio_ExtiPin;
1213
pub use crate::gpio::GpioExt as _stm32f4xx_hal_gpio_GpioExt;
1314
pub use crate::i2c::Pins as _stm32f4xx_hal_i2c_Pins;
1415
pub use crate::rcc::RccExt as _stm32f4xx_hal_rcc_RccExt;
@@ -22,4 +23,5 @@ pub use crate::rcc::RccExt as _stm32f4xx_hal_rcc_RccExt;
2223
))
2324
))]
2425
pub use crate::rng::RngExt as _stm32f4xx_hal_rng_RngExt;
26+
pub use crate::syscfg::SysCfgExt as _stm32f4xx_hal_syscfg_SysCfgExt;
2527
pub use crate::time::U32Ext as _stm32f4xx_hal_time_U32Ext;

src/syscfg.rs

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use crate::bb;
2+
use crate::stm32::{RCC, SYSCFG};
3+
use core::ops::Deref;
4+
5+
/// Extension trait that constrains the `SYSCFG` peripheral
6+
pub trait SysCfgExt {
7+
/// Constrains the `SYSCFG` peripheral so it plays nicely with the other abstractions
8+
fn constrain(self) -> SysCfg;
9+
}
10+
11+
impl SysCfgExt for SYSCFG {
12+
fn constrain(self) -> SysCfg {
13+
unsafe {
14+
// NOTE(unsafe) this reference will only be used for atomic writes with no side effects.
15+
let rcc = &(*RCC::ptr());
16+
17+
// Enable clock.
18+
bb::set(&rcc.apb2enr, 14);
19+
}
20+
21+
SysCfg(self)
22+
}
23+
}
24+
25+
pub struct SysCfg(SYSCFG);
26+
27+
impl Deref for SysCfg {
28+
type Target = SYSCFG;
29+
30+
#[inline(always)]
31+
fn deref(&self) -> &Self::Target {
32+
&self.0
33+
}
34+
}

0 commit comments

Comments
 (0)