十五、中断管理

文章详细阐述了FreeRTOS中两套API函数的使用场景和区别,特别是在中断处理中的应用。带后缀FromISR的函数用于中断服务,不直接进行任务切换,而是通过参数指示。中断的延时处理通常涉及记录标志位。FreeRTOS可管理的中断优先级由configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY配置,PendSV中断用于任务调度。文章还讨论了如何判断中断是否可管理以及PendSV中断在任务切换中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、两套API函数

(1)使用场景不同

在读写队列等FreeRTOS提供API函数均有两套(如下图所示),其可用于不同的场景。
在这里插入图片描述
一套可以在任务和中断中使用(带有后缀FromISR的),另一套只能在任务中使用。

(2)更进一步的区别——xHigherPriorityTaskWoken 参数

在这里插入图片描述

关键在于 xHigherPriorityTaskWoken 参数,当然如果不想使用这个参数可知直接传NULL,
在上图中前一个API函数可能导致任务阻塞、任务切换,即上下文切换,这个函数可能很长时间才能返回,在函数内部实现了任务切换
而后一个函数也可能导致任务切换,但是不会在函数内部进行切换。而是返回一个参数来表示是否需要切换。(明显后者的效率更高)

(3)那么使用带后缀FromISR的话,任务切换是如何进行的呢?

1)自己根据参数判断

在这里插入图片描述

2)调用API函数进行判断

在这里插入图片描述

在这里插入图片描述

2、中断的延时处理——即中断服务函数中记录标志位,退出后才在任务中进行处理

对于中断的处理来说,ISR要尽量的快,所以对于中断的处理来说一般是分为如下的两个部分(即中断的延时处理)
在这里插入图片描述
具体可以如下例子:
在这里插入图片描述

3、FreeRTOS中对中断的管理

(1)FreeRTOS可管理的最高中断优先级的设置

对于前面临界资源访问中提出的问题——关闭中断是否是关闭了所有中断呢?
答案是没有关闭所有中断,如下图中:
在这里插入图片描述

假定横线上方的中断为A类,下方的为B类,A类中断服务函数中绝对不能调用上面说的带有FromISR后缀的中断,而B类可以。
所有对于前面的读写队列等操作中关闭的中断仅仅是上面假定的B类中断 (systick也属于假定的B类中断,还有PendSV、其他硬件中断等)

前面提到自己设想的A B类中断的划分:用户可以自定义配置系统可管理的最高中断优先级的宏定义
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY , 它 是 用 于 配 置 内 核 中 的basepri 寄存器的,当 basepri 设置为某个值的时候,NVIC 不会响应比该优先级低的中断,而优先级比之更高的中断则不受影响。

(2)那么在FreeRTOS提供的API中代码端是如何判断是否可以管理的呢?

在每个带有FromISR后缀的API函数内部均调用了一个函数(见下图)来判断当前优先级是否有效(即判断当前优先级是否对于一个阈值,对于这一点的优先级数值越小优先级越高
当判断当前优先级有效的时候才能进行带有FromISR后缀的API函数内部的后续代码(这个是FreeRTOS所做的措施)
在这里插入图片描述
这个API内部最终关键代码如下:
在这里插入图片描述
所以若在优先级高于可管理的最高优先级的中断处理函数里面调用了带有FromISR后缀的API函数,进入这个API函数后,此时因为当前优先级无效,所以这个API函数会进入死循环,即认为系统死机。

(3)FreeRTOS中经典的可管理的几类中断

主要是有systick中断、PendSV中断和一些硬件中断;其中前两个中断的优先级是最低的,其都是用于任务的切换。
具体是在开启调度器的API函数里面实现的:

	/* Make PendSV and SysTick the lowest priority interrupts. */
	portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
	portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;

其中里面用到的宏定义为:


1. #define __NVIC_PRIO_BITS          4 /*!< STM32 uses 4 Bits for the Priority Levels    */
2. #define configPRIO_BITS       		__NVIC_PRIO_BITS

3. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY			15         //中断最低优先级

4. #define configKERNEL_INTERRUPT_PRIORITY     ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

5.#define portNVIC_PENDSV_PRI					( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
6.#define portNVIC_SYSTICK_PRI				( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
    
    

(4)Pendsv中断的作用

对于systick中断服务程序的作用前面提到了,那么PendSV中断(任务调度中断)服务程序的作用是什么呢?

PendSV中断服务程序的作用:保存当前任务的现场、挑出当前优先级最高的就绪任务(在前面说到的链表中找,实际直接调用vTaskSwitchContext())并切换挑出来的任务来执行

即任务的切换是在 PendSV 中断服务函数中完成的。

那么问题又来了——为什么前面说任务的切换是在systick中断中完成的呢?
实际上是在SysTick中断中触发PendSV中断,实际的任务切换是在PendSV的中断服务函数中完成的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值