为了把操作系统和系统底层的异常、中断硬件隔离开来,RT-Thread 把中断和异常封装为一组抽象接口,如下图所示:

rt_interrupt_enter() 和 rt_interrupt_leave():用于在中断服务程序进入和离开时通知内核中断上下文的切换。
中断服务程序注册
rt_isr_handler_t rt_hw_interrupt_install ( int vector,
rt_isr_handler_t handler,
void *param,
char *name );
vector:中断号
handler:中断服务程序
param:传给中断服务程序的参数
name:中断名称
中断服务程序:
static void irq_callback(void *args)
{
rt_interrupt_enter();
rt_sem_release(irq_sem); /* 释放信号量唤醒线程 */
rt_interrupt_leave();
}如果调用了内核的函数,必须添加
rt_interrupt_enter/leave()如果没调用内核的函数,不需要添加。
不能调用会导致阻塞的函数。
如果是 DMA 等这种不需要调用 RT-Thread 内核函数的硬件中断,直接像裸机一样使用就行了,使用 NVIC 注册和使能。(不确定,待实验。)
void DMA1_Channel1_IRQHandler(void)
{
__HAL_DMA_CLEAR_FLAG(&hdma_adc1, DMA_FLAG_TC1);
}
中断使能与屏蔽
屏蔽中断源:
void rt_hw_interrupt_mask(int vector);使能中断源:
void rt_hw_interrupt_umask(int vector);vector 为中断号。
全局中断开关
用于保护临界资源,是一种强大和高效的互斥机制,缺点是关中断时间长会影响系统的实时性。
关中断,线程暂停调度,当前线程独占 CPU。
关闭全局中断:
rt_base_t rt_hw_interrupt_disable(void);返回值:返回之前的中断状态。
打开全局中断:
void rt_hw_interrupt_enable(rt_base_t level);level:恢复中断关闭前的状态。
这两个函数需配对使用:
/* 关闭中断 */
level = rt_hw_interrupt_disable();
/* 执行互斥操作 */
a = a + value;
/* 恢复中断 */
rt_hw_interrupt_enable(level);
开关全局中断的 API 支持多级嵌套使用,比如:
void global_interrupt_demo(void)
{
rt_base_t level0;
rt_base_t level1;
level0 = rt_hw_interrupt_disable();
level1 = rt_hw_interrupt_disable();
// 执行函数功能...
rt_hw_interrupt_enable(level1); // 注意开中断的顺序
rt_hw_interrupt_enable(level0);
}这样做的好处是,假设有一个函数:
void func_a(void)
{
rt_base_t level0;
level0 = rt_hw_interrupt_disable();
// 执行函数功能...
rt_hw_interrupt_enable(level0);
}
需要被其它函数调用:
void func_b(void)
{
func_a();
// 执行函数功能...
}
void func_c(void)
{
rt_base_t level0;
level0 = rt_hw_interrupt_disable();
func_a(); // 这样做也没问题
// 执行函数功能...
rt_hw_interrupt_enable(level0);
}
这个特性可以给开发带来很大的便利,不需要考虑多次开关中断带来的中断状态不确定问题。