Rust中的结构内部中断

t98cgbkg  于 2023-03-08  发布在  其他
关注(0)|答案(1)|浏览(126)

我是Rust embedded的新手,我想在一个结构体中使用#[interrupt]宏。在下面的示例中,我将2个GPIO配置为输入并使能中断:

use core::cell::RefCell;
use cortex_m::interrupt::Mutex;
use stm32f4xx_hal::{
    gpio::{gpioa::PA4, gpiod::PD2, Edge, ExtiPin, Input, PinMode},
    interrupt,
    pac::{
        Interrupt::{EXTI2, EXTI4},
        EXTI,
    },
    syscfg::SysCfg,
};

type EosRightPin = PD2<Input>;
type EosLeftPin = PA4<Input>;

static G_EOSR: Mutex<RefCell<Option<EosRightPin>>> = Mutex::new(RefCell::new(None));
static G_EOSL: Mutex<RefCell<Option<EosLeftPin>>> = Mutex::new(RefCell::new(None));

pub struct EndOfStroke {
    eos_r: EosRightPin,
    eos_l: EosLeftPin,
}

impl EndOfStroke {
    pub fn new(pin_eos_r: PD2<impl PinMode>, pin_eos_l: PA4<impl PinMode>) -> Self {
        let eos_r = pin_eos_r.into_input().internal_pull_down(true);
        let eos_l = pin_eos_l.into_input().internal_pull_down(true);

        Self { eos_r, eos_l }
    }

    pub fn enable_interrupt(mut self, syscfg: &mut SysCfg, exti: &mut EXTI) {
        // Enable external interrupt
        self.eos_r.make_interrupt_source(syscfg);
        self.eos_l.make_interrupt_source(syscfg);
        self.eos_r.trigger_on_edge(exti, Edge::Rising);
        self.eos_l.trigger_on_edge(exti, Edge::Rising);
        self.eos_r.enable_interrupt(exti);
        self.eos_l.enable_interrupt(exti);

        cortex_m::interrupt::free(|cs| {
            G_EOSR.borrow(cs).replace(Some(self.eos_r));
            G_EOSL.borrow(cs).replace(Some(self.eos_l));
        });

        // Enable the external interrupt
        unsafe {
            cortex_m::peripheral::NVIC::unmask(EXTI2);
            cortex_m::peripheral::NVIC::unmask(EXTI4);
        }
    }

    #[interrupt]
    fn EXTI2() {
        //TODO disable motor if it is going to the right

        // Clear the interrupt
        cortex_m::interrupt::free(|cs| {
            let mut eos_r = G_EOSR.borrow(cs).borrow_mut();
            eos_r.as_mut().unwrap().clear_interrupt_pending_bit();
        });
    }

    #[interrupt]
    fn EXTI4() {
        //TODO disable motor if it is going to the left

        // Clear the interrupt
        cortex_m::interrupt::free(|cs| {
            let mut eos_l = G_EOSL.borrow(cs).borrow_mut();
            eos_l.as_mut().unwrap().clear_interrupt_pending_bit();
        });
    }
}

问题是

error[E0425]: cannot find function `__cortex_m_rt_EXTI2` in this scope
  --> src/bsp/end_of_stroke.rs:53:5
   |
53 |     #[interrupt]
   |     ^^^^^^^^^^^^ not found in this scope
   |
   = note: this error originates in the attribute macro `interrupt` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider using the associated function
   |
53 |     Self::#[interrupt]
   |     ++++++
error[E0425]: cannot find function `__cortex_m_rt_EXTI4` in this scope
  --> src/bsp/end_of_stroke.rs:64:5
   |
64 |     #[interrupt]
   |     ^^^^^^^^^^^^ not found in this scope
   |
   = note: this error originates in the attribute macro `interrupt` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider using the associated function
   |
64 |     Self::#[interrupt]
   |     ++++++

如果我在main.rs内部使用这些中断函数,它会工作,但我不知道为什么。

zsbz8rwp

zsbz8rwp1#

解决方案是将中断函数移到EndOfStrike的实现之外。但如果有人知道,我无法解释为什么。

use core::cell::RefCell;
use cortex_m::interrupt::Mutex;
use stm32f4xx_hal::{
    gpio::{gpioa::PA4, gpiod::PD2, Edge, ExtiPin, Input, PinMode},
    interrupt,
    pac::{
        Interrupt::{EXTI2, EXTI4},
        EXTI,
    },
    syscfg::SysCfg,
};

type EosRightPin = PD2<Input>;
type EosLeftPin = PA4<Input>;

static G_EOSR: Mutex<RefCell<Option<EosRightPin>>> = Mutex::new(RefCell::new(None));
static G_EOSL: Mutex<RefCell<Option<EosLeftPin>>> = Mutex::new(RefCell::new(None));

pub struct EndOfStroke {
    eos_r: EosRightPin,
    eos_l: EosLeftPin,
}

impl EndOfStroke {
    pub fn new(pin_eos_r: PD2<impl PinMode>, pin_eos_l: PA4<impl PinMode>) -> Self {
        let eos_r = pin_eos_r.into_input().internal_pull_down(true);
        let eos_l = pin_eos_l.into_input().internal_pull_down(true);

        Self { eos_r, eos_l }
    }

    pub fn enable_interrupt(mut self, syscfg: &mut SysCfg, exti: &mut EXTI) {
        // Enable external interrupt
        self.eos_r.make_interrupt_source(syscfg);
        self.eos_l.make_interrupt_source(syscfg);
        self.eos_r.trigger_on_edge(exti, Edge::Rising);
        self.eos_l.trigger_on_edge(exti, Edge::Rising);
        self.eos_r.enable_interrupt(exti);
        self.eos_l.enable_interrupt(exti);

        cortex_m::interrupt::free(|cs| {
            G_EOSR.borrow(cs).replace(Some(self.eos_r));
            G_EOSL.borrow(cs).replace(Some(self.eos_l));
        });

        // Enable the external interrupt
        unsafe {
            cortex_m::peripheral::NVIC::unmask(EXTI2);
            cortex_m::peripheral::NVIC::unmask(EXTI4);
        }
    }
}

#[interrupt]
fn EXTI2() {
    //TODO disable motor if it is going to the right

    // Clear the interrupt
    cortex_m::interrupt::free(|cs| {
        let mut eos_r = G_EOSR.borrow(cs).borrow_mut();
        eos_r.as_mut().unwrap().clear_interrupt_pending_bit();
    });
}

#[interrupt]
fn EXTI4() {
    //TODO disable motor if it is going to the left

    // Clear the interrupt
    cortex_m::interrupt::free(|cs| {
        let mut eos_l = G_EOSL.borrow(cs).borrow_mut();
        eos_l.as_mut().unwrap().clear_interrupt_pending_bit();
    });
}

相关问题