内核大佬来告诉你,什么叫中断管理(rtthread)

257 阅读3分钟

一.中断管理

当 CPU 正在处理内部数据时,外界发生了紧急情况,要求 CPU 暂停当前的工作转去处理这个 异步事件。处理完毕后,再回到原来被中断的地址,继续原来的工作,这样的过程称为中断。实现这一功能的系统称为 中断系统,申请 CPU 中断的请求源称为 中断源。中断是一种异常,异常是导致处理器脱离正常运行转向执行特殊代码的任何事件,如果不及时进行处理,轻则系统出错,重则会导致系统毁灭性地瘫痪。如下图是一个简单的中断示意图。

二.RT-Thread 中断工作机制

1.中断向量表

中断向量表是所有中断处理程序的入口,如下图所示是 Cortex-M 系列的中断处理过程:把一个函数(用户中断服务程序)同一个虚拟中断向量表中的中断向量联系在一起。当中断向量对应中断发生的时候,被挂接的用户中断服务程序就会被调用执行。

在 Cortex-M 内核上,所有中断都采用中断向量表的方式进行处理,即当一个中断触发时,处理器将直接判定是哪个中断源,然后直接跳转到相应的固定位置进行处理,每个中断服务程序必须排列在一起放在统一的地址上(这个地址必须要设置到 NVIC 的中断向量偏移寄存器中)。中断向量表一般由一个数组定义或在起始代码中给出,默认采用起始代码给出:

__Vectors DCD __initial_sp ; Top of Stack

DCD Reset_Handler ; Reset 处理函数

DCD NMI_Handler ; NMI 处理函数

DCD HardFault_Handler ; Hard Fault 处理函数

DCD MemManage_Handler ; MPU Fault 处理函数

DCD BusFault_Handler ; Bus Fault 处理函数

DCD UsageFault_Handler ; Usage Fault 处理函数

DCD 0 ; 保留

DCD 0 ; 保留

DCD 0 ; 保留

DCD 0 ; 保留

DCD SVC_Handler ; SVCall 处理函数

DCD DebugMon_Handler ; Debug Monitor 处理函数

DCD 0 ; 保留

DCD PendSV_Handler ; PendSV 处理函数

DCD SysTick_Handler ; SysTick 处理函数

… …

NMI_Handler PROC

EXPORT NMI_Handler [WEAK]

B .

ENDP

HardFault_Handler PROC

EXPORT HardFault_Handler [WEAK]

B .

ENDP

2.中断处理过程

RT-Thread 中断管理中,将中断处理程序分为中断前导程序、用户中断服务程序、中断后续程序三部分,如下图:

三.RT-Thread 中断管理接口

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

\

4.全局中断开关使用示例

这是一个中断的应用例程:在多线程访问同一个变量时,使用开关全局中断对该变量进行保护,如下代码所示:

使用开关中断进行全局变量的访问

#include <rthw.h>

#include <rtthread.h>

#define THREAD_PRIORITY 20

#define THREAD_STACK_SIZE 512

#define THREAD_TIMESLICE 5

/* 同时访问的全局变量 */

static rt_uint32_t cnt;

void thread_entry(void *parameter)

{undefined

rt_uint32_t no;

rt_uint32_t level;

no = (rt_uint32_t) parameter;
while (1)
{
    /* 关闭全局中断 */
    level = rt_hw_interrupt_disable();
    cnt += no;
    /* 恢复全局中断 */
    rt_hw_interrupt_enable(level);

    rt_kprintf("protect thread[%d]'s counter is %d\n", no, cnt);
    rt_thread_mdelay(no * 10);
}

}

/* 用户应用程序入口 */

int interrupt_sample(void)

{undefined

rt_thread_t thread;

/* 创建 t1 线程 */
thread = rt_thread_create("thread1", thread_entry, (void *)10,
                          THREAD_STACK_SIZE,
                          THREAD_PRIORITY, THREAD_TIMESLICE);
if (thread != RT_NULL)
    rt_thread_startup(thread);


/* 创建 t2 线程 */
thread = rt_thread_create("thread2", thread_entry, (void *)20,
                          THREAD_STACK_SIZE,
                          THREAD_PRIORITY, THREAD_TIMESLICE);
if (thread != RT_NULL)
    rt_thread_startup(thread);

return 0;
}

/* 导出到 msh 命令列表中 */

MSH_CMD_EXPORT(interrupt_sample, interrupt sample);

仿真运行结果如下:

\ | /

RT - Thread Operating System

/ | \ 3.1.0 build Aug 27 2018

2006 - 2018 Copyright by rt-thread team

msh >interrupt_sample

msh >protect thread[10]'s counter is 10

protect thread[20]'s counter is 30

protect thread[10]'s counter is 40

protect thread[20]'s counter is 60

protect thread[10]'s counter is 70

protect thread[10]'s counter is 80

protect thread[20]'s counter is 100

protect thread[10]'s counter is 110

protect thread[10]'s counter is 120

protect thread[20]'s counter is 140