FreeRTOS中打开关闭任务切换
2017-08-10 18:02
155 查看
本文介绍FreeRTOS中解决多任务之间互相影响的两种方法。
1 基本临界区
基本临界区是指宏 taskENTER_CRITICAL()与taskEXIT_CRITICAL()之间的代码区间,下面是一段范例代码。Critical Sections 也被称作Critical Regions。
临界区是提供互斥功能的一种非常原始的实现方法。临界区的工作仅仅是简单地把中断全部关掉,或是关掉优先级在configMAX_SYSCAL_INTERRUPT_PRIORITY 及以下的中断——依赖于具体使用的FreeRTOS 移植。抢占式上下文切换只可能在某个中断中完成,所以调用taskENTER_CRITICAL()的任务可以在中断关闭的时段一直保持运行态,直到退出临界区。
临界区必须只具有很短的时间,否则会反过来影响中断响应时间。在每次调用taskENTER_CRITICAL()之后,必须尽快地配套调用一taskEXIT_CRITICAL()。从这个角度来看,对标准输出的保护不应当采用临界区,因为写终端在时间上会是一个相对较长的操作。
临界区嵌套是安全的,因为内核有维护一个嵌套深度计数。临界区只会在嵌套深度为0 时才会真正退出——即在为每个之前调用的taskENTER_CRITICAL()都配套调用了taskEXIT_CRITICAL()之后。
2 挂起(锁定)调度器
也可以通过挂起调度器来创建临界区。挂起调度器有些时候也被称为锁定调度器。基本临界区保护一段代码区间不被其它任务或中断打断。由挂起调度器实现的临界区只可以保护一段代码区间不被其它任务打断,因为这种方式下,中断是使能的。
如果一个临界区太长而不适合简单地关中断来实现,可以考虑采用挂起调度器的方式。但是唤醒(resuming, or un-suspending)调度器却是一个相对较长的操作。所以评估哪种是最佳方式需要结合实际情况。
vTaskSuspendAll() API 函数
void vTaskSuspendAll( void );
通过调用 vTaskSuspendAll()来挂起调度器。
挂起调度器可以停止上下文切换而不用关中断。如果某个中断在调度器挂起过程中要求进行上下文切换,则个这请求也会被挂起,直到调度器被唤醒后才会得到。
xTaskResumeAll() API 函数
portBASE_TYPE xTaskResumeAll( void );
嵌套调用 vTaskSuspendAll()和xTaskResumeAll()是安全的,因为内核有维护一个嵌套深度计数。调度器只会在嵌套深度计数为0 时才会被唤醒——即在为每个之前调用的vTaskSuspendAll()都配套调用了xTaskResumAll()之后。
1 基本临界区
基本临界区是指宏 taskENTER_CRITICAL()与taskEXIT_CRITICAL()之间的代码区间,下面是一段范例代码。Critical Sections 也被称作Critical Regions。
/* 为了保证对PORTA寄存器的访问不被中断,将访问操作放入临界区。 进入临界区 */ taskENTER_CRITICAL(); /* 在taskENTER_CRITICAL()与 taskEXIT_CRITICAL()之间不会切换到其它任务。 中断可以执行,也允许嵌套,但只是针对优先级高于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断 –而且这些中断不允许访问FreeRTOS API函数. */ PORTA |= 0x01; /* 我们已经完成了对PORTA的访问,因此可以安全地离开临界区了。 */ taskEXIT_CRITICAL(); |
临界区必须只具有很短的时间,否则会反过来影响中断响应时间。在每次调用taskENTER_CRITICAL()之后,必须尽快地配套调用一taskEXIT_CRITICAL()。从这个角度来看,对标准输出的保护不应当采用临界区,因为写终端在时间上会是一个相对较长的操作。
临界区嵌套是安全的,因为内核有维护一个嵌套深度计数。临界区只会在嵌套深度为0 时才会真正退出——即在为每个之前调用的taskENTER_CRITICAL()都配套调用了taskEXIT_CRITICAL()之后。
2 挂起(锁定)调度器
也可以通过挂起调度器来创建临界区。挂起调度器有些时候也被称为锁定调度器。基本临界区保护一段代码区间不被其它任务或中断打断。由挂起调度器实现的临界区只可以保护一段代码区间不被其它任务打断,因为这种方式下,中断是使能的。
如果一个临界区太长而不适合简单地关中断来实现,可以考虑采用挂起调度器的方式。但是唤醒(resuming, or un-suspending)调度器却是一个相对较长的操作。所以评估哪种是最佳方式需要结合实际情况。
vTaskSuspendAll() API 函数
void vTaskSuspendAll( void );
通过调用 vTaskSuspendAll()来挂起调度器。
挂起调度器可以停止上下文切换而不用关中断。如果某个中断在调度器挂起过程中要求进行上下文切换,则个这请求也会被挂起,直到调度器被唤醒后才会得到。
xTaskResumeAll() API 函数
portBASE_TYPE xTaskResumeAll( void );
portBASE_TYPE xTaskResumeAll( void ); 返回值 在调度器挂起过程中,上下文切换请求也会被挂起,直到调度器被唤醒后才会得到执行。如果一个挂起的上下文切换请求在xTaskResumeAll()返回前得到执行,则函数返回pdTRUE。在其它情况下,xTaskResumeAll()返回pdFALSE。没有挂起的上下文切换,以及挂起的上下文切换在返回前没有被执行。 |
相关文章推荐
- FreeRTOS 任务调度 任务切换
- 【转】WinForm中实现各窗体之间切换,关闭,打开的操作
- FreeRTOS---任务切换
- FreeRTOS高级篇4---FreeRTOS任务切换分析
- 定时自动关闭程序、打开网页和隐藏任务计划
- jquery切换div,打开关闭按钮
- 前端设计js+Tab切换可关闭+添加并自动判断是否已打开自动切换当前状态
- 使用selenium+python;在页面A点击一个按钮跳转到页面B,页面A没有关闭,浏览器打开了一个B,切换窗口定位页面B的元素
- FreeRTOS学习之:任务切换解析
- FreeRTOS任务切换解析
- [Vim]vim学习笔记--多个文件打开,切换,关闭
- 使用宏定义打开/关闭调试输出(debug版本与release版本互相切换)
- 解决: ctrl+shift 快速切换输入法导致自动关闭当前打开的任何窗口的问题
- FreeRTOS任务切换解析
- [Vim]vim学习笔记--多个文件打开,切换,关闭
- C# 打开多个进度条窗口 ,完成任务后如何自动关闭。比如WIN的复制文件一样。
- Visual Studio 2008 中使用API打开file://形式的文件,关闭后文件被删除
- SourceInsight打开,切换工程出错问题。
- windows 7 休眠关闭/打开
- ucosii任务切换OS_TASK_SW()