OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4268|回复: 0

请教 《嵌入式实时操作系统分uCOS-II原理及应用 第二版》任哲 里面的一个例子

[复制链接]

9

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2013-6-3
在线时间
0 小时
发表于 2013-6-4 17:33:38 | 显示全部楼层 |阅读模式
本书的P146 例5-6
使用一个信号量实现独占式访问资源而出现了任务优先级反转的应用实例:


/************************Test*************************************/
#include "includes.h"
#define  TASK_STK_SIZE   512 //任务堆栈长度
OS_STK   StartTaskStk[TASK_STK_SIZE]; //定义任务堆栈区
OS_STK   MyTaskStk[TASK_STK_SIZE]; //定义任务堆栈区
OS_STK   YouTaskStk[TASK_STK_SIZE]; //定义任务堆栈区
OS_STK   HerTaskStk[TASK_STK_SIZE]; //定义任务堆栈区
INT16S   key; //用于退出的键
char*s1="MyTask正在运行";
char*s2="YouTask正在运行";
char*s3="HerTask正在运行";
char*ss="MyTask请求信号量";
INT8U err;  
INT8U y=0; //字符显示位置 
INT32U Times=0;
OS_EVENT *Semp; //定义事件控制块
void  StartTask(void *data); //声明起始任务
void  MyTask(void *data); //声明任务
void  YouTask(void *data); //声明任务
void  HerTask(void *data); //声明任务
/************************主函数*********************************/
void  main (void)
{
    OSInit( ); //初始化uCOS_II
    PC_DOSSaveReturn( ); //保存Dos环境
    PC_VectSet(uCOS, OSCtxSw); //安装uCOS_II中断
    Semp = OSSemCreate (1); //定义信号量
    OSTaskCreate(StartTask, //创建任务StartTask
(void*)0, //给任务传递参数
&StartTaskStk[TASK_STK_SIZE - 1], //设置任务堆栈栈顶
0); //使任务的优先级别为0
    OSStart( ); //启动多任务管理
}
/***********************任务StartTask*******************************/
void  StartTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_sr;
#endif
    pdata = pdata; 
    OS_ENTER_CRITICAL( );
    PC_VectSet(0x08, OSTickISR); //安装时钟中断向量
    PC_SetTickRate(OS_TICKS_PER_SEC); //设置uCOS_II时钟频率
    OS_EXIT_CRITICAL( );

    OSStatInit( ); //初始化统计任务
    OSTaskCreate(MyTask, //创建任务MyTask
(void*)0, //给任务传递参数
&MyTaskStk[TASK_STK_SIZE - 1], //设置任务堆栈栈顶
3); //使任务的优先级别为3
    OSTaskCreate(YouTask, //创建任务YouTask
(void*)0, //给任务传递参数
&YouTaskStk[TASK_STK_SIZE - 1], //设置任务堆栈栈顶
4); //使任务的优先级别为4
    OSTaskCreate(HerTask, //创建任务HerTask
(void*)0, //给任务传递参数
&HerTaskStk[TASK_STK_SIZE - 1], //设置任务堆栈栈顶
5); //使任务的优先级别为5
    for (;;) 
    {
//如果按下Esc键则退出uCOS_II
if (PC_GetKey(&key) == TRUE) 
{
            if (key == 0x1B) 
    {
                PC_DOSReturn( );
            }
        }
        OSTimeDlyHMSM(0, 0, 3, 0); //等待3秒
    }
}
/************************任务MyTask*******************************/
void  MyTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_sr;
#endif
    pdata = pdata;
  
    for (;;) 
    {  
        OSTimeDlyHMSM(0, 0, 1, 200); //等待200毫秒                                          
        {
   C_DispStr(10,++y,
ss,
DISP_BGND_BLACK+DISP_FGND_WHITE );
            OSSemPend(Semp,0,&err); //请求信号量
   C_DispStr(10,++y,
s1,
DISP_BGND_BLACK+DISP_FGND_WHITE );
 
   OSSemPost(Semp); //发送信号量
        }
        OSTimeDlyHMSM(0, 0, 0, 200); //等待200毫秒
    }
}
/************************任务YouTask******************************/
void  YouTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_sr;
#endif
    pdata = pdata;     
     
    for (;;) 
    {                                           
        PC_DispStr(10,++y,
s2,
DISP_BGND_BLACK+DISP_FGND_WHITE );          
        OSTimeDlyHMSM(0, 0, 0, 300); //等待300毫秒
    }
}
/************************任务HerTask******************************/
void  HerTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_sr;
#endif
    pdata = pdata;   

    for (;;) 
    {                                          
        OSSemPend(Semp,0,&err); //请求信号量        
PC_DispStr(10,++y,
s3,
DISP_BGND_BLACK+DISP_FGND_WHITE );

        for(Times;Times<20000000;Times++)
{
OS_Sched();
}
        
OSSemPost(Semp); //发送信号量          
        OSTimeDlyHMSM(0, 0, 1, 0); //等待1秒
    }
}
/************************End**************************************/

运行结果为:
            YouTask running
            HerTask  running
            YouTask running 
            YouTask running 
            YouTask running 
            MyTask  pend_Semp
            YouTask running  
            YouTask running  
            YouTask running  
            YouTask running  
            YouTask running  
            YouTask running  
            MyTask  running
。。。。。。

我是这么理解的程序执行后,StartTask一直在 OSTimeDlyHMSM(0, 0, 3, 0); ,MyTask先执行 OSTimeDlyHMSM(0, 0, 1, 200);  后YouTask执行,输出            

YouTask running 后 OSTimeDlyHMSM(0, 0, 0, 300);    HerTask执行,输出 HerTask  running 后进入Times的for循环,不停的调用 OS_Sched(); 切换任务,
因为MyTask延时200ms    YouTask延时的300ms 那么肯定是MyTask先到时间获得CPU使用权,继续执行,输出 MyTask  pend_Semp 然后才在OSSemPend(Semp,0,&err); 
里面,YouTask才获得CPU试用权输出 YouTask running 直到HerTask执行 OSSemPost(Semp) ...
我感觉结果应该是:
            YouTask running
            HerTask  running
            MyTask  pend_Semp 
            YouTask running 
            YouTask running 
            YouTask running 
            YouTask running  
            YouTask running  
            YouTask running  
            YouTask running  
            YouTask running  
            YouTask running  
            MyTask  running 

请教大家 我什么地方理解错了,谢谢指点了....









        

            

    




正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 23:01

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表