Skip to content

Commit

Permalink
Use bare_metal::CriticalSection for GPIO configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
urdh committed Aug 23, 2024
1 parent b2e2e9d commit a52b4e8
Show file tree
Hide file tree
Showing 27 changed files with 207 additions and 52 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Changed

- Updated the `cast` dependency from 0.2 to 0.3
- Use `bare_metal::CriticalSection` for GPIO configuration (breaking change)

### Added

Expand Down
19 changes: 15 additions & 4 deletions examples/adc_values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use stm32f0xx_hal as hal;

use crate::hal::{pac, prelude::*};

use cortex_m::{interrupt::Mutex, peripheral::syst::SystClkSource::Core};
use bare_metal::Mutex;
use cortex_m::peripheral::syst::SystClkSource::Core;
use cortex_m_rt::{entry, exception};

use core::{cell::RefCell, fmt::Write};
Expand All @@ -25,7 +26,12 @@ fn main() -> ! {
hal::pac::Peripherals::take(),
cortex_m::peripheral::Peripherals::take(),
) {
cortex_m::interrupt::free(move |cs| {
cortex_m::interrupt::free(move |_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { &bare_metal::CriticalSection::new() };

let mut flash = p.FLASH;
let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut flash);

Expand Down Expand Up @@ -60,7 +66,7 @@ fn main() -> ! {
tx.write_str("\n\rThis ADC example will read various values using the ADC and print them out to the serial terminal\r\n").ok();

// Move all components under Mutex supervision
*SHARED.borrow(cs).borrow_mut() = Some(Shared { adc, tx });
*SHARED.borrow(*cs).borrow_mut() = Some(Shared { adc, tx });
});
}

Expand All @@ -74,7 +80,12 @@ fn SysTick() {
use core::ops::DerefMut;

// Enter critical section
cortex_m::interrupt::free(|cs| {
cortex_m::interrupt::free(|_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { bare_metal::CriticalSection::new() };

// Get access to the Mutex protected shared data
if let Some(ref mut shared) = SHARED.borrow(cs).borrow_mut().deref_mut() {
// Read temperature data from internal sensor using ADC
Expand Down
8 changes: 7 additions & 1 deletion examples/blinky.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ fn main() -> ! {
let gpioa = p.GPIOA.split(&mut rcc);

// (Re-)configure PA1 as output
let mut led = cortex_m::interrupt::free(|cs| gpioa.pa1.into_push_pull_output(cs));
let mut led = cortex_m::interrupt::free(|_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { &bare_metal::CriticalSection::new() };
gpioa.pa1.into_push_pull_output(cs)
});

loop {
// Turn PA1 on a million times in a row
Expand Down
7 changes: 6 additions & 1 deletion examples/blinky_adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ fn main() -> ! {

let gpioa = p.GPIOA.split(&mut rcc);

let (mut led, mut an_in) = cortex_m::interrupt::free(move |cs| {
let (mut led, mut an_in) = cortex_m::interrupt::free(move |_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { &bare_metal::CriticalSection::new() };

(
// (Re-)configure PA1 as output
gpioa.pa1.into_push_pull_output(cs),
Expand Down
8 changes: 7 additions & 1 deletion examples/blinky_delay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ fn main() -> ! {
let gpioa = p.GPIOA.split(&mut rcc);

// (Re-)configure PA1 as output
let mut led = cortex_m::interrupt::free(move |cs| gpioa.pa1.into_push_pull_output(cs));
let mut led = cortex_m::interrupt::free(move |_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { &bare_metal::CriticalSection::new() };
gpioa.pa1.into_push_pull_output(cs)
});

// Get delay provider
let mut delay = Delay::new(cp.SYST, &rcc);
Expand Down
7 changes: 6 additions & 1 deletion examples/blinky_multiple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ fn main() -> ! {
let gpioa = p.GPIOA.split(&mut rcc);
let gpiob = p.GPIOB.split(&mut rcc);

let (led1, led2) = cortex_m::interrupt::free(move |cs| {
let (led1, led2) = cortex_m::interrupt::free(move |_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { &bare_metal::CriticalSection::new() };

(
// (Re-)configure PA1 as output
gpioa.pa1.into_push_pull_output(cs),
Expand Down
8 changes: 7 additions & 1 deletion examples/blinky_timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ fn main() -> ! {
let gpioa = p.GPIOA.split(&mut rcc);

// (Re-)configure PA1 as output
let mut led = cortex_m::interrupt::free(move |cs| gpioa.pa1.into_push_pull_output(cs));
let mut led = cortex_m::interrupt::free(move |_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { &bare_metal::CriticalSection::new() };
gpioa.pa1.into_push_pull_output(cs)
});

// Set up a timer expiring after 1s
let mut timer = Timer::tim1(p.TIM1, Hertz(1), &mut rcc);
Expand Down
28 changes: 22 additions & 6 deletions examples/blinky_timer_irq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ use crate::hal::{

use cortex_m_rt::entry;

use bare_metal::Mutex;
use core::cell::RefCell;
use cortex_m::{interrupt::Mutex, peripheral::Peripherals as c_m_Peripherals};
use cortex_m::peripheral::Peripherals as c_m_Peripherals;

// A type definition for the GPIO pin to be used for our LED
type LEDPIN = gpioa::PA5<Output<PushPull>>;
Expand All @@ -35,14 +36,24 @@ fn TIM7() {
static mut INT: Option<Timer<TIM7>> = None;

let led = LED.get_or_insert_with(|| {
cortex_m::interrupt::free(|cs| {
cortex_m::interrupt::free(|_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { bare_metal::CriticalSection::new() };

// Move LED pin here, leaving a None in its place
GLED.borrow(cs).replace(None).unwrap()
})
});

let int = INT.get_or_insert_with(|| {
cortex_m::interrupt::free(|cs| {
cortex_m::interrupt::free(|_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { bare_metal::CriticalSection::new() };

// Move LED pin here, leaving a None in its place
GINT.borrow(cs).replace(None).unwrap()
})
Expand All @@ -55,7 +66,12 @@ fn TIM7() {
#[entry]
fn main() -> ! {
if let (Some(mut p), Some(cp)) = (Peripherals::take(), c_m_Peripherals::take()) {
cortex_m::interrupt::free(move |cs| {
cortex_m::interrupt::free(move |_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { &bare_metal::CriticalSection::new() };

let mut rcc = p
.RCC
.configure()
Expand All @@ -71,7 +87,7 @@ fn main() -> ! {
let led = gpioa.pa5.into_push_pull_output(cs);

// Move the pin into our global storage
*GLED.borrow(cs).borrow_mut() = Some(led);
*GLED.borrow(*cs).borrow_mut() = Some(led);

// Set up a timer expiring after 1s
let mut timer = Timer::tim7(p.TIM7, Hertz(1), &mut rcc);
Expand All @@ -80,7 +96,7 @@ fn main() -> ! {
timer.listen(Event::TimeOut);

// Move the timer into our global storage
*GINT.borrow(cs).borrow_mut() = Some(timer);
*GINT.borrow(*cs).borrow_mut() = Some(timer);

// Enable TIM7 IRQ, set prio 1 and clear any pending IRQs
let mut nvic = cp.NVIC;
Expand Down
8 changes: 7 additions & 1 deletion examples/dac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ fn main() -> ! {
let mut rcc = dp.RCC.configure().sysclk(8.mhz()).freeze(&mut dp.FLASH);
let gpioa = dp.GPIOA.split(&mut rcc);

let pa4 = cortex_m::interrupt::free(move |cs| gpioa.pa4.into_analog(cs));
let pa4 = cortex_m::interrupt::free(move |_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { &bare_metal::CriticalSection::new() };
gpioa.pa4.into_analog(cs)
});

let mut dac = dac(dp.DAC, pa4, &mut rcc);

Expand Down
19 changes: 15 additions & 4 deletions examples/flash_systick.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use stm32f0xx_hal as hal;

use crate::hal::{gpio::*, pac, prelude::*};

use cortex_m::{interrupt::Mutex, peripheral::syst::SystClkSource::Core, Peripherals};
use bare_metal::Mutex;
use cortex_m::{peripheral::syst::SystClkSource::Core, Peripherals};
use cortex_m_rt::{entry, exception};

use core::cell::RefCell;
Expand All @@ -19,7 +20,12 @@ static GPIO: Mutex<RefCell<Option<gpioa::PA1<Output<PushPull>>>>> = Mutex::new(R
#[entry]
fn main() -> ! {
if let (Some(mut p), Some(cp)) = (pac::Peripherals::take(), Peripherals::take()) {
cortex_m::interrupt::free(move |cs| {
cortex_m::interrupt::free(move |_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { &bare_metal::CriticalSection::new() };

let mut rcc = p.RCC.configure().sysclk(48.mhz()).freeze(&mut p.FLASH);

let gpioa = p.GPIOA.split(&mut rcc);
Expand All @@ -28,7 +34,7 @@ fn main() -> ! {
let led = gpioa.pa1.into_push_pull_output(cs);

// Transfer GPIO into a shared structure
*GPIO.borrow(cs).borrow_mut() = Some(led);
*GPIO.borrow(*cs).borrow_mut() = Some(led);

let mut syst = cp.SYST;

Expand Down Expand Up @@ -62,7 +68,12 @@ fn SysTick() {
static mut STATE: u8 = 1;

// Enter critical section
cortex_m::interrupt::free(|cs| {
cortex_m::interrupt::free(|_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { bare_metal::CriticalSection::new() };

// Borrow access to our GPIO pin from the shared structure
if let Some(ref mut led) = *GPIO.borrow(cs).borrow_mut().deref_mut() {
// Check state variable, keep LED off most of the time and turn it on every 10th tick
Expand Down
19 changes: 15 additions & 4 deletions examples/flash_systick_fancier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use stm32f0xx_hal as hal;

use crate::hal::{gpio::*, pac, prelude::*};

use cortex_m::{interrupt::Mutex, peripheral::syst::SystClkSource::Core, Peripherals};
use bare_metal::Mutex;
use cortex_m::{peripheral::syst::SystClkSource::Core, Peripherals};
use cortex_m_rt::{entry, exception};

use core::cell::RefCell;
Expand All @@ -22,7 +23,12 @@ static GPIO: Mutex<RefCell<Option<LEDPIN>>> = Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
if let (Some(mut p), Some(cp)) = (pac::Peripherals::take(), Peripherals::take()) {
cortex_m::interrupt::free(move |cs| {
cortex_m::interrupt::free(move |_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { &bare_metal::CriticalSection::new() };

let mut rcc = p.RCC.configure().sysclk(48.mhz()).freeze(&mut p.FLASH);

// Get access to individual pins in the GPIO port
Expand All @@ -32,7 +38,7 @@ fn main() -> ! {
let led = gpioa.pb3.into_push_pull_output(cs);

// Transfer GPIO into a shared structure
swap(&mut Some(led), &mut GPIO.borrow(cs).borrow_mut());
swap(&mut Some(led), &mut GPIO.borrow(*cs).borrow_mut());

let mut syst = cp.SYST;

Expand Down Expand Up @@ -88,7 +94,12 @@ fn SysTick() {
// Otherwise move it out of the Mutex protected shared region into our exception handler
else {
// Enter critical section
cortex_m::interrupt::free(|cs| {
cortex_m::interrupt::free(|_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { bare_metal::CriticalSection::new() };

// Swap globally stored data with SysTick private data
swap(LED, &mut GPIO.borrow(cs).borrow_mut());
});
Expand Down
7 changes: 6 additions & 1 deletion examples/i2c_find_address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
if let Some(p) = pac::Peripherals::take() {
cortex_m::interrupt::free(move |cs| {
cortex_m::interrupt::free(move |_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { &bare_metal::CriticalSection::new() };

let mut flash = p.FLASH;
let mut rcc = p.RCC.configure().freeze(&mut flash);

Expand Down
23 changes: 17 additions & 6 deletions examples/led_hal_button_irq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ use crate::hal::{
prelude::*,
};

use cortex_m::{interrupt::Mutex, peripheral::Peripherals as c_m_Peripherals};
use bare_metal::Mutex;
use cortex_m::peripheral::Peripherals as c_m_Peripherals;
use cortex_m_rt::entry;

use core::{cell::RefCell, ops::DerefMut};
Expand All @@ -29,7 +30,12 @@ static INT: Mutex<RefCell<Option<EXTI>>> = Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
if let (Some(p), Some(cp)) = (Peripherals::take(), c_m_Peripherals::take()) {
cortex_m::interrupt::free(move |cs| {
cortex_m::interrupt::free(move |_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { &bare_metal::CriticalSection::new() };

// Enable clock for SYSCFG
let rcc = p.RCC;
rcc.apb2enr.modify(|_, w| w.syscfgen().set_bit());
Expand Down Expand Up @@ -64,9 +70,9 @@ fn main() -> ! {
exti.rtsr.modify(|_, w| w.tr1().set_bit());

// Move control over LED and DELAY and EXTI into global mutexes
*LED.borrow(cs).borrow_mut() = Some(led);
*DELAY.borrow(cs).borrow_mut() = Some(delay);
*INT.borrow(cs).borrow_mut() = Some(exti);
*LED.borrow(*cs).borrow_mut() = Some(led);
*DELAY.borrow(*cs).borrow_mut() = Some(delay);
*INT.borrow(*cs).borrow_mut() = Some(exti);

// Enable EXTI IRQ, set prio 1 and clear any pending IRQs
let mut nvic = cp.NVIC;
Expand All @@ -88,7 +94,12 @@ fn main() -> ! {
#[interrupt]
fn EXTI0_1() {
// Enter critical section
cortex_m::interrupt::free(|cs| {
cortex_m::interrupt::free(|_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { bare_metal::CriticalSection::new() };

// Obtain all Mutex protected resources
if let (&mut Some(ref mut led), &mut Some(ref mut delay), &mut Some(ref mut exti)) = (
LED.borrow(cs).borrow_mut().deref_mut(),
Expand Down
8 changes: 6 additions & 2 deletions examples/pwm.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#![deny(unsafe_code)]
#![no_main]
#![no_std]

Expand All @@ -18,7 +17,12 @@ fn main() -> ! {
let mut rcc = dp.RCC.configure().sysclk(8.mhz()).freeze(&mut dp.FLASH);

let gpioa = dp.GPIOA.split(&mut rcc);
let channels = cortex_m::interrupt::free(move |cs| {
let channels = cortex_m::interrupt::free(move |_| {
// SAFETY: We are in a critical section, but the `cortex_m` critical section
// token is not compatible with the `bare_metal` token. Future version of the
// `cortex_m` crate will not supply *any* token to this callback!
let cs = unsafe { &bare_metal::CriticalSection::new() };

(
gpioa.pa8.into_alternate_af2(cs),
gpioa.pa9.into_alternate_af2(cs),
Expand Down
Loading

0 comments on commit a52b4e8

Please sign in to comment.