Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
学习过程总结
中断管理
RT-Thread学习笔记 --(7)RT-Thread中断管理学习总结
发布于 2020-12-21 15:48:18 浏览:2288
订阅该版
[tocm] 前面几篇文章总结了RT-Thread多线程相关内容的学习过程,包括多线程的使用,多线程的同步,多线程的通信,关于多线程相关的学习总结,可以查看以下链接: [RT-Thread学习笔记 --(4)RT-Thread多线程学习总结](https://club.rt-thread.org/ask/article/2366.html) [RT-Thread学习笔记 --(5)RT-Thread线程间同步学习总结](https://club.rt-thread.org/ask/article/2386.html) [RT-Thread学习笔记 --(6)RT-Thread线程间通信学习总结](https://club.rt-thread.org/ask/article/2422.html) 本文的内容是关于RT-Thread中断管理的学习总结,包括简单地介绍了什么是中断,裸机中断与RT-Thread中断有什么区别,RT-Thread是如何处理中断的,RT-Thread内核提供哪些中断相关的接口,等等。 关于RT-Thread中断管理相关的内容,官方提供了比较丰富的文档作为参考,具体可以查看以下链接: [https://www.rt-thread.org/document/site/programming-manual/interrupt/interrupt/#rt-thread](https://www.rt-thread.org/document/site/programming-manual/interrupt/interrupt/#rt-thread) 本文尝试从以下几个方面总结一下RT-Thread中断管理的学习过程 ![1.png](/uploads/20201221/43b845ba136b7cf657367c773f1760a4.png) ## **中断相关的概念描述** **什么是中断?**中断,顾名思义就是一项正在进行的工作,突然间被其他事情打断,导致原来正在进行的工作不能继续正常进行,而需要去把其他事情处理完,才能回来继续进行原来的工作。 如何通俗地理解中断?想象一下这样的场景,周末你正在家里愉快地写着代码,突然间你的手机铃声响了,你必须停下手里的工作,记录代码写到哪个阶段,然后就去接这个电话了。“写代码”就是正在进行的工作,“电话响起”就是中断事件。 这个电话是媳妇打过来的,她让你去菜市场买点韭菜和猪肉,晚上包饺子吃,媳妇的话哪敢不听,于是你觉得菜市场买东西比较重要,挂掉电话后就去买东西了,买完东西回来后,再接着写刚刚还没完成的代码。“菜市场买东西”就是中断服务程序,这就是一个典型的中断处理过程。 ![2.png](/uploads/20201221/7a7e84a873f27ec014a6344d8f74e923.png) **关于中断的操作模式和特权级别**,Cortex-M的处理器有三种状态划分,分别是:特权级处理模式,特权级线程模式,用户级线程模式。这三种状态的关系,如下图所示。 ![3.png](/uploads/20201221/43dfc39d4650cf17a5e2a9be35c5762e.png) 从上图可以看出,中断或异常的服务程序,总是处于特权级处理模式的。而RT-Thread系统内核复位上电时启动的主线程(main线程),是运行在特权级线程模式的。其他用户创建的线程,是运行在用户级线程模式的。 为什么处理器要区分特权级和用户级?特权,顾名思义就是处理器如果工作在这个级别下,权限就会比较高,就可以访问一些特殊的寄存器,以防止用户级的代码访问这些特殊寄存器,对数据进行破坏。中断由于其特殊性,所以,中断函数是工作在特权级别下的。 **裸机中断与操作系统中断两者有什么区别呢**?我们在裸机代码中处理硬件中断的时候,一般只要编写中断处理函数就可以了,这种方式处理中断,简单且直接。 然而,有了操作系统之后,所有的东西都变了,要考虑的问题就多了很多。因为操作里面运行了很多线程,中断来了之后,就要告知操作系统,把当前运行线程的信息保存到栈里面,再去处理中断服务程序,处理完中断要再回去处理线程,此时又可能涉及到线程切换调度,而线程切换本身又需要PendSV中断参与。 所以,在裸机处理中断和在操作系统中处理中断,简直就是天壤之别。 ## **RT-Thread 中断处理机制** 了解过Cortex-M系列单片机的工程师,一般都知道在芯片的汇编启动文件startup_xxx.s里面,有一个中断向量表,所有的中断都是通过这个中断向量表来进行处理的。 当一个中断异常触发的时候,处理器将会判断是哪个中断源,然后跳转到固定位置进行处理,每个中断服务程序的地址入口必须是放到统一的地址上,也就是需要设置到NVIC的中断向量偏移寄存器里面,中断向量表如下图所示。 ![4.png](/uploads/20201221/ee502fadc3cbd6f373678901aba974c2.png) 其实,不管有没有操作系统的参与,一旦硬件发送中断和异常之后,中断的入口都是在这个中断向量表的。区别无非就是在裸机环境下,直接处理中断服务程序,而在有操作系统的情况下,需要先保留线程的运行情况,然后再处理中断,处理完中断后,再恢复线程的运行环境。 **硬件中断的优先级是最高的,任何线程的优先级都要低于硬件中断,因此,只要发生了硬件中断事件,系统就必须要进行相应的处理。** RT-Thread在处理中断的时候,一般都会有三个阶段:中断前导程序,中断服务程序,中断后续程序,这三个阶段,如下图所示。 ![5.png](/uploads/20201221/4a79fc18656fe79b5e87c855fdf21831.png) **中断前导程序**的主要工作是,当中断事件发生的时候,处理器的硬件会把当前CPU相关的寄存器参数自动压入中断栈里面。程序需要调用rt_interrupt_enter()函数,把全局变量rt_interrupt_nest进行加1操作,这个全局变量是用来记录中断的嵌套层数的。 **用户中断服务程序**的主要工作分两种情况,一种是不进行线程切换,另一种是进行线程切换。不进行线程切换的话,中断服务程序和中断后续程序运行完成后,将返回被中断的线程。 而如果要进行线程切换,则会调用rt_hw_context_switch_interrupt() 函数进行上下文切换,这个函数主要是设置变量rt_interrupt_to_thread,然后触发PendSV中断。 在这里要注意一下:由于PendSV中断的优先级最低,不能进行中断抢占,因此即使触发了该中断,但由于此时还在用户中断处理函数里面,所以PendSV中断还处于等待阶段,只有退出了中断后续程序,才会进行PendSV中断处理,才会进行线程的上下文切换。所以,线程的上下文切换是不会在用户中断里面进行的,是在中断结束后进行的。 **中断后续程序**的主要工作是,通知系统内核离开中断状态,通过调用rt_interrupt_leave()函数,将全局变量rt_interrupt_nest进行减1操作,然后从中断栈里面恢复恢复CPU相关的寄存器参数。 这里恢复CPU寄存器参数的时候需要注意,如果在用户中断里面涉及到线程切换,那么这个时候就需要恢复到新的线程CPU寄存器参数,而不是恢复到被中断打断的线程CPU寄存器参数。 RT-Thread操作系统在处理中断的时候,通常采用“上半部分(Top Half)”和“底半部分(Bottom Half)”这种方式。原因在于,操作系统本身不会对中断服务程序的处理时间做任何假设和限制,但为了保证系统的实时性,用户需要保证中断服务程序在尽可能短的时间内完成。 如何理解“上半部分(Top Half)”和“底半部分(Bottom Half)”这种中断处理方式?还是以买菜为例。媳妇来电话让你到菜市场买菜(中断事件),但你考虑到如果长时间中断不写代码,会导致思路断链,为了避免这种情况(避免长时间处理中断服务),完全可以在网上下单购买(短时间的中断处理),生鲜超市收到下单信息(信号量、邮件、消息队列),就会安排快递小哥送货上门,买菜这么耗时的工作就由其他人(其他线程)去完成了。 ![6.png](/uploads/20201221/d45e077c22eea878208846b24ba79597.png) “上半部分(Top Half)”和“底半部分(Bottom Half)”这种中断处理方式,主要是应用在一些需要耗时处理中断事务的场合,比如数据的接收和处理。通常接收数据的时间比较短,只要把接收到的数据保存下来即可,但处理数据的过程就可能比较耗时,这样就需要分开来处理,上半部分就是接收数据,底半部分就是耗时的数据处理。 ## **RT-Thread中断相关的API函数接口** 为了把操作系统和硬件底层的中断异常隔离开来,RT-Thread系统内核把中断和异常封装为一组抽象的接口,具体的函数接口如下图所示。 ![7.png](/uploads/20201221/2389bce11390e3871b0de50026be320d.png) ## **RT-Thread中断相关的应用示例** RT-Thread中断相关的应用示例,主要是为了验证中断相关的API接口函数,例如全局中断开关的使用示例,通过按键中断示例来验证“上半部分(Top Half)”和“底半部分(Bottom Half)”这种中断处理方式。 示例源码下载链接:[https://github.com/embediot/rtthread_study_notes](https://github.com/embediot/rtthread_study_notes) **全局中断开关示例**,主要是为了验证多线程访问同一个变量时,使用开关全局中断的方式对该全局变量进行临界区保护。 **按键中断示例**主要是为了验证“上半部分(Top Half)”和“底半部分(Bottom Half)”这种中断处理方式。通过按键触发中断事件,在中断服务函数里面发送邮件,通知线程进行相应的处理。 在irq_test.h头文件里面,通过打开相应的宏定义开关,重新编译工程源码,下载到开发板即可验证实验现象,如下图所示。 ![8.png](/uploads/20201221/370e4ff66f15a2aa201be8367a2a78ee.png) ## **RT-Thread中断应用的注意事项** 中断是一种异常,当系统发生中断异常的时候就必须要进行处理,在RT-Thread实时操作系统里面处理中断的时候,如果不及时处理或对中断处理不当,轻则会造成系统出错或逻辑混乱,重则会导致系统毁灭性地瘫痪。 在处理RT-Thread中断异常的时候,有以下注意事项: 1.中断服务程序工作在特权级处理模式,优先级比任何线程要高,任何线程都不能抢占中断服务程序。 2.在操作系统里面,可以支持中断嵌套,高优先级中断可以抢占低优先级中断,线程的重新调度是在所有中断都处理完之后才重新启动的。 3.在Cortex-M架构里面,中断发生时CPU的寄存器入栈是由硬件自动完成的,中断的前导程序通常只是记录中断的嵌套层数。 4.RT-Thread采用独立的内存空间作为中断栈,而不是采用线程栈作为中断栈,这种方式随着线程的增加,减少内存占用的效果也越明显。 5.建议采用“上半部分(Top Half)”和“底半部分(Bottom Half)”这种方式来处理中断异常,中断服务程序的处理时间应尽可能短。 6.使用全局中断开关是禁止多线程访问临界区最简单的一种方式,这种方式可以应用在任何场合,但要注意这种方式对系统实时性影响巨大,使用不当会破坏系统的实时性能。使用全局中断锁的时间应尽可能短。 7.全局中断开关支持多级中断嵌套使用,每次调用rt_hw_interrupt_enable()函数,可以让系统恢复到关中断之前的状态(这个状态有可能是关中断也有可能是开中断)。 8.中断服务程序是运行在特权处理模式下的,在这种运行模式里面是不能使用挂起当前线程操作的相关函数的,因为中断服务程序的运行环境里面根本不存在线程。 感谢阅读! ![qrcode40.png](/uploads/20201221/44c54532c5d27ecb8d818f1e7e1b22cc.png)
1
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
embediot
这家伙很懒,什么也没写!
文章
11
回答
0
被采纳
0
关注TA
发私信
相关文章
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
cubemx
PWM
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
xusiwei1236
8
个答案
2
次被采纳
踩姑娘的小蘑菇
1
个答案
2
次被采纳
用户名由3_15位
9
个答案
1
次被采纳
bernard
4
个答案
1
次被采纳
RTT_逍遥
3
个答案
1
次被采纳
本月文章贡献
聚散无由
2
篇文章
15
次点赞
catcatbing
2
篇文章
5
次点赞
Wade
2
篇文章
4
次点赞
Ghost_Girls
1
篇文章
7
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部