Created
July 26, 2020 00:30
-
-
Save Yatekii/28e341f58a5e3e73325851e2a9bc4fe8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![no_std] | |
#![no_main] | |
extern crate panic_halt; | |
use cortex_m_rt::entry; | |
use stm32f4::stm32f407::{self, interrupt}; | |
#[entry] | |
fn start() -> ! { | |
// Acquire the device peripherals. They can only be taken once ever. | |
let device_peripherals = stm32f407::Peripherals::take().unwrap(); | |
// Get a reference to GPIOD and RCC to save typing. | |
let gpiod = &device_peripherals.GPIOD; | |
let rcc = &device_peripherals.RCC; | |
let tim2 = &device_peripherals.TIM2; | |
// Enable the GPIOD clock and set PD12 to be an output | |
rcc.ahb1enr.modify(|_, w| w.gpioden().enabled()); | |
gpiod.moder.modify(|_, w| w.moder12().output()); | |
// Set up the timer for slow interrupt generation | |
// NOTE(unsafe): The psc field has not been sufficiently documented | |
// to allow safe writing of arbitrary integer values, so we have to | |
// use unsafe here. This could be fixed by improving the SVD file. | |
rcc.apb1enr.modify(|_, w| w.tim2en().enabled()); | |
tim2.dier.write(|w| w.uie().enabled()); | |
tim2.psc.write(|w| w.psc().bits(1000)); | |
tim2.arr.write(|w| w.arr().bits(2000)); | |
tim2.cr1.write(|w| w.cen().enabled()); | |
// Enable the timer interrupt in the NVIC. | |
unsafe { cortex_m::peripheral::NVIC::unmask(stm32f407::Interrupt::TIM2) }; | |
// The main thread can now go to sleep. | |
// WFI (wait for interrupt) puts the core in sleep until an interrupt occurs. | |
loop { | |
cortex_m::asm::nop(); | |
} | |
} | |
/// Interrupt handler for TIM2 | |
#[interrupt] | |
fn TIM2() { | |
// NOTE(unsafe): We have to use unsafe to access the peripheral | |
// registers in this interrupt handler because we already used `take()` | |
// in the main code. In this case all our uses are safe, not least because | |
// the main thread only calls `wfi()` after enabling the interrupt, so | |
// no race conditions or other unsafe behaviour is possible. | |
// For ways to avoid using unsafe here, consult the Concurrency chapter: | |
// https://rust-embedded.github.io/book/concurrency/concurrency.html | |
// Clear the UIF bit to indicate the interrupt has been serviced | |
unsafe { | |
(*stm32f407::TIM2::ptr()) | |
.sr | |
.modify(|_, w| w.uif().clear_bit()) | |
}; | |
// Read ODR12 to see if the pin is set, and if so, clear it, | |
// otherwise, set it. We use the atomic BSRR register to | |
// set/reset it without needing to read-modify-write ODR. | |
let ptr = stm32f407::GPIOB::ptr(); | |
unsafe { | |
if (*ptr).odr.read().odr12().is_high() { | |
(*ptr).bsrr.write(|w| w.br12().set_bit()); | |
} else { | |
(*ptr).bsrr.write(|w| w.bs12().set_bit()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment