一、中断的概念
1.1 rtthread中断处理过程

rtthread将中断分为三个过程:前导程序、中断服务程序、后续程序。

前导程序:保留cpu中断现场,m3核该局部由硬件实现,对于保留现场的寄存器有 PSR、 PC、 LR、 R12、 R3-R0。之后告诉内核解决中断。中断服务程序:在中断触发后要执行的用户操作。后续程序:告诉内核中断解决实现,复原cpu现场。

1.2 中断栈

rtthread会在中断的后期解决中切换栈指针到事后留出的中断栈空间,等中断退出时复原用户的栈指针。
1.3 中断低半部解决

低半部解决用于解决耗时长的操作,举一种应用信号量实现低半部的例子:线程demo_nw_thread阻塞在期待nw_bh_sem,在中断服务程序中开释nw_bh_sem信号让demo_nw_thread线程解决中断的低半部。

rt_sem_t nw_bh_sem;

/ 数 据 读 取、 分 析 的 线 程 /
void demo_nw_thread(void *param)
{

/* 首 先 对 设 备 进 行 必 要 的 初 始 化 工 作 */device_init_setting();/*.. 其 他 的 一 些 操 作..*//* 创 建 一 个 semaphore 来 响 应 Bottom Half 的 事 件 */nw_bh_sem = rt_sem_create("bh_sem", 0, RT_IPC_FLAG_FIFO);while(1){    /* 最 后, 让 demo_nw_thread 等 待 在 nw_bh_sem 上 */    rt_sem_take(nw_bh_sem, RT_WAITING_FOREVER);    /* 接 收 到 semaphore 信 号 后, 开 始 真 正 的 Bottom Half 处 理 过 程 */    nw_packet_parser (packet_buffer);    nw_packet_process(packet_buffer);}

}

int main(void)
{

rt_thread_t thread;/* 创 建 处 理 线 程 */thread = rt_thread_create("nwt",demo_nw_thread, RT_NULL, 1024, 20, 5);if (thread != RT_NULL)rt_thread_startup(thread);

}

void demo_nw_isr(int vector, void *param)
{

/* 当 network 设 备 接 收 到 数 据 后, 陷 入 中 断 异 常, 开 始 执 行 此 ISR *//* 开 始 Top Half 部 分 的 处 理, 如 读 取 硬 件 设 备 的 状 态 以 判 断 发 生 了 何 种 中 断 */nw_device_status_read();/*.. 其 他 一 些 数 据 操 作 等..*//* 释 放 nw_bh_sem, 发 送 信 号 给 demo_nw_thread, 准 备 开 始 Bottom Half */rt_sem_release(nw_bh_sem);/* 然 后 退 出 中 断 的 Top Half 部 分, 结 束 device 的 ISR */

}

二、中断api

要应用中断,首先须要装载一个中断,当中断触发时,就会进入中断处理函数解决。

能够通过rt_hw_interrupt_mask屏蔽指定中断号的中断,防止再次触发的中断对本次中断解决的影响。rtthread提供全局中断的关上和敞开api,这是rtthread线程同步的根底,利用全局中断的关上和敞开能够实现对临界区的爱护。

//装载中断
/*
vector:中断号
handle:中断服务程序
param:中断服务程序的参数
name:中断的名称
*/
rt_isr_handler_t rt_hw_interrupt_install(int vector,

                                            rt_isr_handler_t handler,                                            void *param,                                            char *name);     

//屏蔽中断:可防止再次触发的中断对正在解决的中断的影响
/*
vector:中断号
*/
void rt_hw_interrupt_mask(int vector);

//勾销屏蔽中断
/*
vector:中断号
*/
void rt_hw_interrupt_umask(int vector);

//敞开全局中断
/*
返回函数执行前的中断状态
*/
rt_base_t rt_hw_interrupt_disable(void);

//关上全局中断,与敞开全局中断配合应用,爱护临界区的效率比互斥锁高,对实时性影响较大。
/*
level:中断状态
*/
void rt_hw_interrupt_enable(rt_base_t level);

//中断告诉:批改中断深度 rt_interrupt_nest
void rt_interrupt_enter(void);
void rt_interrupt_leave(void);

三、中断与轮询

轮询模式采纳程序执行的形式:查问到相应的事件对其进行解决。这种形式在实时操作系统中存在的问题是低优先级的线程得不到cpu的使用权,所以通常状况下,RTOS应用中断来驱动外设。
对于低速的状况,中断模式十分好,cpu能够在期待数据到来前解决其它工作。但对于高速设施,因为操作系统切换上下文有8us的事件,如果解决一个25us的工作,数据带宽为8/(25+8)=75.8%,采纳轮询模式不存在上下文切换的问题,数据带宽为100%。
四、示例

本示例的线程通过全局中断开关来爱护全局变量。

/*

  • Copyright (c) 2006-2018, RT-Thread Development Team
    *
  • SPDX-License-Identifier: Apache-2.0
    *
  • Change Logs:
  • Date Author Notes
  • 2018-08-24 yangjie the first version
    */

/ 程序清单:敞开中断进行全局变量的拜访 /

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)
{

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)
{

rt_thread_t thread;/* 创立thread1线程 */thread = rt_thread_create("thread1", thread_entry, (void *)10,                          THREAD_STACK_SIZE,                          THREAD_PRIORITY, THREAD_TIMESLICE);if (thread != RT_NULL)    rt_thread_startup(thread);/* 创立thread2线程 */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);

原文链接:https://club.rt-thread.org/as...