Hi. I'm trying to configure the timer interrupt with stm32f3 crate. But the interrupt is never occurred. I have enabled TIM7 interrupt with NVIC and enable the update interrupt in tim7.dier register. But it seems something is still lacked. I have failed to find useful information in the reference book of stm32f303. I also tried interrupt in cortex-m, but it didn't work either.
The code in this topic works well. But in compared with the code there, I didn't miss anything.
#![no_main]
#![no_std]
use cortex_m_rt::entry;
use panic_halt as _;
use stm32f3::stm32f303;
use stm32f303::{interrupt, Interrupt, NVIC};
#[entry]
fn main() -> ! {
let dp = stm32f303::Peripherals::take().unwrap();
let rcc = &dp.RCC;
// init TIM7 timer
let tim7 = &dp.TIM7;
rcc.apb1enr.modify(|_, w| w.tim7en().set_bit());
tim7.cr1.modify(|_, w| w.cen().clear_bit());
tim7.psc.write(|w| w.psc().bits(7_999));
tim7.arr.write(|w| w.arr().bits(50));
// enable interrupt
NVIC::unpend(Interrupt::TIM7);
unsafe {
NVIC::unmask(Interrupt::TIM7);
}
tim7.dier.modify(|_, w| w.uie().set_bit());
// enable the counter
tim7.cr1.modify(|_, w| w.cen().set_bit());
loop {}
}
#[interrupt]
fn TIM7() {
let dp = stm32f303::Peripherals::take().unwrap();
let rcc = &dp.RCC;
rcc.ahbenr.modify(|_, w| w.iopeen().set_bit());
let gpioe = &dp.GPIOE;
gpioe.moder.modify(|_, w| w.moder9().output());
gpioe.odr.modify(|_, w| w.odr9().set_bit());
let tim7 = &dp.TIM7;
tim7.sr.modify(|_, w| w.uif().clear_bit());
NVIC::unpend(Interrupt::TIM7);
}
Aha, I have found the error. Nothing is missed in the configuration of the timer and interrupt. But let dp = stm32f303::Peripherals::take().unwrap(); in TIM7 function causes an error. So when I set a breakpoint at the next line, it cannot be reached.
I have finished a simple horse race lamp program. I am very curious about how to share peripheral register structs with interrupt handlers in a better way. Thank you for helping me.
#![no_main]
#![no_std]
use cortex_m_rt::entry;
use panic_halt as _;
use stm32f3::stm32f303::{self, rcc::ahbenr::IOPGEN_R};
use stm32f303::{interrupt, Interrupt, NVIC};
static mut TIMER: Option<stm32f303::TIM7> = None;
static mut GPIOE: Option<stm32f303::GPIOE> = None;
static mut i: u8 = 0;
unsafe fn get_gpioe() -> &'static mut stm32f303::GPIOE {
if let Some(ref mut gpioe) = GPIOE {
&mut *gpioe
} else {
panic!()
}
}
unsafe fn get_timer() -> &'static mut stm32f303::TIM7 {
if let Some(ref mut timer) = TIMER {
&mut *timer
} else {
panic!()
}
}
#[entry]
fn main() -> ! {
let dp = stm32f303::Peripherals::take().unwrap();
let rcc = &dp.RCC;
// enable interrupt
NVIC::unpend(Interrupt::TIM7);
unsafe {
NVIC::unmask(Interrupt::TIM7);
}
// init LED
rcc.ahbenr.modify(|_, w| w.iopeen().set_bit());
{
let gpioe = &dp.GPIOE;
gpioe.moder.modify(|_, w| {
w.moder8()
.output()
.moder9()
.output()
.moder10()
.output()
.moder11()
.output()
.moder12()
.output()
.moder13()
.output()
.moder14()
.output()
.moder15()
.output()
});
}
// init TIM7 timer
{
let tim7 = &dp.TIM7;
rcc.apb1enr.modify(|_, w| w.tim7en().set_bit());
tim7.cr1.modify(|_, w| w.cen().clear_bit());
tim7.psc.write(|w| w.psc().bits(7_999));
tim7.arr.write(|w| w.arr().bits(50));
tim7.dier.modify(|_, w| w.uie().set_bit());
// enable the counter
tim7.cr1.modify(|_, w| w.cen().set_bit());
}
// set the value of static TIMER and GPIOE
unsafe {
GPIOE = Some(dp.GPIOE);
TIMER = Some(dp.TIM7);
}
loop {}
}
#[interrupt]
fn TIM7() {
let tim7 = unsafe { get_timer() };
NVIC::unpend(Interrupt::TIM7);
tim7.sr.modify(|_, w| w.uif().clear_bit());
let gpioe = unsafe { get_gpioe() };
unsafe {
if i == 0 {
gpioe.odr.modify(|_, w| w.odr9().set_bit());
gpioe.odr.modify(|_, w| w.odr8().clear_bit());
} else if i == 1 {
gpioe.odr.modify(|_, w| w.odr10().set_bit());
gpioe.odr.modify(|_, w| w.odr9().clear_bit());
} else if i == 2 {
gpioe.odr.modify(|_, w| w.odr11().set_bit());
gpioe.odr.modify(|_, w| w.odr10().clear_bit());
} else if i == 3 {
gpioe.odr.modify(|_, w| w.odr12().set_bit());
gpioe.odr.modify(|_, w| w.odr11().clear_bit());
} else if i == 4 {
gpioe.odr.modify(|_, w| w.odr13().set_bit());
gpioe.odr.modify(|_, w| w.odr12().clear_bit());
} else if i == 5 {
gpioe.odr.modify(|_, w| w.odr14().set_bit());
gpioe.odr.modify(|_, w| w.odr13().clear_bit());
} else if i == 6 {
gpioe.odr.modify(|_, w| w.odr15().set_bit());
gpioe.odr.modify(|_, w| w.odr14().clear_bit());
} else if i == 7 {
gpioe.odr.modify(|_, w| w.odr8().set_bit());
gpioe.odr.modify(|_, w| w.odr15().clear_bit());
}
i = if i == 7 { 0 } else { i + 1 };
}
}
I think your get_peripheral function in your latest example (and the more specific versions in the previous examples before that) are highly dangerous. Using them, it's very easy to get multiple mutable references to the same memory, which is unsound.
However, I think the best way to solve this problem is to just use RTIC. It is really good and will generate the most efficient code based on how you access resources. I highly recommend you look at it with an open mind.
Another note, in case you don't already know: The stm32f3 library is what we call a PAC (Peripheral Access Crate), which is a very low-level way to access the hardware. Depending on your use case, it might be preferable to use stm32f3xx-hal instead. I haven't used it (so I can't vouch for it), but its development seems very active.