123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- //! Blinks an LED
- //!
- //! This assumes that a LED is connected to pc13 as is the case on the blue pill board.
- //!
- //! Please note according to RM0008:
- //! "Due to the fact that the switch only sinks a limited amount of current (3 mA), the use of
- //! GPIOs PC13 to PC15 in output mode is restricted: the speed has to be limited to 2MHz with
- //! a maximum load of 30pF and these IOs must not be used as a current source (e.g. to drive a LED)"
- #![no_std]
- #![no_main]
- use panic_halt as _;
- use stm32f1xx_hal as hal;
- use crate::hal::{
- gpio::{gpioc, Output, PushPull},
- pac::{interrupt, Interrupt, Peripherals, EXTI},
- prelude::*,
- rtc::Rtc,
- };
- use core::cell::RefCell;
- use cortex_m::{asm::wfi, interrupt::Mutex};
- use cortex_m_rt::entry;
- use embedded_hal::digital::v2::OutputPin;
- // A type definition for the GPIO pin to be used for our LED
- type LEDPIN = gpioc::PC13<Output<PushPull>>;
- // Make LED pin globally available
- static G_LED: Mutex<RefCell<Option<LEDPIN>>> = Mutex::new(RefCell::new(None));
- // Make RTC globally available
- static G_RTC: Mutex<RefCell<Option<Rtc>>> = Mutex::new(RefCell::new(None));
- // Make EXTI registers globally available
- static G_EXTI: Mutex<RefCell<Option<EXTI>>> = Mutex::new(RefCell::new(None));
- // Toggle LED every 3 seconds
- const TOGGLE_INTERVAL_SECONDS: u32 = 3;
- // The f100 does not have an RTC, so this example is disabled
- #[cfg(feature = "stm32f101")]
- #[entry]
- fn main() -> ! {
- loop {
- continue;
- }
- }
- #[cfg(not(feature = "stm32f101"))]
- #[interrupt]
- fn RTCALARM() {
- static mut LED: Option<LEDPIN> = None;
- static mut RTC: Option<Rtc> = None;
- static mut EXTI: Option<EXTI> = None;
- let led = LED.get_or_insert_with(|| {
- cortex_m::interrupt::free(|cs| G_LED.borrow(cs).replace(None).unwrap())
- });
- let rtc = RTC.get_or_insert_with(|| {
- cortex_m::interrupt::free(|cs| G_RTC.borrow(cs).replace(None).unwrap())
- });
- let exti = EXTI.get_or_insert_with(|| {
- cortex_m::interrupt::free(|cs| G_EXTI.borrow(cs).replace(None).unwrap())
- });
- exti.pr.write(|w| w.pr17().set_bit());
- rtc.set_alarm(rtc.current_time() + TOGGLE_INTERVAL_SECONDS);
- let _ = led.toggle();
- }
- #[cfg(not(feature = "stm32f101"))]
- #[entry]
- fn main() -> ! {
- let dp = Peripherals::take().unwrap();
- let mut pwr = dp.PWR;
- let mut rcc = dp.RCC.constrain();
- // Set up the GPIO pin
- let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);
- let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
- let _ = led.set_high(); // Turn off
- cortex_m::interrupt::free(|cs| *G_LED.borrow(cs).borrow_mut() = Some(led));
- // Set up the EXTI (see notes in section 18.4.2 of reference manual)
- let exti = dp.EXTI;
- exti.ftsr.write(|w| w.tr17().set_bit());
- exti.imr.write(|w| w.mr17().set_bit());
- cortex_m::interrupt::free(|cs| *G_EXTI.borrow(cs).borrow_mut() = Some(exti));
- // Set up the RTC
- // Enable writes to the backup domain
- let mut backup_domain = rcc.bkp.constrain(dp.BKP, &mut rcc.apb1, &mut pwr);
- // Start the RTC
- let mut rtc = Rtc::rtc(dp.RTC, &mut backup_domain);
- rtc.set_time(0);
- rtc.set_alarm(TOGGLE_INTERVAL_SECONDS);
- rtc.listen_alarm();
- cortex_m::interrupt::free(|cs| *G_RTC.borrow(cs).borrow_mut() = Some(rtc));
- // Enable RTCALARM IRQ
- unsafe { cortex_m::peripheral::NVIC::unmask(Interrupt::RTCALARM) };
- loop {
- wfi();
- }
- }
|