Search code examples
rustembeddedinterrupt-handlingcortex-mstm32f3

My EXTI0 interrupt handler is not overwritten/working properly (STM32F3Discovery)


I'm trying to learn about coding for embedded devices and want to implement an interrupt. For that, I have written a program where the main function is just a loop that blinks one led and the interrupt should light up another led to test if everything has worked.

My code looks like the following:

#![no_main]
#![no_std]

use f3discovery::{Tim6, set_high};

use cortex_m;
use cortex_m_rt::entry;
use stm32f30x::interrupt;


#[inline(never)]
fn delay_ms(ms: u16) {
    Tim6::new_ms(ms).setup();
    Tim6::start();
    while Tim6::check_finish() {}
    Tim6::reset();
}


const RCC_AHBENR: u32 = 0x4002_1014;
const RCC_APB2ENR: u32 = 0x4002_1018;

const _GPIOA_MODER: u32 = 0x4800_0000;
const GPIOA_PUPDR: u32 = 0x4800_000C;
const _GPIOA_BSRR: u32 = 0x4800_0018;

const _SYSCFG_EXTICR1 : u32 = 0x4001_0008;

const EXTI_IMR1 : u32 = 0x4001_0400;
const EXTI_RTSR1 : u32 = 0x4001_0408;
const EXTI_PR1 : u32 = 0x4001_0414;

const NVIC_ISER0 : u32 = 0xE000_E100;

#[entry]
fn main() -> ! {
    let (mut leds, _rcc, _tim6) = aux9::init();

    Tim6::enable();
    
    set_high(RCC_AHBENR, 1 << 17);
    set_high(RCC_APB2ENR, 1);
    set_high(GPIOA_PUPDR, 1 << 1);
    set_high(EXTI_IMR1, 1);
    set_high(EXTI_RTSR1, 1);
    set_high(NVIC_ISER0, 1 << 6);

    loop {
        leds[0].on();
        delay_ms(500);
        leds[0].off();
        delay_ms(500);
    }
}

#[interrupt]
fn EXTI0() {
    let (mut leds, _rcc, _tim6) = aux9::init();

    leds[4].on();
    // delay_ms(500);
    // leds[4].off();
    // delay_ms(500);
    set_high(EXTI_PR1, 1);
}

I'm using the f3discovery module which I wrote myself for the timer and another module (aux9) for the LEDs. When I run the program the first LED blink's until the button is pressed which leads to the interrupt. But the second LED never lights up. Removing the EXTI0 yields the same result which leads me to think the handler is not properly overwritten.

I am gratefull for any advice :)


Solution

  • The reason is the line

    let (mut leds, _rcc, _tim6) = aux9::init();
    

    in the EXTI0 function. The function aux9::init() includes the line

    let p = stm32f0x::Peripherals::take().unwrap()
    

    and the unwrap will panic at the second function call, thus jumping to the panic handler where the program will stay.

    Credits for this to agg.