中断
中断在许多方面与异常不同,但它们的操作和使用方式基本相似,并且它们也由相同的中断控制器处理。异常由 Cortex-M 架构定义,而中断始终是特定供应商(甚至通常是芯片)的特定实现,无论是在命名还是功能上。
中断允许很大的灵活性,在尝试以高级方式使用它们时需要考虑这一点。我们不会在本书中介绍这些用法,但最好记住以下几点
- 中断具有可编程的优先级,这决定了它们处理程序的执行顺序
- 中断可以嵌套和抢占,即中断处理程序的执行可能会被另一个更高优先级的中断打断
- 一般来说,需要清除触发中断的原因以防止无限次地重新进入中断处理程序
运行时的一般初始化步骤始终相同
- 设置外围设备以在期望的情况下生成中断请求
- 在中断控制器中设置中断处理程序的期望优先级
- 在中断控制器中启用中断处理程序
与异常类似,cortex-m-rt
crate 提供了一个 interrupt
属性来声明中断处理程序。可用的中断(以及它们在中断处理程序表中的位置)通常通过 svd2rust
从 SVD 描述中自动生成。
// Interrupt handler for the Timer2 interrupt
#[interrupt]
fn TIM2() {
// ..
// Clear reason for the generated interrupt request
}
中断处理程序看起来像普通函数(除了缺少参数),类似于异常处理程序。然而,由于特殊的调用约定,它们不能被固件的其他部分直接调用。但是,可以在软件中生成中断请求以触发跳转到中断处理程序。
与异常处理程序类似,也可以在中断处理程序中声明 static mut
变量以进行安全状态保存。
#[interrupt]
fn TIM2() {
static mut COUNT: u32 = 0;
// `COUNT` has type `&mut u32` and it's safe to use
*COUNT += 1;
}
有关此处演示的机制的更详细描述,请参阅异常部分。