Skip to content

Commit 7ca3a1f

Browse files
Merge #213
213: Use bitbanding to avoid data races r=therealprof a=thalesfragoso Partially addresses #171. Co-authored-by: Thales Fragoso <thales.fragosoz@gmail.com>
2 parents eaefada + 7a4f978 commit 7ca3a1f

File tree

9 files changed

+236
-173
lines changed

9 files changed

+236
-173
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1919
- I2C driver updated to detect and clear all error condition flags.
2020
- Allow for skipping an ongoing DMA transfer if not using double buffering.
2121
- Change DMA traits to `embedded-dma`.
22+
- Use bitbanding during clock enabling and peripheral reset to avoid data races.
2223

2324
### Added
2425

src/adc.rs

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
Temperature in °C = (110-30)/(VtempCal110::get().read()-VtempCal30::get().read()) * (adc_sample - VtempCal30::get().read()) + 30
99
*/
1010

11-
use crate::{gpio::*, signature::VrefCal, signature::VDDA_CALIB, stm32};
11+
use crate::{bb, gpio::*, pac, signature::VrefCal, signature::VDDA_CALIB};
1212
use core::fmt;
1313
use embedded_hal::adc::{Channel, OneShot};
1414

@@ -24,7 +24,7 @@ pub struct Temperature;
2424
macro_rules! adc_pins {
2525
($($pin:ty => ($adc:ident, $chan:expr)),+ $(,)*) => {
2626
$(
27-
impl Channel<stm32::$adc> for $pin {
27+
impl Channel<pac::$adc> for $pin {
2828
type ID = u8;
2929
fn channel() -> u8 { $chan }
3030
}
@@ -606,21 +606,25 @@ impl<ADC> fmt::Debug for Adc<ADC> {
606606
}
607607

608608
macro_rules! adc {
609-
($($adc_type:ident => ($constructor_fn_name:ident, $common_type:ident, $rcc_enr_reg:ident, $rcc_enr_field: ident, $rcc_rst_reg: ident, $rcc_rst_field: ident)),+ $(,)*) => {
609+
($($adc_type:ident => ($constructor_fn_name:ident, $common_type:ident, $en_bit: expr)),+ $(,)*) => {
610610
$(
611-
impl Adc<stm32::$adc_type> {
611+
impl Adc<pac::$adc_type> {
612612
/// Enables the ADC clock, resets the peripheral (optionally), runs calibration and applies the supplied config
613613
/// # Arguments
614614
/// * `reset` - should a reset be performed. This is provided because on some devices multiple ADCs share the same common reset
615-
pub fn $constructor_fn_name(adc: stm32::$adc_type, reset: bool, config: config::AdcConfig) -> Adc<stm32::$adc_type> {
615+
pub fn $constructor_fn_name(adc: pac::$adc_type, reset: bool, config: config::AdcConfig) -> Adc<pac::$adc_type> {
616616
unsafe {
617-
let rcc = &(*stm32::RCC::ptr());
618-
//Enable the common clock
619-
rcc.$rcc_enr_reg.modify(|_, w| w.$rcc_enr_field().set_bit());
617+
// All ADCs share the same reset interface.
618+
const RESET_BIT: u8 = 8;
619+
// NOTE(unsafe) this reference will only be used for atomic writes with no side effects.
620+
let rcc = &(*pac::RCC::ptr());
621+
622+
//Enable the clock
623+
bb::set(&rcc.apb2enr, $en_bit);
620624
if reset {
621625
//Reset the peripheral(s)
622-
rcc.$rcc_rst_reg.modify(|_, w| w.$rcc_rst_field().set_bit());
623-
rcc.$rcc_rst_reg.modify(|_, w| w.$rcc_rst_field().clear_bit());
626+
bb::set(&rcc.apb2rstr, RESET_BIT);
627+
bb::clear(&rcc.apb2rstr, RESET_BIT);
624628
}
625629
}
626630

@@ -676,15 +680,15 @@ macro_rules! adc {
676680
/// Enables the vbat internal channel
677681
pub fn enable_vbat(&self) {
678682
unsafe {
679-
let common = &(*stm32::$common_type::ptr());
683+
let common = &(*pac::$common_type::ptr());
680684
common.ccr.modify(|_, w| w.vbate().set_bit());
681685
}
682686
}
683687

684688
/// Enables the vbat internal channel
685689
pub fn disable_vbat(&self) {
686690
unsafe {
687-
let common = &(*stm32::$common_type::ptr());
691+
let common = &(*pac::$common_type::ptr());
688692
common.ccr.modify(|_, w| w.vbate().clear_bit());
689693
}
690694
}
@@ -695,23 +699,23 @@ macro_rules! adc {
695699
//VBAT prevents TS and VREF from being sampled
696700
self.disable_vbat();
697701
unsafe {
698-
let common = &(*stm32::$common_type::ptr());
702+
let common = &(*pac::$common_type::ptr());
699703
common.ccr.modify(|_, w| w.tsvrefe().set_bit());
700704
}
701705
}
702706

703707
/// Disables the temp and vref internal channels
704708
pub fn disable_temperature_and_vref(&mut self) {
705709
unsafe {
706-
let common = &(*stm32::$common_type::ptr());
710+
let common = &(*pac::$common_type::ptr());
707711
common.ccr.modify(|_, w| w.tsvrefe().clear_bit());
708712
}
709713
}
710714

711715
/// Returns if the temp and vref internal channels are enabled
712716
pub fn temperature_and_vref_enabled(&mut self) -> bool {
713717
unsafe {
714-
let common = &(*stm32::$common_type::ptr());
718+
let common = &(*pac::$common_type::ptr());
715719
common.ccr.read().tsvrefe().bit_is_set()
716720
}
717721
}
@@ -750,7 +754,7 @@ macro_rules! adc {
750754
pub fn set_clock(&mut self, clock: config::Clock) {
751755
self.config.clock = clock;
752756
unsafe {
753-
let common = &(*stm32::$common_type::ptr());
757+
let common = &(*pac::$common_type::ptr());
754758
common.ccr.modify(|_, w| w.adcpre().bits(clock.into()));
755759
}
756760
}
@@ -861,7 +865,7 @@ macro_rules! adc {
861865
/// to sample for at a given ADC clock frequency
862866
pub fn configure_channel<CHANNEL>(&mut self, _channel: &CHANNEL, sequence: config::Sequence, sample_time: config::SampleTime)
863867
where
864-
CHANNEL: Channel<stm32::$adc_type, ID=u8>
868+
CHANNEL: Channel<pac::$adc_type, ID=u8>
865869
{
866870
//Check the sequence is long enough
867871
self.adc_reg.sqr1.modify(|r, w| {
@@ -939,7 +943,7 @@ macro_rules! adc {
939943
/// Note that it reconfigures the adc sequence and doesn't restore it
940944
pub fn convert<PIN>(&mut self, pin: &PIN, sample_time: config::SampleTime) -> u16
941945
where
942-
PIN: Channel<stm32::$adc_type, ID=u8>
946+
PIN: Channel<pac::$adc_type, ID=u8>
943947
{
944948
self.adc_reg.cr2.modify(|_, w| w
945949
.dma().clear_bit() //Disable dma
@@ -970,9 +974,9 @@ macro_rules! adc {
970974
}
971975
}
972976

973-
impl<PIN> OneShot<stm32::$adc_type, u16, PIN> for Adc<stm32::$adc_type>
977+
impl<PIN> OneShot<pac::$adc_type, u16, PIN> for Adc<pac::$adc_type>
974978
where
975-
PIN: Channel<stm32::$adc_type, ID=u8>,
979+
PIN: Channel<pac::$adc_type, ID=u8>,
976980
{
977981
type Error = ();
978982

@@ -1014,7 +1018,7 @@ macro_rules! adc {
10141018
feature = "stm32f469",
10151019
feature = "stm32f479",
10161020
))]
1017-
adc!(ADC1 => (adc1, ADC_COMMON, apb2enr, adc1en, apb2rstr, adcrst));
1021+
adc!(ADC1 => (adc1, ADC_COMMON, 8));
10181022

10191023
#[cfg(any(
10201024
feature = "stm32f405",
@@ -1029,7 +1033,7 @@ adc!(ADC1 => (adc1, ADC_COMMON, apb2enr, adc1en, apb2rstr, adcrst));
10291033
feature = "stm32f469",
10301034
feature = "stm32f479",
10311035
))]
1032-
adc!(ADC2 => (adc2, ADC_COMMON, apb2enr, adc2en, apb2rstr, adcrst));
1036+
adc!(ADC2 => (adc2, ADC_COMMON, 9));
10331037

10341038
#[cfg(any(
10351039
feature = "stm32f405",
@@ -1044,7 +1048,7 @@ adc!(ADC2 => (adc2, ADC_COMMON, apb2enr, adc2en, apb2rstr, adcrst));
10441048
feature = "stm32f469",
10451049
feature = "stm32f479",
10461050
))]
1047-
adc!(ADC3 => (adc3, ADC_COMMON, apb2enr, adc3en, apb2rstr, adcrst));
1051+
adc!(ADC3 => (adc3, ADC_COMMON, 10));
10481052

10491053
#[cfg(feature = "stm32f401")]
10501054
adc_pins!(

src/dac.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
#![deny(unused_imports)]
66
use core::mem;
77

8-
use crate::gpio::gpioa::{PA4, PA5};
9-
use crate::gpio::Analog;
10-
use crate::pac::DAC;
11-
use crate::stm32::RCC;
8+
use crate::{
9+
bb,
10+
gpio::{
11+
gpioa::{PA4, PA5},
12+
Analog,
13+
},
14+
pac::{DAC, RCC},
15+
};
1216

1317
pub struct C1;
1418
pub struct C2;
@@ -42,17 +46,21 @@ pub fn dac<PINS>(_dac: DAC, _pins: PINS) -> PINS::Output
4246
where
4347
PINS: Pins<DAC>,
4448
{
45-
// NOTE(unsafe) This executes only during initialisation
46-
let rcc = unsafe { &(*RCC::ptr()) };
49+
unsafe {
50+
const EN_BIT: u8 = 29;
51+
const RESET_BIT: u8 = 29;
4752

48-
// Enable DAC clocks
49-
rcc.apb1enr.modify(|_, w| w.dacen().set_bit());
53+
// NOTE(unsafe) this reference will only be used for atomic writes with no side effects.
54+
let rcc = &(*RCC::ptr());
5055

51-
// Reset DAC
52-
rcc.apb1rstr.modify(|_, w| w.dacrst().set_bit());
53-
rcc.apb1rstr.modify(|_, w| w.dacrst().clear_bit());
56+
// Enable and reset clock.
57+
bb::set(&rcc.apb1enr, EN_BIT);
58+
bb::set(&rcc.apb1rstr, RESET_BIT);
59+
bb::clear(&rcc.apb1rstr, RESET_BIT);
5460

55-
unsafe { mem::MaybeUninit::uninit().assume_init() }
61+
// NOTE(unsafe) ZST, doesn't need initialization.
62+
mem::MaybeUninit::uninit().assume_init()
63+
}
5664
}
5765

5866
macro_rules! dac {

src/gpio.rs

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use core::marker::PhantomData;
44

5-
use crate::stm32::{EXTI, SYSCFG};
5+
use crate::pac::{EXTI, SYSCFG};
66

77
/// Extension trait to split a GPIO peripheral in independent pins and registers
88
pub trait GpioExt {
@@ -236,7 +236,7 @@ macro_rules! exti {
236236
}
237237

238238
macro_rules! gpio {
239-
($GPIOX:ident, $gpiox:ident, $iopxenr:ident, $PXx:ident, $extigpionr:expr, [
239+
($GPIOX:ident, $gpiox:ident, $rcc_bit:expr, $PXx:ident, $extigpionr:expr, [
240240
$($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty, $exticri:ident),)+
241241
]) => {
242242
/// GPIO
@@ -245,9 +245,9 @@ macro_rules! gpio {
245245
use core::convert::Infallible;
246246

247247
use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, toggleable};
248-
use crate::stm32::$GPIOX;
248+
use crate::pac::$GPIOX;
249249

250-
use crate::stm32::{RCC, EXTI, SYSCFG};
250+
use crate::{pac::{RCC, EXTI, SYSCFG}, bb};
251251
use super::{
252252
Alternate, AlternateOD, Floating, GpioExt, Input, OpenDrain, Output, Speed,
253253
PullDown, PullUp, PushPull, AF0, AF1, AF2, AF3, AF4, AF5, AF6, AF7, AF8, AF9, AF10,
@@ -266,10 +266,13 @@ macro_rules! gpio {
266266
type Parts = Parts;
267267

268268
fn split(self) -> Parts {
269-
// NOTE(unsafe) This executes only during initialisation
270-
let rcc = unsafe { &(*RCC::ptr()) };
271-
rcc.ahb1enr.modify(|_, w| w.$iopxenr().set_bit());
269+
unsafe {
270+
// NOTE(unsafe) this reference will only be used for atomic writes with no side effects.
271+
let rcc = &(*RCC::ptr());
272272

273+
// Enable clock.
274+
bb::set(&rcc.ahb1enr, $rcc_bit);
275+
}
273276
Parts {
274277
$(
275278
$pxi: $PXi { _mode: PhantomData },
@@ -834,7 +837,7 @@ macro_rules! gpio {
834837
feature = "stm32f469",
835838
feature = "stm32f479"
836839
))]
837-
gpio!(GPIOA, gpioa, gpioaen, PA, 0, [
840+
gpio!(GPIOA, gpioa, 0, PA, 0, [
838841
PA0: (pa0, 0, Input<Floating>, exticr1),
839842
PA1: (pa1, 1, Input<Floating>, exticr1),
840843
PA2: (pa2, 2, Input<Floating>, exticr1),
@@ -872,7 +875,7 @@ gpio!(GPIOA, gpioa, gpioaen, PA, 0, [
872875
feature = "stm32f469",
873876
feature = "stm32f479"
874877
))]
875-
gpio!(GPIOB, gpiob, gpioben, PB, 1, [
878+
gpio!(GPIOB, gpiob, 1, PB, 1, [
876879
PB0: (pb0, 0, Input<Floating>, exticr1),
877880
PB1: (pb1, 1, Input<Floating>, exticr1),
878881
PB2: (pb2, 2, Input<Floating>, exticr1),
@@ -910,7 +913,7 @@ gpio!(GPIOB, gpiob, gpioben, PB, 1, [
910913
feature = "stm32f469",
911914
feature = "stm32f479"
912915
))]
913-
gpio!(GPIOC, gpioc, gpiocen, PC, 2, [
916+
gpio!(GPIOC, gpioc, 2, PC, 2, [
914917
PC0: (pc0, 0, Input<Floating>, exticr1),
915918
PC1: (pc1, 1, Input<Floating>, exticr1),
916919
PC2: (pc2, 2, Input<Floating>, exticr1),
@@ -947,7 +950,7 @@ gpio!(GPIOC, gpioc, gpiocen, PC, 2, [
947950
feature = "stm32f469",
948951
feature = "stm32f479"
949952
))]
950-
gpio!(GPIOD, gpiod, gpioden, PD, 3, [
953+
gpio!(GPIOD, gpiod, 3, PD, 3, [
951954
PD0: (pd0, 0, Input<Floating>, exticr1),
952955
PD1: (pd1, 1, Input<Floating>, exticr1),
953956
PD2: (pd2, 2, Input<Floating>, exticr1),
@@ -984,7 +987,7 @@ gpio!(GPIOD, gpiod, gpioden, PD, 3, [
984987
feature = "stm32f469",
985988
feature = "stm32f479"
986989
))]
987-
gpio!(GPIOE, gpioe, gpioeen, PE, 4, [
990+
gpio!(GPIOE, gpioe, 4, PE, 4, [
988991
PE0: (pe0, 0, Input<Floating>, exticr1),
989992
PE1: (pe1, 1, Input<Floating>, exticr1),
990993
PE2: (pe2, 2, Input<Floating>, exticr1),
@@ -1019,7 +1022,7 @@ gpio!(GPIOE, gpioe, gpioeen, PE, 4, [
10191022
feature = "stm32f469",
10201023
feature = "stm32f479"
10211024
))]
1022-
gpio!(GPIOF, gpiof, gpiofen, PF, 5, [
1025+
gpio!(GPIOF, gpiof, 5, PF, 5, [
10231026
PF0: (pf0, 0, Input<Floating>, exticr1),
10241027
PF1: (pf1, 1, Input<Floating>, exticr1),
10251028
PF2: (pf2, 2, Input<Floating>, exticr1),
@@ -1054,7 +1057,7 @@ gpio!(GPIOF, gpiof, gpiofen, PF, 5, [
10541057
feature = "stm32f469",
10551058
feature = "stm32f479"
10561059
))]
1057-
gpio!(GPIOG, gpiog, gpiogen, PG, 6, [
1060+
gpio!(GPIOG, gpiog, 6, PG, 6, [
10581061
PG0: (pg0, 0, Input<Floating>, exticr1),
10591062
PG1: (pg1, 1, Input<Floating>, exticr1),
10601063
PG2: (pg2, 2, Input<Floating>, exticr1),
@@ -1091,7 +1094,7 @@ gpio!(GPIOG, gpiog, gpiogen, PG, 6, [
10911094
feature = "stm32f469",
10921095
feature = "stm32f479"
10931096
))]
1094-
gpio!(GPIOH, gpioh, gpiohen, PH, 7, [
1097+
gpio!(GPIOH, gpioh, 7, PH, 7, [
10951098
PH0: (ph0, 0, Input<Floating>, exticr1),
10961099
PH1: (ph1, 1, Input<Floating>, exticr1),
10971100
PH2: (ph2, 2, Input<Floating>, exticr1),
@@ -1111,7 +1114,7 @@ gpio!(GPIOH, gpioh, gpiohen, PH, 7, [
11111114
]);
11121115

11131116
#[cfg(any(feature = "stm32f401"))]
1114-
gpio!(GPIOH, gpioh, gpiohen, PH, 7, [
1117+
gpio!(GPIOH, gpioh, 7, PH, 7, [
11151118
PH0: (ph0, 0, Input<Floating>, exticr1),
11161119
PH1: (ph1, 1, Input<Floating>, exticr1),
11171120
]);
@@ -1128,7 +1131,7 @@ gpio!(GPIOH, gpioh, gpiohen, PH, 7, [
11281131
feature = "stm32f469",
11291132
feature = "stm32f479"
11301133
))]
1131-
gpio!(GPIOI, gpioi, gpioien, PI, 8, [
1134+
gpio!(GPIOI, gpioi, 8, PI, 8, [
11321135
PI0: (pi0, 0, Input<Floating>, exticr1),
11331136
PI1: (pi1, 1, Input<Floating>, exticr1),
11341137
PI2: (pi2, 2, Input<Floating>, exticr1),
@@ -1155,7 +1158,7 @@ gpio!(GPIOI, gpioi, gpioien, PI, 8, [
11551158
feature = "stm32f469",
11561159
feature = "stm32f479"
11571160
))]
1158-
gpio!(GPIOJ, gpioj, gpiojen, PJ, 9, [
1161+
gpio!(GPIOJ, gpioj, 9, PJ, 9, [
11591162
PJ0: (pj0, 0, Input<Floating>, exticr1),
11601163
PJ1: (pj1, 1, Input<Floating>, exticr1),
11611164
PJ2: (pj2, 2, Input<Floating>, exticr1),
@@ -1182,7 +1185,7 @@ gpio!(GPIOJ, gpioj, gpiojen, PJ, 9, [
11821185
feature = "stm32f469",
11831186
feature = "stm32f479"
11841187
))]
1185-
gpio!(GPIOK, gpiok, gpioken, PK, 10, [
1188+
gpio!(GPIOK, gpiok, 10, PK, 10, [
11861189
PK0: (pk0, 0, Input<Floating>, exticr1),
11871190
PK1: (pk1, 1, Input<Floating>, exticr1),
11881191
PK2: (pk2, 2, Input<Floating>, exticr1),

0 commit comments

Comments
 (0)