CH04-03-操作系统原理与实践-μCOS-III任务通信.pptx
《CH04-03-操作系统原理与实践-μCOS-III任务通信.pptx》由会员分享,可在线阅读,更多相关《CH04-03-操作系统原理与实践-μCOS-III任务通信.pptx(87页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、嵌入式系统设计原理嵌入式操作系统原理与实践主讲人:赖树明东莞理工学院05事件标志组01通信机制概述02信号量03互斥信号量04消息队列0101通信机制概述通信机制概述01使用实时操作系统,相对于裸机程序的一个优势是可以把复杂的功能划分到不同的任务中,但这些任务的数据以及逻辑功能是存在密切的联系的,因此需要有一种机制可以实现任务之间的通信,以便于使用这些独立的任务可以按我们的设想协调运行起来,uc/OS-III操作系统提供了丰富的任务间通信的机制,可以让我们根据使用场景,选择不同的通信方式。概述A信号量B互斥信号量C消息队列D事件标志组E任务信号量F任务消息队列概述0202信号量信号量介绍API
2、函数接口任务同步示例任务互斥示例信号量02信号量(Semaphore)是一种实现任务间通信的机制,用于任务之间同步或临界资源的互斥访问。通俗理解:信号量是一个正值变量,表示资源的可申请数,当任务申请信号量时,变量值减1,任务使用完成后,再释放信号量,效果是变量值加1;信号量为0时,申请信号号的任务则无法获得信号,表现为退出或者等待挂起,直到有其他任务释放了信号量,这些等待的任务会按照优先级来获取信号量,继续执行其代码。概念信号量介绍n信号量可以细分为两种类型:二进制信号量和计数信号量。n二进制信号量只能取两个值:0或者1,在开发中使用最多的还是是二值信号量这种情形;n计数信号量允许的值介于02
3、55/65535/4294967295之间,具体取决于信号量机制是使用8位、16位,还是32位数据类型实现的。n对于C/OS-III,信号量的最大值由数据类型OS_SEM_CTR(见os_type.h)决定,可以根据需要更改其他类似。特征信号量的使用流程有三个必需的步骤,分别是创建信号量、申请信号量、发送信号量,其他可选操作有删除信号量、中止等待信号量、修改信号值等。使用流程表表4.1 信号量函数信号量函数序号函数名功能描述备注1OSSemCreate()创建一个信号量必须调用2OSSemDel()删除一个信号量必须调用3OSSemPend()等待信号量必须调用4OSSemPendAbort(
4、)中止对信号量的等待可选调用5OSSemPost()发送或发出信号量信号可选调用6OSSemSet()强制信号量计数为所需值可选调用信号量02API函数接口C/OS-III系统使用OS_SEM结构来表示一个信号量,创建信号量,只需要调用系统提供的OSSemCreate函数,根据需要传递必须参数即可创建信号量原型:void OSSemCreate(OS_SEM *p_sem,CPU_CHAR *p_name,OS_SEM_CTR cnt,RTOS_ERR *p_err)功能:创建信号量参数:p_sem:指向要初始化的信号量的指针,一般传递OS_SEM类型变量地址。p_name:指向要分配给信号量
5、名称的指针。cnt:信号量的初始值,如果用于共享资源,则应初始化为可用资源数;如用于表示事件的发生,则应初始化为0。p_err:指向存放错误代码变量的地址,函数调用可能产生的错误码如下:OS_ERR_NONE:无错误,指示信号量创建成功;OS_ERR_CREATE_ISR:在中断服务程序中调用了此函数;OS_ERR_ILLEGAL_CREATE_RUN_TIME:在调用OSSafetyCriticalStart()后尝试创建信号量。OS_ERR_NAME:如果p_name是一个NULL指针 OS_ERR_OBJ_CREATED:如果信号量已经创建,即p_sem前面已经被创建过了。OS_ERR_
6、OBJ_PTR_NULL:如果p_sem是一个NULL指针 OS_ERR_OBJ_TYPE:p_sem类型不是OS_SEM*;信号量02API函数接口示例代码 OS_SEM my_sem_test;/定义信号量全局变量,用于任务同步。/创建一个信号量 OSSemCreate(OS_SEM*)&my_sem_test,(CPU_CHAR*)MySemTest,(OS_SEM_CTR)0,(OS_ERR*)&err);/创建失败,让程序进入死循环,这样在开发阶段方便发现问题。if(err!=OS_ERR_NONE)while(1);信号量02API函数接口调用OSSemPend函数申请指定的信号量
7、,如果所申请的信号量其信号值大于0,则马上获得信号量,同时把信号值减去1,继续执行后面的代码。如果当前信号值是0,则表示当前信号量不可用,此时任务可以选择继续往下运行或者进入挂起状态等待信号量变成正数。申请信号量函数原型:OS_SEM_CTROSSemPend(OS_SEM*p_sem,OS_TICKtimeout,OS_OPTopt,CPU_TS*p_ts,OS_ERR*p_err)函数功能:申请信号量,申请成功任务继续往下运行,信号量不可用时,任务挂起或者返回错误码后继续往下运行(具体哪一种情况由调用函数时给opt参数传递的值决定)。函数参数:p_sem:是指向信号量的指针,一般传递OS_
8、SEM类型变量地址;timeout:超时时间(以时钟节拍为单位)。当opt参数传递为OS_OPT_PEND_BLOCKING,timeout值为大于0时,表示信号量任务挂起的最长等待时间,如超过在该参数指定的时长,信号量还不可用,则任务恢复运行,并且将p_err指向的错误码变量值设置为OS_ERR_TIMEOUT。当值为0时,表示任务将永久挂起,直到等待的信号量变成可用,然后获得信号量恢复运行。opt:OS_OPT_PEND_BLOCKING:任务会阻塞;OS_OPT_PEND_NON_BLOCKING:任务不会阻塞.p_ts:用于存放信号量释放/挂起中止/信号量删除时的时间戳。如不需要时间戳
9、,传NULL。p_err:指向存放错误代码变量的地址,函数调用可能产生的错误码如下:OS_ERR_NONE:指示成功获得信号量;.OS_ERR_PEND_ISR:指示从ISR调用此函数,结果将导致挂起;OS_ERR_TIMEOUT:指示在指定的超时时间内未收到信号量。函数返回值:信号量计数器的当前值,值为0表示当前信号量不可用。一般是通过p_err指向的错误码来判断申请结果。信号量02API函数接口示例代码 函数示例:假设当前信号量my_sem_test已经创建好了。OS_ERR err;/存放函数调用错误码 /没有获得信号量会挂起任务 OSSemPend(&my_sem_test,0,OS_
10、OPT_PEND_BLOCKING,0,&err);/请求信号量 /判断申请信号量是否成功 if(err!=OS_ERR_NONE)/在以下编写没有正确获得信号量但是函数返回时的处理代码 /根据实际情况编写出错处理代码 信号量02API函数接口本示例是使用信号量实现两个任务同步,演示通过信号量实现任务间通信的方法。任务1负责检测按键1是否按下,按下了则发送信号量;任务2负责申请信号量,等待任务1发送信号量后,往下执行代码,控制开发板上的LED。实验的效果是每按下按键1一次,开发板上的LED就会反转一次。发送信号量信号量02任务同步示例主函数OS_SEM key_sem;/定义一个信号量,用于任
11、务同步int main(void)OS_ERR err;CPU_SR_ALLOC();.OSInit(&err);/初始化C/OS-III /创建一个信号量 OSSemCreate(OS_SEM*)&key_sem,(CPU_CHAR*)key_sem,(OS_SEM_CTR)0,/信号值初始值设置为0 (OS_ERR*)&err);/创建失败,让程序进入死循环,这样在开发阶段方便发现问题。if(err!=OS_ERR_NONE)while(1);OS_CRITICAL_ENTER();/进入临界区 /创建开始任务 ./调用OSTaskCreate创建启动任务 OS_CRITICAL_EXIT
12、();/退出临界区 OSStart(&err);/开启C/OS-III信号量02任务同步示例主函数OS_SEM key_sem;/定义一个信号量,用于任务同步int main(void)OS_ERR err;CPU_SR_ALLOC();.OSInit(&err);/初始化C/OS-III /创建一个信号量 OSSemCreate(OS_SEM*)&key_sem,(CPU_CHAR*)key_sem,(OS_SEM_CTR)0,/信号值初始值设置为0 (OS_ERR*)&err);/创建失败,让程序进入死循环,这样在开发阶段方便发现问题。if(err!=OS_ERR_NONE)while(1
13、);OS_CRITICAL_ENTER();/进入临界区 /创建开始任务 ./调用OSTaskCreate创建启动任务 OS_CRITICAL_EXIT();/退出临界区 OSStart(&err);/开启C/OS-III信号量02任务同步示例任务1函数/任务1的任务函数void task1_task(void*p_arg)u8 key;OS_ERR err;while(1)key=KEY_Scan(0);/扫描按键if(key=KEY1_PRES)/如果按下开发板按键1printf(Task1:发送一个信号量rn);/输出发送信号量提示OSSemPost(&key_sem,OS_OPT_PO
14、ST_1,&err);/发送信号量printf(当前信号值:%urn,key_sem.Ctr);OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err);/延时10ms 信号量02任务同步示例任务1函数 void task2_task(void*p_arg)u8 num;OS_ERR err;while(1)/没有获得信号量会挂起任务 OSSemPend(&key_sem,0,OS_OPT_PEND_BLOCKING,0,&err);/请求信号量 /判断申请信号量是否成功 if(err!=OS_ERR_NONE)/在以下编写没有正确获得信号量但是函数返
15、回时的处理代码 /.LED1_Toglge();/翻转LED1状态 信号量02任务同步示例本示例是使用信号量实现对共享资源的互斥访问,演示通过信号量实现任务间通信的另一种使用场景。任务1和任务2都需要访问一个共享资源,即一块数据缓冲区,程序中可表示为一个数组,其中任务1对这块数组进行写操作,任务2负责读取出任务1写入的数据。为了保证任务2每次都可以完整读取任务1的一次完成写操作数据,保证数据不会混乱,则任务1和任务2在访问这块共享的内存(数组)时都需要申请同一个信号量,如果信号量被其中一个持有了,则需要等待对方访问完共享资源,然后发送信号量,才可以访问共享资源,从而保证了共享资源的互斥访问。功
16、能说明信号量02任务互斥示例示例框图信号量02任务互斥示例主函数 OS_SEM share_mem_sem;/定义一个信号量,用于保护共享资访问。int main(void)OS_ERR err;CPU_SR_ALLOC();.OSInit(&err);/初始化C/OS-III /创建一个信号量share_mem_sem OSSemCreate(OS_SEM*)&share_mem_sem,(CPU_CHAR*)share_mem_sem,(OS_SEM_CTR)1,/注意本示例初始值不能为0 (OS_ERR*)&err);/创建失败,让程序进入死循环,这样在开发阶段方便发现问题。if(err
17、!=OS_ERR_NONE)while(1);OS_CRITICAL_ENTER();/进入临界区 /调用OSTaskCreate创建启动任务。OS_CRITICAL_EXIT();/退出临界区 OSStart(&err);/开启C/OS-III 信号量02任务互斥示例主函数 void task1_task(void*p_arg)OS_ERR err;uint32_t cnt=1;/记录写入数据的次数 while(1)OSSemPend(&share_mem_sem,0,OS_OPT_PEND_BLOCKING,0,&err);/请求信号量 /判断申请信号量是否成功 if(err!=OS_ER
18、R_NONE)/在以下编写没有正确获得信号量但是函数返回时的处理代码 /以下开始访问共享资源,往array_buf数组中写入数据 sprintf(array_buf,cnt:%05d,cnt);/开始访问共享资源 printf(第%d次写入数据:%srn,cnt,array_buf);/输出写入内容提示 cnt+;/写入次数增加 OSSemPost(&share_mem_sem,OS_OPT_POST_1,&err);/释放信号量 OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);/延时1s 信号量02任务互斥示例任务1函数/任务1的任务函数vo
19、id task1_task(void*p_arg)u8 key;OS_ERR err;while(1)key=KEY_Scan(0);/扫描按键if(key=KEY1_PRES)/如果按下开发板按键1printf(Task1:发送一个信号量rn);/输出发送信号量提示OSSemPost(&key_sem,OS_OPT_POST_1,&err);/发送信号量printf(当前信号值:%urn,key_sem.Ctr);OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err);/延时10ms 信号量02任务互斥示例任务2函数 void task2_task
20、(void*p_arg)OS_ERR err;char read_buf50=0;/用于存放临时数据 uint32_t cnt=1;/记录读取数据的次数 while(1)/没有获得信号量会挂起任务 OSSemPend(&share_mem_sem,0,OS_OPT_PEND_BLOCKING,0,&err);if(err!=OS_ERR_NONE)/在以下编写没有正确获得信号量但是函数返回时的处理代码 ./以下开始访问共享资源,把array_buf数组中的字符串复制到read_buf中 strcpy(read_buf,array_buf);/开始访问共享资源 /输出读取到的内容提示,写入次数增
21、加 printf(第%d次读取数据:%srn,cnt+,read_buf);OSSemPost(&share_mem_sem,OS_OPT_POST_1,&err);/释放信号量 OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_PERIODIC,&err);信号量02任务互斥示例0303互斥信号量互斥信号量介绍API函数接口任务互斥示例-优先级反转,是指某个共享资源被较低优先级的任务所持有,较高优先级的任务任务申请该共享资源无法获得,导致较高优先级任务反而被更低优先级的任务推迟被调度执行的现象。互斥信号量03互斥信号量介绍优先级反转概念C/OS-III支持一种特殊类型的
22、二值互斥信号量,称为互斥信号量(也称为互斥体),相对于前面学习过普通二值互斥信号量,它解决了优先级反转的问题。接下来的先来学习什么是什么级转换,才可以更好理解互斥信号量的作用。互斥信号量概念右图展示一个优先级反转的示例:系统中有高(TaskH),中(TaskM),低(TaskL)三个级别优先级任务,某一时刻低TaskL任务持有信号量S,此时TaskH就绪抢占TaskL,然后申请信号量S,但是此时信号量被 Task L 持有,因此Task H挂起,放弃CPU。然后Task L恢复运行,运行过程中TaskM就绪抢占TaskL,TaskM没有申请信号量S,因此它可以长时间持有CPU,这样就导致了Ta
23、skH反而被比它低的任务TaskM推迟调度,因为只有TaskM释放CPU,TaskL才可以继续运行,从而释放信号量,Task才有机会运行,这现象就是优先级反转。互斥信号量03互斥信号量介绍优先级反转示例互斥信号量的使用流程很简单:创建互斥信号量、申请互斥信号量、释放互斥信号量三个必需的步骤,其他可选操作有删除互斥信号量、中止等待互斥信号量。互斥信号量接口互斥信号量03API函数接口 互斥信号量函数互斥信号量函数序号函数名功能描述备注1OSMutexCreate()创建一个互斥信号量必须调用2OSMutexDel()删除一个互斥信号量必须调用3OSMutexPend()等待互斥信号量必须调用4O
24、SMutexPendAbort()中止对互斥信号量的等待 可选调用5OSMutexPost()释放互斥信号量可选调用C/OS-III系统使用OS_MUTEX结构来表示一个互斥信号量,要创建互斥信号量,我们只需要调用系统提供的OSMutexCreateAPI函数,根据需要传递必须参数即可创建互斥信号量互斥信号量03API函数接口函数原型:void OSMutexCreate(OS_MUTEX *p_mutex,CPU_CHAR *p_name,OS_ERR *p_err)函数功能:创建互斥信号量函数参数:p_mutex:指向要初始化的互斥信号量的指针,一般是传递OS_MUTEX类型的变量地址。p
25、_name:指向要分配给互斥信号量的名称的指针 p_err:指向存放错误代码变量的指针,函数调用可能产生的错误码如下:OS_ERR_NONE:指示互斥信号量创建成功;OS_ERR_CREATE_ISR:指示在中断服务程序中调用了此函数;OS_ERR_NAME:指令p_name是一个NULL指针;OS_ERR_OBJ_CREATED:指示p_mutex已经创建过了;OS_ERR_OBJ_PTR_NULL:指示p_mutex是一个NULL指针;示例代码函数示例:OS_MUTEXmy_mutex_test;/定义互斥信号量全局变量,用于共享资源保护。OSMutexCreate(OS_MUTEX*)&
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- CH04 03 操作系统 原理 实践 COS III 任务 通信
限制150内