热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

uC/OS-II源码分析(四)

内核结构1,临界区,OS_ENTER_CRITICAL和OS_EXIT_CRITICAL为了处理临界区代码,必须关中断,等处理完毕后,再开中断。关中断可以避免其他任务或中断进入临界区代

内核结构

1,  临界区,OS_ENTER_CRITICAL和OS_EXIT_CRITICAL

为了处理临界区代码,必须关中断,等处理完毕后,再开中断。关中断可以避免其他任务或中断进入临界区代码。uC/OS-II定义了这两个宏来实现,但注意一条:调用uC/OS-II功能函数时,中断应该总是开着的。

      1)当OS_CRITICAL_METHOD= = 1时,简单实现如下:

 

    #define OS_ENTER_CRITICAL() disable_int() 
    # define OS_EXIT_CRITICAL() enable_int()

 

但这样有一个问题,如果禁止中断的情况下调用uC/OS-II功能函数,那么从功能函数返回时,中断可能变成允许的了,而实际上还是希望是禁止的。

      2)当OS_CRITICAL_METHOD= = 2时,实现如下:

    #define OS_ENTER_CRITICAL()    
            asm(“PUSH PSW”);
            asm(“DI”);
    #define OS_EXIT_CRITICAL()
            asm(“POP PSW”);

 

执行OS_ENTER_CRITICAL()时,先将中断状态保存到堆栈,然后关中断;执行OS_EXIT_CRITICAL()时,再从堆栈中恢复原来的中断开/关状态。这种方法不会改变中断状态,避免前面的问题。

      3)当OS_CRITICAL_METHOD= = 3时,实现如下:

    #define OS_ENTER_CRITICAL()    
        cpu_sr = get_processor_psw();
        disable_interrupts();
    #define OS_EXIT_CRITICAL()
        set_ processor_psw(cpu_sr);

 

      将处理器状态字保存在局部变量中。

2,  任务是一个无限循环,返回类型为void,参数void*,用于传数据给任务。任务可以调用OSTaskDel(OS_PRIO_SELF)进行自我删除。任务有5种状态:

1)     睡眠态。任务驻留在程序空间(ROM或RAM),还未交给uC/OS-II来管理。

2)     就绪态。OSTaskCreate()或OSTaskCreateExt()来创建一个任务后,就进入就绪态。任务可以调用OSTaskDel返回到睡眠态,或调用该函数让另一个任务进入睡眠态。

3)     运行态。OSStart()启动多任务运行。它只在启动时调用一次,运行就绪列表中优先级最高的任务。就绪的任务只有当所以优先级比其高的任务转为等待状态,或者是被删除了,才能进入运行态。

4)     等待状态。正在运行的任务可以调用OSTimeDly()或OSTimeDlyHMSM()将自身延迟一段时间进入等待状态,一直到延迟时间到来。这两个函数会强制执行任务切换,选择下一个优先级最高的任务运行。等待时间过去后,系统服务函数OSTimeTick()使延迟了的任务进入就绪态。

正在运行的任务也可能需要等待某一事件的发生,可以调用:OSFlagPend(),OSSemPend(),OSMutexPend(),OSMboxPend(),OSQPend()等函数。若某事件未发生,则任务进入等待状态,直到事件发生。当任务因等待事件被挂起时,下一个优先级最高的任务得到CPU。当事件发生了或超时,被挂起的任务进入就绪态。事件发生的报告可能来自另一个任务或中断服务子程序。

5)     中断服务态 。被中断的任务进入中断服务态,从而被挂起,中断服务子程序得到CPU,后者可能报告一个或多个事件发生,从而使一个或多个任务进入就绪态。因此从中断服务子程序返回前,uC/OS-II要判断被中断的任务的优先级和就绪列表中其他任务的优先级高低,选择最高的任务进入运行态。

6)     当所以任务都在等待事件发生或等待延迟的时间结束时,uC/OS-II运行OSTaskIdle()任务。

3,  任务控制块(OS_TCB)

建立一个任务时,一个OS_TCB就被赋值。当任务的CPU被剥夺时,用它来保存任务的状态,当任务重新得到CPU时,它也能保证任务从当时被中断的那一点继续执行。OS_TCB全部驻留在RAM中。

 

typedef struct os_tcb 
{
    OS_STK        *OSTCBStkPtr;        /*指向当前任务堆栈栈顶的指针*/
#if OS_TASK_CREATE_EXT_EN > 0
    void          *OSTCBExtPtr;        /* 指向用户定义的任务控制块扩展*/
    OS_STK        *OSTCBStkBottom;     /* 指向栈底的指针*/
    INT32U         OSTCBStkSize;       /* 栈中可容纳的元素数目(
uC/OS-II允许每个任务的堆栈容量任意,)*/
    INT16U         OSTCBOpt;           /* 传给OSTaskCreateExt()的任务选择项*/
    INT16U         OSTCBId;            /* Task ID (0..65535) */
#endif
    struct os_tcb *OSTCBNext;          /*TCB列表中指向下一个TCB的指针*/
    struct os_tcb *OSTCBPrev;          /* TCB列表中指向上一个TCB的指针*/
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0) || (OS_SEM_EN > 0) || (OS_MUTEX_EN > 0)
    OS_EVENT      *OSTCBEventPtr;      /*指向事件控制块的指针*/
#endif
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)
    void          *OSTCBMsg;           /*指向传递给任务的消息的指针,消息来自OSMboxPost() or OSQPost() */
#endif
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
#if OS_TASK_DEL_EN > 0
    OS_FLAG_NODE  *OSTCBFlagNode;      /*指向事件标志节点的指针*/
#endif    
    OS_FLAGS       OSTCBFlagsRdy;      /* 使任务进入就绪态的事件标志*/
#endif
    INT16U         OSTCBDly;           /* 让任务延时若干节拍或把任务挂起一段时间等待某一事件发生时使用的计时变量*/
    INT8U          OSTCBStat;          /* 任务状态*/
    INT8U          OSTCBPrio;          /* 任务优先级(0 == highest, 63 == lowest)*/
    //下面四个变量用于加速任务进入就绪态或进入等待事件发生状态的过程,算法比较巧妙
    INT8U          OSTCBX;             /* Bit position in group  corresponding to task priority (0..7) */
    INT8U          OSTCBY;             /* Index into ready table corresponding to task priority        
    INT8U          OSTCBBitX;          /* Bit mask to access bit position in ready table               
    INT8U          OSTCBBitY;          /* Bit mask to access bit position in ready group               
#if OS_TASK_DEL_EN > 0
    BOOLEAN        OSTCBDelReq;        /* 表面任务是否需要删除自己*/
#endif
} OS_TCB;

 

uC/OS-II在通过OS_MAX_TASKS定义了最大的任务数目,这也决定了分配给用户程序的任务控制块OS_TCB的数目,但此外uC/OS-II还分配给系统任务OS_N_SYS_TASKS若干个额外的任务控制块,供其内部使用。uC/OS-II初始化时,所以任务控制块都被链接成单向空任务链表,任务一旦建立,空任务控制块指针OSTCBFreeList指向的任务控制块就赋给该任务,然后OSTCBFreeList调整为指向链表中下一个空任务控制块。一旦任务被删除,任务控制块被还给空任务链表。

      任务建立时,OS_TCBInit()初始化任务控制块,函数OSTaskCreate()或OSTaskCreateExt()调用任务控制块初始化函数TCBInit。

 

INT8U  OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)
{
#if OS_CRITICAL_METHOD == 3                                /* 为CPU状态寄存器分配内存*/
    OS_CPU_SR  cpu_sr;
#endif    
    OS_TCB    *ptcb;
    OS_ENTER_CRITICAL();
    ptcb = OSTCBFreeList;                                  /* 从空闲TCB链表中取一个空TCB*/
    if (ptcb != (OS_TCB *)0) 
    {//取到了空TCB
        OSTCBFreeList        = ptcb->OSTCBNext;            /* 更新空闲TCB链表头指针*/
        OS_EXIT_CRITICAL();
        ptcb->OSTCBStkPtr    = ptos;                       /* 保存栈顶指针到TCB*/
        ptcb->OSTCBPrio      = (INT8U)prio;                /* 保存任务优先级到TCB*/
        ptcb->OSTCBStat      = OS_STAT_RDY;                /* 任务状态设置为就绪*/
        ptcb->OSTCBDly       = 0;                          /* 任务不延时等待*/
#if OS_TASK_CREATE_EXT_EN > 0//使用扩展
        ptcb->OSTCBExtPtr    = pext;                       /* 保存TCB扩展指针*/
        ptcb->OSTCBStkSize   = stk_size;                   /* 保存栈大小*/
        ptcb->OSTCBStkBottom = pbos;                       /* 保存栈底*/
        ptcb->OSTCBOpt       = opt;                        /* 保存任务选择项*/
        ptcb->OSTCBId        = id;                         /*保存任务ID*/
#else//不使用扩展
        pext                 = pext;                       
        stk_size             = stk_size;
        pbos                 = pbos;
        opt                  = opt;
        id                   = id;
#endif
#if OS_TASK_DEL_EN > 0
        ptcb->OSTCBDelReq    = OS_NO_ERR;                //初始化删除标志
#endif
        ptcb->OSTCBY         = prio >> 3;                  /* 预先计算X, Y, BitX and BitY*/
        ptcb->OSTCBBitY      = OSMapTbl[ptcb->OSTCBY];
        ptcb->OSTCBX         = prio & 0x07;
        ptcb->OSTCBBitX      = OSMapTbl[ptcb->OSTCBX];

#if OS_EVENT_EN > 0
        ptcb->OSTCBEventPtr  = (OS_EVENT *)0;              /* 任务不等待任何事件发生*/
#endif
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0)
        ptcb->OSTCBFlagNode  = (OS_FLAG_NODE *)0;          /* 任务不等待事件标志*/
#endif
#if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0))
        ptcb->OSTCBMsg       = (void *)0;                  /* 没有接收任何消息*/
#endif
#if OS_VERSION >= 204
        OSTCBInitHook(ptcb);
#endif
        OSTaskCreateHook(ptcb);                            /* 调用用户定义的钩子函数*/
        OS_ENTER_CRITICAL();
        OSTCBPrioTbl[prio] = ptcb;
        ptcb->OSTCBNext    = OSTCBList;                    /*将TCB插入已经建立任务的双向链表中*/
        ptcb->OSTCBPrev    = (OS_TCB *)0;
        if (OSTCBList != (OS_TCB *)0) {
            OSTCBList->OSTCBPrev = ptcb;
        }
        OSTCBList               = ptcb;
        OSRdyGrp               |= ptcb->OSTCBBitY;         /*让用户进入就绪态*/
        OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
        OS_EXIT_CRITICAL();
        return (OS_NO_ERR);
    }
    OS_EXIT_CRITICAL();
    return (OS_NO_MORE_TCB);
}

 

作者:洞庭散人

出处:http://phinecos.cnblogs.com/    

本博客遵从 Creative Commons Attribution 3.0 License,若用于非商业目的,您可以自由转载,但请保留原作者信息和文章链接URL。

推荐阅读
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文介绍了PhysioNet网站提供的生理信号处理工具箱WFDB Toolbox for Matlab的安装和使用方法。通过下载并添加到Matlab路径中或直接在Matlab中输入相关内容,即可完成安装。该工具箱提供了一系列函数,可以方便地处理生理信号数据。详细的安装和使用方法可以参考本文内容。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
author-avatar
timer_open
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有