Closed dunajski closed 2 years ago
I think the current problem is that you overwrite the interrupt
with your local assignment of the module here use cortex_m::interrupt::{self, Mutex};
.
Maybe just removing the self
there and using cortex_m::interrupt::free
at the bottom will solver your problem already.
I changed to:
use cortex_m::interrupt::free;
use cortex_m::interrupt::Mutex;
use stm32g0::stm32g071::{self, Interrupt, NVIC, TIM3, interrupt};
and usage of interrupt::free to free.
#[interrupt]
fn TIM2() {
free(|cs| {
if let Some(ref mut tim2) = G_TIM.borrow(cs).borrow_mut().deref_mut() {
tim2.sr.write(|w| w.uif().clear_bit()); // cannot reach here with debugger
}
});
}
I think that my ISR is invkoing in loop. How to clear this interrupt properly? I marked that I can not reach line with comment in ISR. Does anyone know why
if let Some(ref mut tim2) = G_TIM.borrow(cs).borrow_mut().deref_mut()
is evaluated as false?
Perhaps the problem is the interrupt fires before you call replace
on the G_TIM
Option
, so it's None
at that point. You could try making the critical section in main
cover the entire timer setup and storing it in the option instead, like:
rcc_r.apbenr1.write(|w| w.tim3en().set_bit());
interrupt::free(|cs| {
prepare_timer3(timer_r);
G_TIM.borrow(cs).replace(Some(tim3))
});
@adamgreig I think you are right, thank you. I show my whole code, maybe someone will need it in future.
#![no_std]
#![no_main]
use panic_halt as _;
use core::cell::RefCell;
use core::ops::DerefMut;
use cortex_m::interrupt::free;
use cortex_m::interrupt::Mutex;
use cortex_m_rt::entry;
use stm32g0::stm32g071::{self, interrupt, Interrupt, NVIC};
static G_TIM: Mutex<RefCell<Option<stm32g071::TIM2>>> = Mutex::new(RefCell::new(None));
static G_GPIOA: Mutex<RefCell<Option<stm32g071::GPIOA>>> = Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
let p = stm32g071::Peripherals::take().unwrap();
let gpioa = &p.GPIOA;
let rcc_r = &p.RCC;
// enable Clock for GPIOA
rcc_r.iopenr.modify(|_, w| w.iopaen().set_bit());
let tim2 = p.TIM2;
// Nucleo G071RB LED so need to set as output
gpioa.moder.modify(|_, w| unsafe { w.moder5().bits(0b01) });
rcc_r.apbenr1.write(|w| w.tim2en().set_bit());
free(|cs| {
tim2.cr1.write(|w| w.cen().clear_bit());
tim2.psc.write(|w| unsafe { w.psc().bits(16000) });
tim2.arr.write(|w| unsafe { w.arr_l().bits(1000) });
tim2.egr.write(|w| w.ug().set_bit());
tim2.dier.write(|w| w.uie().set_bit());
tim2.cr1.write(|w| w.cen().set_bit());
G_TIM.borrow(cs).replace(Some(tim2));
});
// NVIC unmask interrupt
unsafe {
NVIC::unmask(Interrupt::TIM2);
};
let gpioa = p.GPIOA;
free(|cs| {
G_GPIOA.borrow(cs).replace(Some(gpioa));
});
let mut increment = 0;
loop {
increment += 1;
if increment > 1000 {
increment = 0;
}
}
}
#[interrupt]
fn TIM2() {
free(|cs| {
if let Some(ref mut tim2) = G_TIM.borrow(cs).borrow_mut().deref_mut() {
tim2.sr.write(|w| w.uif().clear_bit());
}
});
free(|cs| {
if let Some(ref mut gpioa) = G_GPIOA.borrow(cs).borrow_mut().deref_mut() {
if gpioa.odr.read().odr5().bit_is_set() {
gpioa.odr.modify(|_, w| w.odr5().clear_bit());
} else {
gpioa.odr.modify(|_, w| w.odr5().set_bit());
}
}
});
}
I have to read more about how Mutex
works.
Few weeks ago I started to learn Rust Embedded. Now I'm stuck, and I would like to ask you for help. So..
I wanted to use TIM3 in my code to change variable (in future peripheral state) and clear (unpend?) interrupt via registers inside ISR.
In C I did something like this inside ISR:
..and now I'm stuck to do this in Rust. At first I show what I've done so far.
And I get this compilation error:
I have problem how to resolve those dependency problem. Could you tell me also that what I did with this Mutex G_TIM is fine? I mean I did this after read this article: https://docs.rust-embedded.org/book/concurrency/#sharing-peripherals I also read this https://users.rust-lang.org/t/rust-embedded-stm32f303-timer-interrupt-hanging/40323 but I don't want to use hal crates.
I also asked at Stackoverflow: how-to-clear-interrupt-with-perpiheral-handle-embedded-rust ... and Rust forum: https://users.rust-lang.org/t/how-to-clear-interrupt-with-peripheral-handle/67214