OpenEdv-开源电子网

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

关于任哲嵌入式实时系统ucos-II原理及应用第4章例题4-2的疑问

[复制链接]

0

主题

4

帖子

0

精华

新手入门

积分
12
金钱
12
注册时间
2023-4-3
在线时间
7 小时
发表于 2023-4-3 14:17:11 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 xiaoyuba 于 2023-4-4 08:41 编辑

例题4-2  设计一个有3个任务的应用程序Test。这3个任务分别是MyTask,YouTask和InterTask。其中,任务InterTask是在时钟节拍中断服务程序中用钩子函数OSTimeTickHook()中断了1000次时使用一个信号量InterKey激活的。运行并分析由中断服务程序激活任务的工作特点。
/******************************Test*******************************/
#include "includes.h"
#define  TASK_STK_SIZE   512                                //任务堆栈长度
OS_STK   MyTaskStk[TASK_STK_SIZE];                        //定义任务堆栈区
OS_STK   YouTaskStk[TASK_STK_SIZE];                        //定义任务堆栈区
OS_STK   InterTaskStk[TASK_STK_SIZE];                        //定义任务堆栈区
INT16S   key;                                                //用于退出uCOS_II的键
INT8U         x=0,y=0;                                        //字符显示位置
BOOLEAN  InterKey=FALSE;
void  MyTask(void *data);                                //声明任务
void  YouTask(void *data);                                //声明任务
void  InterTask(void *data);                                //声明任务
/************************主函数*********************************/
void  main (void)
{
    char* s_M="M";                                        //定义要显示的字符
    OSInit( );                                                //初始化uCOS_II
    PC_DOSSaveReturn( );                                //保存Dos环境
    PC_VectSet(uCOS, OSCtxSw);                                //安装uCOS_II中断
    OSTaskCreate(
                MyTask,                                        //创建任务MyTask
                s_M,                                        //给任务传递参数
                &MyTaskStk[TASK_STK_SIZE - 1],                //设置任务堆栈栈顶指针
                0                                        //任务的优先级别为0
                );                                
    OSStart( );                                                //启动多任务管理
}

/*******************任务MyTask**********************************/

void  MyTask (void *pdata)
{
    char* s_Y="Y";                                        //定义要显示的字符
        char* s_H="H";
#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);                        //设置时钟频率
    OS_EXIT_CRITICAL( );
    OSStatInit( );                                        //初始化统计任务
    OSTaskCreate(
                YouTask,                                //创建任务YouTask
                s_Y,                                        //给任务传递参数
                &YouTaskStk[TASK_STK_SIZE - 1],                //设置任务堆栈栈顶指针
                1                                        // YouTask的优先级别为1
                );        
        OSTaskCreate(
                        InterTask,                        //创建任务InterTask
                        s_H,                                //给任务传递参数
                        &InterTaskStk[TASK_STK_SIZE - 1],//设置任务堆栈栈顶指针
                        2                                // InterTask的优先级别为2
                        );
    for (;;)
    {
        if (x>79)
                {
                           x=0;
                           y+=1;
        }                                                
        PC_DispChar(x, y,                                //字符的显示位置,X,Y为字符位置
                *(char*)pdata,
                DISP_BGND_BLACK+DISP_FGND_WHITE );
                       x += 1;   
                //如果按下Esc键则退出uCOS_II
                if (PC_GetKey(&key) == TRUE)
                {
                if (key == 0x1B)
                    {
                    PC_DOSReturn( );                        //恢复Dos环境
                }
            }
            OSTimeDlyHMSM(0, 0, 3, 0);                        //等待3秒
}
}

/************************任务YouTask******************************/

void  YouTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_sr;
    pdata = pdata;
    for (;;)
    {
        if (x>79)
        {
           x=0;
           y+=1;
        }                                                
        PC_DispChar(
                x, y,                                //字符的显示位置
                *(char*)pdata,
                DISP_BGND_BLACK+DISP_FGND_WHITE
                );
               x += 1;        
        OSTimeDlyHMSM(0, 0, 1, 0);                //等待1秒
    }
}
/***********************InterTask*******************************/
char*s="运行了中断所要求运行的任务InterTask。";
void  InterTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_sr;
#endif
    pdata = pdata;

    for (;;)
    {
        if(InterKey)
        {
                if (x>79)
                {
                           x=0;
                           y+=1;
                }                                                
                PC_DispChar(
                        x, y,                        //字符的显示位置
                        *(char*)pdata,
                        DISP_BGND_BLACK+DISP_FGND_WHITE
                        );
                PC_DispStr(5,6,s,DISP_BGND_BLACK+DISP_FGND_WHITE);        //字符串的显示位置
                       x += 1;
        }
        InterKey=FALSE;
        OSIntNesting--;
        OSTimeDlyHMSM(0, 0, 1, 0);                //等待1秒
    }
}
程序运行结果如下:

下载.png

不明白在InterTask任务中OSIntNesting--这句起什么作用?我把这句注释掉,程序结果也没有影响。现在我把开头定义程序改为:
INT16S   key;                                                //用于退出uCOS_II的键
INT8U  x=0,y=0;                                        //字符显示位置                                                                                                                                    
改为:

INT16S   key;                                                //用于退出uCOS_II的键
INT8U  x=0,y=0,x1=0,y1=5;                                        //字符显示位置                                      
char w[8];     

再把InterTask任务程序改为:
/***********************InterTask*******************************/
char*s="运行了中断所要求运行的任务InterTask。";
void  InterTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_sr;
#endif
    pdata = pdata;

    for (;;)
    {
        if(InterKey)
        {
                if (x>79)
                {
                           x=0;
                           y+=1;
                }                                                
                PC_DispChar(
                        x, y,                        //字符的显示位置
                        *(char*)pdata,
                        DISP_BGND_BLACK+DISP_FGND_WHITE
                        );
                PC_DispStr(5,6,s,DISP_BGND_BLACK+DISP_FGND_WHITE);
                       x += 1;
        }
         InterKey=FALSE;
         OSIntNesting--;
   sprintf(w,"%d",OSIntNesting);
     OSTimeDlyHMSM(0, 0, 1, 0);                //等待1秒
PC_DispStr(x1,y1,w,DISP_BGND_BLACK+DISP_FGND_WHITE);
x1+=3;
PC_DispChar(x1,y1,',',DISP_BGND_BLACK+DISP_FGND_WHITE);
x1++;
if(x1>79)
{
  y1+=1;
  x1=0;
}

    }
}

程序一开始运行结果如下:
1.png

1秒后再打印出0,如下:
2.png

然后我看Ucos-II源码中关于函数OSTimeDlyHMS的源代码,在文件os_time.c中,源代码如下:
#if OS_TIME_DLY_HMSM_EN > 0u
INT8U  OSTimeDlyHMSM (INT8U   hours,
                      INT8U   minutes,
                      INT8U   seconds,
                      INT16U  ms)
{
    INT32U ticks;
    if (OSIntNesting > 0u) {                     /* See if trying to call from an ISR                  */
        return (OS_ERR_TIME_DLY_ISR);
    }
    if (OSLockNesting > 0u) {                    /* See if called with scheduler locked                */
        return (OS_ERR_SCHED_LOCKED);
    }
#if OS_ARG_CHK_EN > 0u
    if (hours == 0u) {
        if (minutes == 0u) {
            if (seconds == 0u) {
                if (ms == 0u) {
                    return (OS_ERR_TIME_ZERO_DLY);
                }
            }
        }
    }
    if (minutes > 59u) {
        return (OS_ERR_TIME_INVALID_MINUTES);    /* Validate arguments to be within range              */
    }
    if (seconds > 59u) {
        return (OS_ERR_TIME_INVALID_SECONDS);
    }
    if (ms > 999u) {
        return (OS_ERR_TIME_INVALID_MS);
    }
#endif
                                                 /* Compute the total number of clock ticks required.. */
                                                 /* .. (rounded to the nearest tick)                   */
    ticks = ((INT32U)hours * 3600uL + (INT32U)minutes * 60uL + (INT32U)seconds) * OS_TICKS_PER_SEC
          + OS_TICKS_PER_SEC * ((INT32U)ms + 500uL / OS_TICKS_PER_SEC) / 1000uL;
    OSTimeDly(ticks);
    return (OS_ERR_NONE);
}
#endif

因为OSIntNesting--,OSIntNesting从0变成了255,OSTimeDlyHMS源码中判断OSLockNesting>0,OSTimeDlyHMS函数马上退出,不延时。所以255到1就一次性打印出来了,OSLockNesting变成0时,延时1秒才有效。但是我在CSDN上下载了任哲这本书的例程源码,它改了人家OSTimeDlyHMS的源码,把
if (OSIntNesting > 0u) {                     /* See if trying to call from an ISR                  */
        return (OS_ERR_TIME_DLY_ISR);
    }
    if (OSLockNesting > 0u) {                    /* See if called with scheduler locked                */
        return (OS_ERR_SCHED_LOCKED);

这2个判断都取消了,但是我运行起来效果还是一样的,这是为啥呢?我把下载的任哲书本例题源码以附件上传,烦请哪位高人给解答下?不胜感激。
任哲书本练习源码--经典-Windows下练习.rar (2.07 MB, 下载次数: 0)

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

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
12
金钱
12
注册时间
2023-4-3
在线时间
7 小时
 楼主| 发表于 2023-4-3 21:23:18 | 显示全部楼层
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
12
金钱
12
注册时间
2023-4-3
在线时间
7 小时
 楼主| 发表于 2023-4-6 10:01:55 | 显示全部楼层
江湖高手帮帮忙
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
12
金钱
12
注册时间
2023-4-3
在线时间
7 小时
 楼主| 发表于 2023-4-17 14:26:26 | 显示全部楼层
没有江湖高手来帮忙看看?
回复

使用道具 举报

20

主题

450

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4638
金钱
4638
注册时间
2017-7-6
在线时间
705 小时
发表于 2023-6-5 09:25:24 | 显示全部楼层
OS_TIME_DLY_HMSM_EN这个宏定义打开了???
我是小白,很白很白的小白!!!
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-22 12:00

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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