您的位置:首页 > 其它

FreeRTOS中打开关闭任务切换

2017-08-10 18:02 155 查看
本文介绍FreeRTOS中解决多任务之间互相影响的两种方法。

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();

临界区是提供互斥功能的一种非常原始的实现方法。临界区的工作仅仅是简单地把中断全部关掉,或是关掉优先级在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 );

portBASE_TYPE xTaskResumeAll( void );

 

返回值 在调度器挂起过程中,上下文切换请求也会被挂起,直到调度器被唤醒后才会得到执行。如果一个挂起的上下文切换请求在xTaskResumeAll()返回前得到执行,则函数返回pdTRUE。在其它情况下,xTaskResumeAll()返回pdFALSE。没有挂起的上下文切换,以及挂起的上下文切换在返回前没有被执行。

嵌套调用 vTaskSuspendAll()和xTaskResumeAll()是安全的,因为内核有维护一个嵌套深度计数。调度器只会在嵌套深度计数为0 时才会被唤醒——即在为每个之前调用的vTaskSuspendAll()都配套调用了xTaskResumAll()之后。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  freertos