ucos-ii 学习笔记——信号量的原理及使用
Created on: 2012-10-7
Author: zhang bin
学习笔记
for ucos-ii PC
redesigned by zhang bin
2012-10-7
versions:V-0.1
All Rights Reserved
/*编写一个应用程序,其中有一个函数Fun()和两个用户任务:MyTask和YouTask。
应用程序中的两个任务都可以
调用此函数,但不能同时调用*/
#include "INCLUDES.h"
#define TASK_STK_SIZE
512
/* 任务堆栈长度*/
//定义一个错误信息
ac_key;
char *s1="MyTask";
char *s2="YouTask";
INT8U err;
INT8U y=0;
OS_EVENT *Fun_Semp;
//注意,前面有一个例子2 定义了互斥信号量,定义如下
//BOOLEAN
个全局变量,来标志共享资源的访问情况
//这样,当已经有任务访问共享资源时,其他的任务就不能访问,知道该资源未
被访问,其他的任务才可以进行访问
//注意这两个信号量的区别和使用情况
//信号量,互斥信号量 实质上就是一个标志位,是一
//声明信号量 是事件控制块ECB类型的
OS_STK
OS_STK
OS_STK
StartTaskStk[TASK_STK_SIZE];
MyTaskStk[TASK_STK_SIZE];
YouTaskStk[TASK_STK_SIZE];
//定义任务堆栈区
void Fun(INT8U x,INT8U y);
void StartTask(void *data);
void MyTask(void *data);
/* 声明任务
*/
void YouTask(void *data);
/*
*********************************************************************
************************************
*
*********************************************************************
************************************
*/
void main (void)
{
MAIN主函数
Fun_Semp=OSSemCreate(1); //在主函数中创建信号量 返回值为创建的信号
量指针,参数是信号量的计数器的值
//用该参数对信号量计数器OSEventCnt进行初始化
//1即代表只创建一个信号量,代表信号量用于对共享资源的访问(例如,把
它当做二值信号量使用),详见P166
OSInit();
uC/OS-II */
PC_DOSSaveReturn();
DOS环境
*/
PC_VectSet(uCOS, OSCtxSw);
uC/OS-II的中断 */
/* 初始化
/* 保存
/* 安装
OSTaskCreate(StartTask,(void *)0, &StartTaskStk[TASK_STK_SIZE - 1], 0); //
创建起始函数
OSStart();
/* 启动多任务管理 */
}
void StartTask(void *pdata)
{
#if OS_CRITICAL_METHOD == 3
register */
OS_CPU_SR cpu_sr;
#endif
key;
INT16S
pdata = pdata;
OS_ENTER_CRITICAL();
PC_VectSet(0x08, OSTickISR);
PC_SetTickRate(OS_TICKS_PER_SEC);
中断向量 */
钟频率 */
OS_EXIT_CRITICAL();
/* Allocate storage for CPU status
/*用于退出的建*/
/* Prevent compiler warning
*/
/* 安装时钟
/* 设置时
OSStatInit();
任务 */
/* 初始化统计
OSTaskCreate(MyTask,(void *)0, &MyTaskStk[TASK_STK_SIZE - 1], 1); //创
建任务函数
OSTaskCreate(YouTask,(void *)0, &YouTaskStk[TASK_STK_SIZE - 1], 2); //创
建任务函数
/* See if key has been pressed
/* Yes, see if it's the ESCAPE key
/* Return to
/* 等待3S*/
/* Allocate storage for CPU status
for (;;)
{
//如果恩下ESC键,则退出UC/OS-II
if (PC_GetKey(&key) == TRUE)
{
if (key == 0x1B)
{
PC_DOSReturn();
*/
}
}
OSTimeDlyHMSM(0,0,3,0);
*/
*/
DOS
}
}
//MyTask的函数代码
void MyTask(void *pdata)
{
#if OS_CRITICAL_METHOD == 3
register */
OS_CPU_SR cpu_sr;
#endif
pdata = pdata;
for (;;)
{
//err表示错误信息
/* Prevent compiler warning */
OSSemPend(Fun_Semp,0,&err);
//请求信号量 参数Fun_Semp是信号
量指针 0那一项是等待时限timeout,0表示无限等待
PC_DispStr(0,++y,s1,DISP_BGND_BLACK+DISP_FGND_WHITE);
示MyTask字符串
//显
Fun(7,y);
//调用Fun函数
OSSemPost(Fun_Semp);
Fun_Semp代表信号量的指针
// 发送信号量 释放信号量,函数的参数
OSTimeDlyHMSM(0,0,1,0);
/* 等待1S*/
}
}
void YouTask(void *pdata)
{
#if OS_CRITICAL_METHOD == 3
register
OS_CPU_SR cpu_sr;
#endif
//Allocate storage for CPU status
pdata=pdata;
for (;;)
{
//请求信号量
OSSemPend(Fun_Semp,0,&err);
PC_DispStr(0,++y,s2,DISP_BGND_BLACK+DISP_FGND_WHITE);
Fun(7,y);
OSSemPost(Fun_Semp);
//调用FUN函数
//释放信号量
OSTimeDlyHMSM(0,0,2,0);
//等待2s
}
}
//公共的函数Fun的代码
void Fun(INT8U x,INT8U y)
{
PC_DispStr(x,y,"
Calling
FUN()",DISP_BGND_BLACK+DISP_FGND_WHITE); //显示字符串,表示调用了
Fun函数
}
//创建信号量时,用的参数为1,即Fun_Semp=OSSemCreate(1); ,只创建了一个
信号量,这种情况一般是信号量用于对
//共享资源的访问(例如,可以把它当做二值信号量使用)
/* 请 求 信 号 量 函 数 OSSemPend(Fun_Semp,0,&err);
Fun_Semp是信号量指针 0那一项是等待时限timeout,
0表示无限等待,err表示错误信息。
原理是每当有任务申请信号量时,
(下面是由申请信号量的函数OSSemPend完成)如果信号量计数器OSEventCnt的
值大于0(即表
// 请 求 信 号 量 参 数
示还有空闲的信号量可以使用),则把
OSEventCnt减1,并使该任务继续运行,表示该任务成功申请到了一个信号量,
空闲的信号量少了一个。
如果信号量计数器OSEventCnt的值等于0,表示没有空闲的信号量可用了,那么
就将该申请的任务列入到任务等待列表OSEventTbl[]
中,而使任务处于等待状态。
(下面的功能由释放信号量的函数OSSemPost完成)如果有正在使用信号量的任
务释放了信号量,则就会在任务等待表中找出优先级最高
的等待任务,并在使它就绪后调用调度器引发一次调度。如果在任务等待列表
中已经没有等待任务了,则信号量计数器就只简单
地加1*/
//在上面的程序中,当MyTask运行时,先请求获得了信号量,对共享资源Fun函
数进行访问,由于只创建了一个信号量,
// 所 以 在MyTask 的 访 问 期 间 , 即 使 任 务YouTask 也 进 行 申 请 信 号 量 , 此 时
OSEventCnt是值已经为0了,所以会把任务
//YouTask列入任务等代表OSEventTbl[]中,使任务处于等待状态。
//只有等MyTask对Fun函数访问完成了,调用OSSemPost(Fun_Semp);释放了信号
量,该释放信号量的函数会先检查任务等待
//表中是否还有等待信号量的任务,如果有,则使任务进入就绪态后,调用调度
器OS_Sched()引发一次任务调度,去运行等待
//任务列表中优先级最高的任务。如果没有,则就把信号量计数器OSSemCnt加1.
//所以任务YouTask要想访问Fun()函数,必须等到任务MyTask对Fun访问完毕,释
放了信号量之后,才能访问,反之亦然
//所以由上面可以看出,只创建一个信号量,即OSSemCreate(1);,作用就相当于
使用一个二值信号量,标志共享资源是否正在
//被访问
//看懂了上面的分析,也就可以解释实验现象了,由于YouTask等待2s,MyTask
等待1s,所以有可能在MyTask访问Fan函数期间,YouTask
//也来访问(也有可能是反过来),但是由于信号量已经被MyTask占用了,所
YouTask只好等待,MyTask使用完了,释放了信号量,YouTask才能正常使用Fun
函数
//这样也就解决了多任务对共享资源的使用的问题,使任务之间得到了同步
//要仔细分析信号量工作的原理,把上面的内容看懂了,基本上也就可以使用信
号量了