以下内容主要注重应用,对源码不做分析,对源码有兴趣的可参考官方具体文档,相关链接:https://doc.micrium.com/display/ucos/
编译环境:Atollic TrueSTUDIO for STM32 9.3.0
硬件:基于STM32F103VET6单片机(使用HAL库)
一、介绍
要启用coitoc /OS-II互斥服务,必须在OS_CFG.H中设置配置常量。当OS_MUTEX_EN设置为0时,禁止互斥服务;将OS_MUTEX_EN设置为1时,启动互斥服务。
任务使用互斥信号量或简单的互斥量来获得对资源的独占访问。互斥量是二进制信号量,它具有超出由μC /OS-II提供的普通信号量机制的额外特性。
应用程序代码使用互斥锁来减少优先级倒置问题,如实时系统概念中所述。当低优先级任务拥有高优先级任务所需的资源时,就会发生优先级反转。为了减少优先级反转,内核可以将低优先级任务的优先级增加到高优先级任务的优先级,直到低优先级任务用完资源。
下图显示了一个流程图来说明任务和互斥之间的关系。互斥锁只能被任务访问。注意,用来表示互斥锁的符号是一个“key”。“key”符号表示互斥锁是用来访问共享资源的。
二、创建一个互斥信号量,OSMutexCreate()
一个互斥信号量使用前需要被创建,通过调用OSMutexCreate()来创建互斥信号量。互斥信号量的初始值总是设置为1,表示资源可用。函数原型为:
1、OS_EVENT *OSMutexCreate (INT8U prio, INT8U *err)
- prio是指互斥信号量的优先级(即当一个任务获取该互斥信号量后,任务的优先级会临时变成该互斥信号量的优先级,因为互斥信号量的优先级和任务的优先级属于同一类,通常建议该互斥信号量的优先级高于所有任务优先级);
- err是存放错误类型;
- 返回与互斥信号量相关联的指向事件控制块的指针。
三、获取互斥信号量,OSMutexPend()
获取互斥信号量,函数原型为:
1、void
OSMutexPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)。
- pevent是互斥信号量相关联的指向事件控制块的指针;
- timeout等待时长(如果是0将一直等下去,直到有可用的互斥信号量);
- err保存错误类型。
四、释放互斥信号量,OSMutexPost()
释放获取的互斥信号量,函数原型为:
1、INT8U OSMutexPost (OS_EVENT *pevent)。
- pevent是互斥信号量相关联的指向事件控制块的指针;
- 返回值是错误类型。
五、使用注意事项
1、互斥信号量只能在任务中使用;
2、互斥信号量创建完成就有资源可用,与信号量创建需指定可用的资源数目不同;
3、互斥信号量的优先级和任务优先级属于同一类,在不支持同级任务优先级的操作系统中尤其要注意;
4、当一个任务获取到一个互斥信号量后会把优先级暂时变成互斥信号量的优先级,释放互斥信号量的时候恢复。
六、示例代码
1、启动互斥服务配置
#define OS_MUTEX_EN 1 /* Enable (1) or Disable (0) code generation for MUTEX */ #define OS_MUTEX_ACCEPT_EN 1 /* Include code for OSMutexAccept() */ #define OS_MUTEX_DEL_EN 1 /* Include code for OSMutexDel() */ #define OS_MUTEX_QUERY_EN 1 /* Include code for OSMutexQuery() */
2、定义一个互斥信号量事件指针:
/* 定义一个互斥信号量事件指针 */ OS_EVENT *MutexSemp;
3、创建互斥信号量,并设置互斥信号量的优先级
/* 创建互斥信号量,指定优先级为2 */ MutexSemp = OSMutexCreate(2, &err);
4、在两个任务中分别使用同一个互斥信号量:
static void AppTaskLed1(void *p_arg) { INT8U err; (void)p_arg; while(1) { /* 获取互斥信号量 */ OSMutexPend(MutexSemp, 0, &err); HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0); /* 释放互斥信号量 */ OSMutexPost(MutexSemp); OSTimeDlyHMSM(0, 0, 1, 0); } } static void AppTaskLed2(void *p_arg) { INT8U err; (void)p_arg; while(1) { /* 获取互斥信号量 */ OSMutexPend(MutexSemp, 0, &err); HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5); /* 释放互斥信号量 */ OSMutexPost(MutexSemp); OSTimeDlyHMSM(0, 0, 2, 0); } }
#endif