【iCore4 双核心板_uC/OS-II】例程七:互斥信号量
一、实验说明:
在介绍互斥信号量前,我们先简单地描述一下什么是优先级反转。使用实时内核心,优先级反转问题是实时系统中出现得最多的问题。假设任务H优先级高于任务M,任务M优先级高于任务L。任务H和任务M处于挂起状态,等待某一事件发生,任务L正在运行。此时,任务L要使用共享资源。使用共享资源之前,首先必须得到该资源的信号量。任务L得到了该信号量,并开始使用该共享资源。由于任务H的优先级高,它等待的事件到来之后剥夺了任务L的CPU使用权,任务L被挂起,任务H开始运行。运行过程中任务H也要使用那个任务L正在使用着的资源,由于该资源的信号量还被任务L占用着,任务H只能进入挂起状态,等待任务L释放该信号量。任务L得以继续运行。由于任务M的优先级高于任务L,当任务M等待的事件发生后,任务M剥夺了任务L的CPU使用权并开始运行。处理它该处理的事件,直到处理完之后将CPU控制权还给任务L。任务L接着运行,直到释放那个共享资源的信号量。直到此时,由于实时内核知道有个高优先级的任务(任务H)在等待这个信号量,内核做任务切换,使任务H得到该信号量并接着运行。
在这种情况下,任务H优先级实际上降到了任务L的优先级水平。因为任务H要等,一直等到任务L释放占有的那个共享资源。由于任务M剥夺了任务L的CPU使用权,使任务H的状况更加恶化,任务M使任务H增加了额外的延迟时间。任务H和任务M的优先级发生了反转。
任务优先级反转是不允许出现的,因为它可能会造成不可预期的严重后果,因此uC/OS-II提供了一种特殊的二值信号量——互斥信号量,它能够顺利地解决这种现象。

(1)任务H和任务M正在等待一个事件发生,处于挂起状态,任务L正在执行。
(2)在某一时刻,任务L请求一个互斥信号量以能够访问一个共享资源。
(3)任务L请求到共享资源的互斥信号量,开始访问该共享资源。
(4)任务H等待的事件发生,由于任务H的优先级高于任务L的优先级,内核挂起了任务L开始执行任务H。
(5)任务H开始执行。
(6)任务H也想访问L现在正在访问着的共享资源(它想从任务L得到互斥信号量),为了尽快地让任务H请求到互斥信号量,并且在L访问共享资源过程中不再被其他中等优先级任务打断,uC/OS-II将任务L的优先级提升到任务H同等高度。
(7)任务L继续访问共享资源,然而它现在是以任务H的优先级进行的,注意任务H还没有运行,因为它正在等待任务L释放互斥信号量,换句话说,任务H在该互斥信号量的等待列表中。
(8)任务L完成共享资源的使用,释放掉互斥信号量 。uC/OS-II发现任务L的优先级被提高,因此将任务L的优先级降低到原来的高度。然后,uC/OS-II将释放的互斥信号量分配给正在等待的任务H。
(9)任务H获得互斥信号量,开始访问共享资源。
(10)任务H完成共享资源的使用,释放掉互斥信号量。
(11)没有更高优先级的任务执行,因此任务H继续执行。
(12)任务H完成,开始等待一个事件。这时uC/OS-II恢复当任务H或者任务L正在执行时处于就绪态的任务M。
(13)任务M执行。
二、实验截图:

三、源代码下载链接:
链接:https://pan.baidu.com/s/1qZavQpA 密码:o8p5
四、核心代码
/*
* Name : main
* Description : ---
* Author : liu.
*
* History
* --------------------
* Rev : 0.00
* Date : 07/12/2017
*
* create.
* --------------------
*/
/*实验现象:
打开串口工具putty.exe,终端显示此时任务AppTask1_task,AppTask2_task和AppTask3_task
的运行状态,任务AppTask1_task请求到互斥信号量红色ARM.LED点亮,任务AppTask2_task运
行过程中蓝色ARM.LED闪烁。
备注:当任务AppTask1_task请求互斥态进入就绪态时,之后本应该执行的任务AppTask2_task
(蓝色ARM.LED闪烁),由于任务AppTask3_task的优先级被提高(高于任务AppTask2_task),
所以任务AppTask2_task就进入了就绪态(蓝色ARM.LED停止闪烁),等待任务AppTask3_task
释放出信号量后继续执行。
*/
int main(void)
{
system_clock.initialize(); //系统时钟初始化
led.initialize(); //LED初始化
usart6.initialize(); //串口初始化
key.initialize(); OSInit(); //UCOS初始化
OSTaskCreate(start_task, //创建开始任务
(void*), //任务参数
(OS_STK*)&START_TASK_STK[START_STK_SIZE-], //任务堆栈
START_TASK_PRIO); //任务优先级
OSStart(); //开启UCOS
}
/*
* Name : start_task
* Description : ---
* Author : liu.
*
* History
* --------------------
* Rev : 0.00
* Date : 07/12/2017
*
* create.
* --------------------
*/
void start_task(void *pdata)
{
INT8U err;
OS_CPU_SR cpu_sr; TaskMutex = OSMutexCreate(, &err);//创建互斥信号量 OSStatInit();//初始化统计任务 OS_ENTER_CRITICAL();//关中断 OSTaskCreate(AppTask1_task,(void*),(OS_STK*)&AppTask1_TASK_STK[AppTask1_STK_SIZE-],AppTask1_TASK_PRIO);//创建AppTask1任务
OSTaskCreate(AppTask2_task,(void*),(OS_STK*)&AppTask2_TASK_STK[AppTask2_STK_SIZE-],AppTask2_TASK_PRIO);//创建AppTask2任务
OSTaskCreate(AppTask3_task,(void*),(OS_STK*)&AppTask3_TASK_STK[AppTask3_STK_SIZE-],AppTask3_TASK_PRIO);//创建AppTask3任务
OSTaskSuspend(OS_PRIO_SELF);//挂起start_task任务 OS_EXIT_CRITICAL();//开中断
}
/*
* Name : AppTask1_task
* Description : ---
* Author : liu.
*
* History
* --------------------
* Rev : 0.00
* Date : 07/12/2017
*
* create.
* --------------------
*/
void AppTask1_task(void *pdata)
{
u8 err; while(){
usart6.printf("\x0c"); //清屏
usart6.printf("\033[1;32;40m"); //设置字体终端为绿色
usart6.printf("\r\n The Task1 is running!\r");
OSTimeDlyHMSM(,,,); //延时1s
usart6.printf("\r\n The Task1 is pending Mutex!\r"); /*等待一个互斥信号量*/
OSMutexPend(TaskMutex, , &err);
usart6.printf("\r\n The Task1 has got Mutex!\r");
LED_RED_ON;
/*释放一个互斥信号量*/
OSMutexPost(TaskMutex);
OSTimeDlyHMSM(,,,); //延时1s
LED_RED_OFF;
}
}
/*
* Name : AppTask2_task
* Description : ---
* Author : liu.
*
* History
* --------------------
* Rev : 0.00
* Date : 07/12/2017
*
* create.
* --------------------
*/
void AppTask2_task(void *pdata)
{
while(){
usart6.printf("\r\n The Task2 is running!\r");
LED_BLUE_ON;
OSTimeDlyHMSM(,,,); //延时200ms
LED_BLUE_OFF;
OSTimeDlyHMSM(,,,); //延时200ms
}
}
/*
* Name : AppTask3_task
* Description : ---
* Author : liu.
*
* History
* --------------------
* Rev : 0.00
* Date : 07/12/2017
*
* create.
* --------------------
*/
void AppTask3_task(void *pdata)
{
int i;
u8 err; while(){
/*等待一个互斥信号量*/
OSMutexPend(TaskMutex, , &err);
usart6.printf("\r\n The Task3 is running!\r");
for(i = ; i< ; i ++){
OS_Sched();
}
/*释放一个互斥信号量*/
OSMutexPost(TaskMutex);
OSTimeDlyHMSM(,,,); //延时1s
}
}
iCore4链接:

【iCore4 双核心板_uC/OS-II】例程七:互斥信号量的更多相关文章
- 【iCore4 双核心板_uC/OS-II】例程十:信号量集
一.实验说明: 在实际应用中,任务常常需要与多个事件同步,即要根据多个信号量组合作用的结果来决定任务的运行方式.UCOSII为了实现多个信号量组合的功能定义了一种特殊的数据结构——信号量集. 二.实验 ...
- 【iCore4 双核心板_uC/OS-II】例程六:信号量——任务同步
一.实验说明: 信号量是一个多任务内核提出的一个协议机构,上一个实验中我们介绍了信号量访问共享资源 的功能,其实信号量最初是用来控制访问共享资源的,它还可以用来同步一个中断服务函数和一个任 务,或者同 ...
- 【iCore4 双核心板_uC/OS-II】例程五:信号量——共享资源
一.实验说明: 信号量是操作系统中的一类事件,是实现任务间通信的一个中间环节.当系统中的多个任务 在运行时,经常需要互相无冲突地访问同一个资源,或者需要互相支持的依赖,甚至有时还要互 相加以必要的限制 ...
- 【iCore4 双核心板_uC/OS-II】例程四:软件定时器
一.实验说明: 一些应用程序执行它们的任务时需要延迟一段特定的时间,因此uC/OS-II为我们提供了一些相应的 延时函数,本例程我们使用软件定时器定时500ms点亮相应的LED实现三色LED循环闪烁. ...
- 【iCore4 双核心板_uC/OS-II】例程二:任务的建立与删除
一.实验说明: 本例程建立三个任务,通过任务寄存器来实现任务的建立与删除功能.红灯和绿灯同时以固定 频率闪烁,当任务寄存器为5时,删除绿灯闪烁的任务LED1,此时只有红灯闪烁,当任务寄存器的 值为10 ...
- 【iCore4 双核心板_uC/OS-II】例程十一:内存管理
一.实验说明: 应用程序在运行中为了某种特殊需要,经常需要临时获得一些内存空间.而作为比较完善的操作系统uC/OS-II,也具有动态分配内存的能力. uC/OS-II对内存进行两级管理:把连续内存分成 ...
- 【iCore4 双核心板_uC/OS-II】例程九:消息队列
一.实验说明: 前面介绍通过信息传递可以进行任务间的交流,信息也可以直接发送给一个任务,在uC/OS-II中每一个任务在它们内部都有一个消息队列,也即任务消息队列,用户可以直接给一个任务发送消息,不需 ...
- 【iCore4 双核心板_uC/OS-II】例程八:消息邮箱
一.实验说明: 消息邮箱是uC/OS-II中的另一种通信机制,可以使一个任务或者中断服务子程序向另一个任务发送一个指针型的变量.通常该指针指向一个包含了“消息”的特定数据结构. 二.实验截图: ...
- 【iCore4 双核心板_uC/OS-II】例程三:任务的挂起与恢复
一.实验说明: 当一个任务正在运行的时候,由于某种情况可能需要终止运行一段时间,终止的这段时间就是 所谓的任务的挂起,可以由该任务自身或者其他任务来挂起一个任务.当被挂起的任务需要再次运 行的时候,可 ...
随机推荐
- Your ApplicationContext is unlikely to start due to a @ComponentScan of the default
问题:** WARNING ** : Your ApplicationContext is unlikely to start due to a @ComponentScan of the defau ...
- Java并发程序设计(二)Java并行程序基础
Java并行程序基础 一.线程的生命周期 其中blocked和waiting的区别: 作者:赵老师链接:https://www.zhihu.com/question/27654579/answer/1 ...
- error LNK2001: unresolved external symbol _main
想运行一个网上下载的opengl离屏渲染(渲染到纹理FBO)的程序,然后一直报错 error LNK2001: unresolved external symbol _main 解决了一下午终于弄明白 ...
- Codeforces Round #443 (Div. 1) A. Short Program
A. Short Program link http://codeforces.com/contest/878/problem/A describe Petya learned a new progr ...
- GMA Round 1 极坐标的忧伤
传送门 极坐标的忧伤 为什么你们不喜欢为我求导……——极坐标 极坐标的心意,想必已经传达到了,那么请为极坐标方程$r=t$(也写作$ρ=θ$)求导吧. 为了考验你的忠诚,你需要回答$r=t$在(0,$ ...
- python函数之协程与面向过程编程
第一:协程 初步了解协程 def eater(): print('start to eat') while True: food=yield print('is eating food:%s'%foo ...
- flask之SQLAlchemy
本篇导航: 介绍 使用 SQLAlchemy-Utils 一. 介绍 SQLAlchemy是一个基于Python实现的ORM框架.该框架建立在 DB API之上,使用关系对象映射进行数据库操作,简言之 ...
- JS 正则表达式从地址中提取省市县
var add1 = '四川省西昌市航天路'; var add2 = '北京市北京市东城区前门大街1号' var add3 = '新疆维吾尔自治区乌鲁木齐市天山区中山路479号'; var add4 ...
- 配置gitlab通过smtp发送邮件
1. 编辑/etc/gitlab/gitlab.rb文件(加到文件最后面就好了,或者通过搜索找到,新版已有这些配置,只不过都是被注释掉了).以QQ企业邮箱为例: gitlab_rails['smtp_ ...
- Spring Aop 修改目标方法参数和返回值
一.新建注解 @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Document ...