UCOSII系统时间管理[通俗易懂]

UCOSII系统时间管理[通俗易懂]一,UCOSII的定时中断绝大多数的内核要求提供定时中断,以实现延时与超时控制等功能。这个定时中断叫做时钟节拍。时钟的中断子程序ISR和时钟节拍函数OSTimeTick()该函数通知UCOSII,发生了时钟节拍中断。二,UCOSII系统时钟函数1,任务延时函数,OSTimeDly(INT16Uticks)实现申请该服务的任务可以延时一段时间这个系统服务的函数叫做OSTimeDly(),这段时间的长短是用时钟节拍的数目来确定的。调用该函数会使µC/OS-Ⅱ进行一次任务调度,并且执行下一个优

大家好,又见面了,我是你们的朋友全栈君。

一,UCOSII的定时中断

绝大多数的内核要求提供定时中断,以实现延时与超时控制等功能。这个定时中断叫做时钟节拍。时钟的中断子程序ISR和时钟节拍函数OSTimeTick()该函数通知UCOSII,发生了时钟节拍中断。

二,UCOSII系统时钟函数

1,任务延时函数, OSTimeDly(INT16U ticks)
实现申请该服务的任务可以延时一段时间这个系统服务的函数叫做 OSTimeDly(),这段时间的长短是用时钟节拍的数目来确定的。调用该函数会使µC/OS-Ⅱ进行一次任务调度,并且执行下一个优先级最高的就绪态任务。

void  OSTimeDly (INT32U ticks)
{
    INT8U      y;
#if OS_CRITICAL_METHOD == 3u  /* Allocate storage for CPU status register  */
    OS_CPU_SR  cpu_sr = 0u;
#endif
 
    if (OSIntNesting > 0u) 
    {                     /* See if trying to call from an ISR */
        return;
    }
    if (OSLockNesting > 0u) 
    {                    /* See if called with scheduler locked*/
        return;
    }
    if (ticks > 0u) 
    {              /* 0 means no delay!  */
        OS_ENTER_CRITICAL();
        y  =  OSTCBCur->OSTCBY; /* Delay current task  */
        OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX;
        if (OSRdyTbl[y] == 0u) 
        {
            OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;
        }
        OSTCBCur->OSTCBDly = ticks;  /* Load ticks in TCB */
        OS_EXIT_CRITICAL();
        OS_Sched();    /* Find next task to run! */
    }
}

(1)任务调用 OSTimeDly()后,一旦规定的时间期满或者有其它的任务通过调用 OSTimeDlyResume()取消了延时,它就会马上进入就绪状态。

(2)参数分析:ticks:代表的是多少个时钟周期节拍

(3)实现过程:
把相应任务的就绪表中的位图的位置清零。把需要执行的等待节拍进行处理。
最后进行任务调度,寻找下一个这个时刻最高优先级的任务。

(4)在OS_TCB的结构体当中的Ticks填写相应的数字的时候通过OSTimeTick()函数可以把任务从就绪态变为等待的状态

void  OSTimeTick (void)
{
    OS_TCB    *ptcb;
 
    if (OSRunning == OS_TRUE) {
#if OS_TICK_STEP_EN > 0u
        switch (OSTickStepState) {                         /* Determine whether we need to process a tick  */
            case OS_TICK_STEP_DIS:                         /* Yes, stepping is disabled                    */
                 step = OS_TRUE;
                 break;
 
            case OS_TICK_STEP_WAIT:                        /* No,  waiting for uC/OS-View to set ...       */
                 step = OS_FALSE;                          /*      .. OSTickStepState to OS_TICK_STEP_ONCE */
                 break;
 
            case OS_TICK_STEP_ONCE:                        /* Yes, process tick once and wait for next ... */
                 step            = OS_TRUE;                /*      ... step command from uC/OS-View        */
                 OSTickStepState = OS_TICK_STEP_WAIT;
                 break;
 
            default:                                       /* Invalid case, correct situation              */
                 step            = OS_TRUE;
                 OSTickStepState = OS_TICK_STEP_DIS;
                 break;
        }
        if (step == OS_FALSE) {                            /* Return if waiting for step command           */
            return;
        }
#endif
 
//此处为此任务运行的核心的代码:
 
        ptcb = OSTCBList;                                  /* Point at first TCB in TCB list               */
        while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) {     /* Go through all TCBs in TCB list              */
            OS_ENTER_CRITICAL();
            if (ptcb->OSTCBDly != 0u) {                    /* No, Delayed or waiting for event with TO     */
                ptcb->OSTCBDly--;                          /* Decrement nbr of ticks to end of delay       */
                if (ptcb->OSTCBDly == 0u) {                /* Check for timeout                            */
 
                    if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
                        ptcb->OSTCBStat  &= (INT8U)~(INT8U)OS_STAT_PEND_ANY;          /* Yes, Clear status flag   */
                        ptcb->OSTCBStatPend = OS_STAT_PEND_TO;                 /* Indicate PEND timeout    */
                    } else {
                        ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
                    }
 
                    if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {  /* Is task suspended?       */
                        OSRdyGrp               |= ptcb->OSTCBBitY;             /* No,  Make ready          */
                        OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
                    }
                }
            }
            ptcb = ptcb->OSTCBNext;                        /* Point at next TCB in TCB list                */
            OS_EXIT_CRITICAL();
        }
    }
}

2,按时分秒延时函数 OSTimeDlyHMSM( INT8U hours, INT8U minutes, INT8U seconds, INT16U milli):

调用 OSTimeDlyHMSM()函数也会使µC/OS-Ⅱ进行一次任务调度,并且执行下一个优先级最高的就绪态任务。任务调用 OSTimeDlyHMSM()后,一旦规定的时间期满或者有其它的任务通过调用 OSTimeDlyResume()取消了延时,它就会马上处于就绪态。只有当该任务在所有就绪态任务中具有最高的优先级时,它才会立即运行。若将时钟频率(OS_TICKS_PER_SEC)设置成 100Hz(10ms),4ms 的延时不会产生任何延时!而 5ms 的延时就等于延时 10ms。µC/OS-Ⅱ支持的延时最长为 65,535 个节拍。要想支持更长时间的延时,OSTimeDlyHMSM()确定了用户想延时多少次超过 65,535 个节拍的数目和剩下的节拍数,超过的节拍数会被分为几次去延时。由于OSTimeDlyHMSM()的具体实现方法,用户不能结束延时调用 OSTimeDlyHMSM()要求延时超过 65535 个节拍的任务。

3,恢复延时的任务:OSTimeDlyResume():把那个全局的时间计数器变量设置为0

INT8U  OSTimeDlyResume (INT8U prio)
{
    OS_TCB    *ptcb;
 
    if (prio >= OS_LOWEST_PRIO) {
        return (OS_ERR_PRIO_INVALID);
    }
    OS_ENTER_CRITICAL();
    ptcb = OSTCBPrioTbl[prio];                                 /* Make sure that task exist            */
    if (ptcb == (OS_TCB *)0) {
        OS_EXIT_CRITICAL();
        return (OS_ERR_TASK_NOT_EXIST);                        /* The task does not exist              */
    }
    if (ptcb == OS_TCB_RESERVED) {
        OS_EXIT_CRITICAL();
        return (OS_ERR_TASK_NOT_EXIST);                        /* The task does not exist              */
    }
    if (ptcb->OSTCBDly == 0u) {                                /* See if task is delayed               */
        OS_EXIT_CRITICAL();
        return (OS_ERR_TIME_NOT_DLY);                          /* Indicate that task was not delayed   */
    }
 
    ptcb->OSTCBDly = 0u;                                       /* 清除任务计数器       */
    if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
        ptcb->OSTCBStat     &= ~OS_STAT_PEND_ANY;              /* Yes, Clear status flag               */
        ptcb->OSTCBStatPend  =  OS_STAT_PEND_TO;               /* Indicate PEND timeout                */
    } else {
        ptcb->OSTCBStatPend  =  OS_STAT_PEND_OK;
    }
    if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {  /* Is task suspended?                   */
        OSRdyGrp               |= ptcb->OSTCBBitY;             /* No,  Make ready                      */
        OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
        OS_EXIT_CRITICAL();
        OS_Sched();                                            /* See if this is new highest priority  */
    } else {
        OS_EXIT_CRITICAL();                                    /* Task may be suspended                */
    }
    return (OS_ERR_NONE);
}

4,让处在延时期的任务结束延时:OSTimeDlyResume( INT8U prio)
  延时的任务可以不等待延时期满,而是通过其它任务取消延时来使自己处于就绪态。实际上,OSTimeDlyResume()也可以唤醒正在等待事件。

5,系统时间, OSTimeGet()函数和 OSTimeSet()函数:在访问 OSTime 的时候中断是关掉的。这是因为在大多数 8 位处理器上增加和拷贝一个 32位的数都需要数条指令,这些指令一般都需要一次执行完毕,而不能被中断等因素打断。
无论时钟节拍何时发生, µCOSⅡ会将一个 32 位的计数器加 1。这个计数器在用户调用 OSStart()初始化多任务和 4,294,967,295 个节拍执行完一遍的时候从 0 开始计数。在时钟节拍的频率等于 100Hz 的时候,这个 32 位的计数器每隔 497 天就重新开始计数。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/136895.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • JAVA中的数组插入与删除指定元素

    JAVA中的数组插入与删除指定元素今天学了Java的数组,写了数组的插入和删除,本人小白,写给不会的小白看,大神请忽略,有错请大家指出来;/**给数组指定位置数组的插入*/importjava.util.*;publicclassArrayInsert{publicstaticvoidmain(String[]args){System.out.println(“请用键

    2022年6月26日
    59
  • Python基本数据类型有哪些

    Python基本数据类型有哪些1.基本数据类型1.数字类型:整型(int),浮点型(float),复数类型(complex)2.字符串类型:str3.逻辑类型:boolTrueFalse4.列表类型:list[]有序可修改5.元组类型:tuple()有序不可修改6.集合类型:set{}无序不重复7.字典类型:dict{key:value}无序2.整形中的四种进制…

    2022年5月24日
    43
  • word2016论文不同章节设置页眉页码方法[通俗易懂]

    word2016论文不同章节设置页眉页码方法[通俗易懂]最近在写硕士论文需要调整页眉页脚,并且每一章都不一样,网上搜的教程都有点复杂,现在自己弄懂了,把它记录下来:1,设置不同章节不同页眉2,设置奇偶页不同2,设置页码从第xx页开始本文以word2016为例,讲述以上3点的设置方法:1,设置不同章节不同页眉首先是常规操作,点击word上方插入–页眉和页码这样页眉和页码就在word上显示出来了然而仅这样操作所有…

    2025年7月3日
    2
  • 字符串正则匹配leetcode_动态规划的特点

    字符串正则匹配leetcode_动态规划的特点原题链接给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。‘.’ 匹配任意单个字符‘*’ 匹配零个或多个前面的那一个元素所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。示例 1:输入:s = “aa” p = “a”输出:false解释:”a” 无法匹配 “aa” 整个字符串。示例 2:输入:s = “aa” p = “a*”输出:true解释:因为 ‘*’ 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是

    2022年8月9日
    8
  • JavaScript foreach 方法跳出循环

    JavaScript foreach 方法跳出循环通常 在 for 循环中跳出循环可以用 break 或者 continue 来跳出循环 break 跳出循环 continue 跳过当次循环 而有时候需要在 foreach 中跳出循环 该怎么做呢 forEach 方法用于调用数组的每个元素 并将元素传递给回调函数 对于空数组不会执行回调函数 回调函数的参数 function currentValue index arr currentValue 必需 当前元素 index 可选 当前元素的索引值 arr

    2025年12月11日
    2
  • 数据结构——线索化二叉树和哈夫曼树[通俗易懂]

    数据结构——线索化二叉树和哈夫曼树[通俗易懂]线索化二叉树和哈夫曼树基础知识介绍与代码分析一、基础知识介绍二、代码分析:线索二叉树(采用中序遍历)#include “pch.h”#include <iostream>using namespace std;//定义线索二叉树typedef struct Tree{ int data, LTag, RTag; //定义数据域与标记域 Tre…

    2022年8月18日
    10

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号