如何从GPIO触发中断

3

我正在将一个玩具应用程序移植到RTFM框架上,但是很难弄清楚如何通过GPIO触发中断。

fn init(p: init::Peripherals, _r: init::Resources) -> init::LateResources {
    let dp: stm32f103xx::Peripherals = p.device;
    let mut rcc = dp.RCC.constrain();
    let mut gpioa = dp.GPIOA.split(&mut rcc.apb2);
    let int = gpioa.pa0.into_floating_input(&mut gpioa.crl);
    dp.EXTI.imr.write(|w| w.mr0().set_bit()); // unmask the interrupt (EXTI)
    dp.EXTI.ftsr.write(|w| w.tr0().set_bit()); // trigger interrupt on falling edge  

    init::LateResources {
        EXTI: dp.EXTI,
        INT: int
    }
}

fn idle(t: &mut Threshold, mut r: idle::Resources) -> ! {
    loop { rtfm::wfi(); }
}

fn exti0(_t: &mut Threshold, mut r: EXTI0::Resources) {
    // never called
}

这个设置使我能够触发中断,但是当处理程序应该被调用时,却出现了SEGV错误。我转储了二进制文件,在INTERRUPTS部分,ext0中断8000058指向地址080024e7。我在二进制文件中找不到对应的函数,所以可能是链接器错误?

我曾经认为RTFM将中断映射到任务名称,而我确实有一个名为"EXTI0"的任务。


不相关,但我建议在启用中断之前设置触发模式(下降沿)。否则,您可能会收到错误触发的杂散中断。 - Clifford
STM32参考手册已经足够清晰明了。请问有什么具体内容不清楚吗? - too honest for this site
1个回答

2
我不了解Rust,但必要的硬件步骤如下:
  1. 启用APB2时钟
  2. 配置GPIO
  3. 将EXTI0线连接到GPIO PA0引脚(通过SYSCFG单元)
  4. 配置EXTI模式(中断)和触发器(下降沿)
  5. 配置NVIC(设置EXTI0优先级,启用EXIT0中断)
  6. 启用EXTI0中断
我在代码中没有看到第3步或第5步。需要在NVIC中启用IRQ并在EXTI外设中启用中断。
使用标准外设库,在C语言中,第3步应该是这样的:
SYSCFG_EXTILineConfig( EXTI_PortSourceGPIOA, EXTI_PinSource0 );

我不知道Rust的等效语法是什么。


1
@PeterJ_01;语言设计者总是为自己的语言做出这样的宣传。你不可能会推广一种不可靠、缓慢和复杂的语言,对吧!? - Clifford
你知道uC软件开发与“大型计算机”软件开发不同。我见过很多试图使其“简单、易用和快速”的尝试,但它们都失败了。而40年前的好C规则仍然适用 :)。顺便说一句 - 我去年开始在uC上使用C++,它非常有前途(生成的代码与C一样好)。 - 0___________
2
Rust 绝对不简单,这点我可以告诉你。RTFM 很有趣,因为它保证无死锁、无数据竞争,使用硬件辅助调度,高效且内存安全,所以我正在努力理解它。如果我想要快速的结果,我会直接使用纯 C 或 Arduino。 - Michael Böckling

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接