在 Rust 中中断内部结构

问题描述 投票:0回答:1

我是嵌入式 Rust 的新手,我想在结构中使用

#[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
中使用这些中断函数,它会起作用,但我不知道为什么。

rust interrupt
1个回答
0
投票

解决方案是将中断函数移到

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();
    });
}

© www.soinside.com 2019 - 2024. All rights reserved.