学习FreeRTOS(3):两种中断

学习FreeRTOS(3):两种中断

典型情况下,程序进入临界区将关闭所有中断。FreeRTOS则提供了一种机制,在进入临界区时仅关闭部分中断,另一部分中断可以继续响应。这种机制让系统享有多任务特性的同时保证极高的实时性。

http://blog.csdn.net/zoomdy/article/details/50659822
mingdu.zheng at gmail dot com

概述

FreeRTOS的选项configMAX_SYSCALL_INTERRUPT_PRIORITY把中断根据优先级分成了两种,一种是优先级低于或等于该选项的中断,另一种是优先级高于该选项的中断。当调用taskENTER_CRITICIAL进入临界区时FreeRTOS仅关闭了优先级低于或等于该选项的中断,而优先级高于该选项的中断则仍然可以得到响应。不妨把前一种中断称之为临界区相关中断,把后一种中断称之为临界区无关中断。

高实时性

引入临界区无关中断机制后,系统获得了更高的实时性能。临界区无关中断不会因为系统进入临界区而被关闭,因此系统进入临界区也可以零延时地响应关键事件中断。系统层的代码不会对临界区无关中断进行任何干涉,该部分中断的控制权完全掌握在应用层,应用层可以根据具体的需求使用或不使用临界区无关中断,可以根据具体算法和时机关闭或开启临界区无关中断。通过严格控制临界区无关中断的关闭时间可以获得系统能提供的最高实时性能。

限制

由于系统层代码是使用临界区作为共享资源保护的基本机制,而临界区无关中断是不受临界区控制的,那么在临界区无关中断中使用系统层API是不安全的,会导致共享资源竞争问题,会导致数据破坏。所以临界区无关中断有一个限制,那就是其中断服务例程不能调用任何系统API,即使是被标注为可以从中断服务例程调用的API也不能被临界区无关中断服务例程调用。

共享资源保护

任务在处理与临界区相关中断之间的共享资源保护时非常简单,只要进入临界区即可。而任务在处理与临界区无关中断的共享资源保护时除了进入临界区外还要做一些额外的工作,即关闭临界区无关中断。之所以还要进入临界区是因为需要避免中断优先级反转,如果仅仅关闭了高优先级的临界区无关中断,而没有关闭低优先级的临界区相关中断,那么在关闭临界区无关中断期间发生了临界区相关中断时,将转而执行临界区相关中断,这导致因为执行低优先级终端而使高优先级中断的关中断时间变长,也就是发生了中断优先级反转。

关中断

这里以Cortex-M架构的微控制器为例讲一下如何关闭临界区无关中断。Cortex-M有两个特殊功能寄存器可用来关闭或打开中断,primask和basepri,将primask置1将屏蔽所有中断(HardFault和NMI除外,这两个算是异常不算中断吧),将basepri设置为某个优先级,则可以屏蔽优先级低于或等于设定值的中断。另外Cortex-M的NVIC也可以对单独的中断源进行屏蔽。
FreeRTOS的临界区保护函数taskENTER_CRITICAL是设置basepri寄存器值为configMAX_SYSCALL_INTERRUPT_PRIORITY来实现的。也就是说只是关闭了优先级低于或等于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断。也只有使用basepri才能将中断分成上述两种。

// taskENTER_CRITICAL()
__asm volatile
    (
    "    mrs r0, basepri    \n"
    "    mov r1, %0         \n"
    "    msr basepri, r1    \n"
    "    bx lr              \n"
    :: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "r0", "r1"
);

关闭临界区无关中断的办法有这么几种,一是设置primask为1,这将关闭所有中断,包括所有临界区相关中断和临界区无关中断,这种方式最简单,但是如有多个临界区无关中断并且其优先级不同,那这种方式是不太适用的,因为这种方式会使高优先级的中断也被关闭。二是将basepri设置为要关闭中断的优先级,这会关闭临界区相关中断的同时关闭所期望的临界区无关中断,而更高优先级的中断仍然可以响应,这是最理想的方式。三是使用NVIC关闭单独的中断,在使用NVIC关闭临界区无关中断之前首先要调用临界区函数taskENTER_CRITICAL关闭所有临界区相关中断,否则会引起严重的中断优先级反转。
需要注意的是,Cortex-M的中断优先级以0为最高,以255为最低,数值和优先级是反的。

唤醒任务

临界区无关中断不能调用任何系统API,因此是不能直接唤醒任务的。不过办法总是有的,仍然以Cortex-M架构的微控制器为例。Cortex-M除了可以由硬件产生中断信号外,也可以由软件来触发中断信号。可以将某一个空闲的中断源与临界区无关中断配合使用。这个空闲的中断源需要配置成临界区相关中断,即其中断优先级应该小于等于configMAX_SYSCALL_INTERRUPT_PRIORITY,这样才可以调用系统API唤醒任务。当临界区无关中断需要唤醒任务时,通过NVIC触发与之配合的临界区相关中断,当退出临界区无关中断服务例程后就可以执行相配合的临界区相关中断服务例程来唤醒任务,这算是曲线救国吗?

总结

如果使用FreeRTOS时,某些中断响应时间不符合要求,或者实时性不达标,或者事件输出抖动比较厉害,都可以使用FreeRTOS提供的这种机制提高系统性能,当然任何优化都是有代价,这种优化的代价是需要额外处理关中断和唤醒任务等。当然,满足系统需求才是最终目标。现在,我终于明白eCos为什么使用basepri寄存器关中断而不是使用primask,也是同样的缘由啊。我也终于明白Cortex-M为什么还会有basepri寄存器,没有硬件的支持,软件闹翻天也不济事吧。

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值