第12章 任务间通信与同步分解
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
任务间的互斥
任务间的互斥 --- 共享资源的申请使用
Task_A
Task_B
Task_A would print
Prtinter
Task_B would print
备注:数据采集任务A 和数据处理任务B 之间存在互斥关系
12.1 几个重要的概念
临界段:代码的临界段也称为临界区,一旦这部分代码开始执 行,则不允许任何中断打断。为确保临界段代码的执行不被中 断,在进入临界段之前须关中断,而临界段代码执行完毕后, 要立即开中断。 由于Cortex-M3/M4的RTX内核库中没有关闭中断的操作,也就是 说 RTX 的源码中不存在临界段。 用户写应用的时候也有临界段的问题,比如以下两种:
RTX 任务调试信息
12.3 事件标志组
事件标志组是实现多任务同步的有效机制之一。初学者会问采用事件 标志组多麻烦,搞个全局变量不是更简单,其实不然。在裸机编程时 ,使用全局变量的确比较方便,但相比事件标志组主要有如下三个问 题:
使用事件标志组可以让 RTOS 内核有效的管理任务,全局变量是无 法做到的,任务的超时等机制需要用户自己去实现。 使用了全局变量就要防止多任务的访问冲突,使用事件标志组已经 处理好了这个问题。用户无需担心。
嵌入式系统原理与应用
第12章 任务间通信与同步
温州大学物理与电子信息工程学院 杨卫波
前言
RTX配置下是有并发的,但任一个时刻点上只有一个程序在处 理机上运行。实际上并行是会涉及很多问题的,如多人同时在 干活,他们需要共享到一些资源,那就涉及到沟通协调的额外 付出了。 RTX的进程间通讯主要依赖于四种机制:事件(Event)、互斥 锁(Mutex)、信号量(Semaphore)、和邮箱(Mailbox)。 前三种机制侧重进程间的同步,邮箱侧重进程间的数据通讯。
设置的任务延迟时间不再工作。
因此,强烈建议关 RTX 内核定时器中断的时间越短越好。
RTX 任务锁的实现
函数原型: void tsk_unlock (void); 函数描述: 用于使能 RTX 内核定时器中断,因此也就重新开启任务切 换。tsk_unlock 一定要跟 tsk_lock 配套使用。 使用这个函数要注意以下问题:函数 tsk_lock 不支持嵌套调用;不允 许在中断服务程序中调用 tsk_lock。 使用举例: #include <rtl.h> void protect_critical_op() { tsk_lock(); do_critical_op(); tsk_unlock(); }
12.2.3 例程说明
实验内容:
1. K1 按键按下,串口打印。 2. 在调用 printf 函数的地方都加上任务锁,防止多个任务调用此函数造成冲 突,以至于串口打印出现乱码。 3. 各个任务实现的功能如下:
AppTaskUserIF任务 :按键消息处理。
AppTaskLED 任务:LED 闪烁,并串口打印任务正在运行。 AppTaskMsgPro 任务:消息处理,用作 LED 闪烁和串口打印任务正在 运行。 AppTaskStart 任务:启动任务,最高优先级任务,实现按键扫描。
通过关闭 RTOS 内核定时器实现关闭了 RTOS 内核定时器的 话,也就关闭了通过 RTOS 内核定时器中断实现任务切换的 功能,因为在退出定时器中断时需要检测当前需要执行的最 高优先级任务,如果有高优先级任务就绪的话需要做任务切 换。RTX 操作系统是采用的这种方式实现任务锁的。
12.2 RTX 任务锁的实现
函数原型: void tsk_lock (void); 函数描述:禁止 RTX 内核定时器中断,因此也就禁止了任务切换。 注意以下问题:
函数 tsk_lock 不支持嵌套调用;
不允许在中断服务程序中调用 tsk_lock;
RTX 内核定时器被关闭期间,RTX 内核任务调度器和需要时间片调 度的任务被阻塞。
使用事件标志组可以有效的解决中断服务程序和任务之间的同步问 题。
12.3.1 事件标志组的实现
各个任务之间使用事件标志组实现任务的通信或者同步。RTX 每 个任务创建的时候,会自动创建 16 个事件标志,事件标志被存储 到每个任务的任务控制块中,即每个任务支持 16 个事件标志。
RTX配置
四个 RTX 任务的实现
__task void AppTaskMsgPro(void) { while (1) { bsp_LedToggle(1); bsp_LedToggle(4); /* 开启任务锁 */ tsk_lock(); printf("任务AppTaskMsgPro正在运行\r\n"); /* 关闭任务锁 */ tsk_unlock(); os_dly_wait(300); } }
任务锁
任务锁:为了防止当前任务的执行被其它高优先级的任务打断 而提供的锁机制就是任务锁。实现任务锁可以通过给调度器加 锁或者直接关闭RTOS内核定时器(就是前面一直说的系统滴答 定时器)来实现。
通过给调度器加锁实现给调度器加锁的话,就无法实现任务 切换,高优先级任务也就无法抢占低优先级任务的执行,同 时高优先级任务也是无法向低优先级任务切换的。这种方式 只是禁止了调度器工作,并没有关闭任何中断。
读取或者修改变量(特别是任务间通信的全局变量)的代码 ,一般来说这是最常见的临界代码。 调用公共函数的代码,特别是不可重入的来自百度文库数,如果多个任 务都访问这个函数,结果是可想而知的。
几个重要的概念
中断锁:因为Cortex-M3/M4的RTX源码中没有关闭中断的操作, 所以也就没有提供开关中断函数。 用户在自己的应用代码采用裸机时如何开关中断的,在使用了 RTX后仍然使用以前的开关中断函数即可。
13:42
嵌入式系统原理与应用
2
任务间的同步
任务间的同步 --- 各任务运行的先后、触发等关系
Task_A
Task_B
Task_A Write Data into Data_Buffer
Data_Buffer
Task_B Read Data from Data_Buffer
备注:数据采集任务A 和数据处理任务B 之间存在同步关系