内核结构
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);
}
本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2007/11/22/969233.html,如需转载请自行联系原作者

uC/OS-II源码分析(四)相关推荐

  1. 【嵌入式系统—实时操作系统】uC/OS II源码的官网下载

    要下载源码为:STM32F107-uC/OS-II源码包 Micrium官网的下载地址:Micrium_uC-Eval-STM32F107_uCOS-II 怎么找? 到官网的产品专区目录入口查找STM ...

  2. ABP源码分析四十七:ABP中的异常处理

    ABP源码分析四十七:ABP中的异常处理 参考文章: (1)ABP源码分析四十七:ABP中的异常处理 (2)https://www.cnblogs.com/1zhk/p/5538983.html (3 ...

  3. 【投屏】Scrcpy源码分析四(最终章 - Server篇)

    Scrcpy源码分析系列 [投屏]Scrcpy源码分析一(编译篇) [投屏]Scrcpy源码分析二(Client篇-连接阶段) [投屏]Scrcpy源码分析三(Client篇-投屏阶段) [投屏]Sc ...

  4. gSOAP 源码分析(四)

    gSOAP 源码分析(四) 2012-6-2 邵盛松 前言 本文主要说明gSOAP中对Client的认证分析 gSOAP中包含了HTTP基本认证,NTLM认证等,还可以自定义SOAP Heard实现认 ...

  5. Spring 源码分析(四) ——MVC(二)概述

    随时随地技术实战干货,获取项目源码.学习资料,请关注源代码社区公众号(ydmsq666) from:Spring 源码分析(四) --MVC(二)概述 - 水门-kay的个人页面 - OSCHINA ...

  6. 【转】ABP源码分析四十七:ABP中的异常处理

    ABP 中异常处理的思路是很清晰的.一共五种类型的异常类. AbpInitializationException用于封装ABP初始化过程中出现的异常,只要抛出AbpInitializationExce ...

  7. 【转】ABP源码分析四:Configuration

    核心模块的配置 Configuration是ABP中设计比较巧妙的地方.其通过AbpStartupConfiguration,Castle的依赖注入,Dictionary对象和扩展方法很巧妙的实现了配 ...

  8. 谷歌chrome浏览器的源码分析(四)

    上一次说到需要调用这个OpenURLFromTab函数,那么这个函数是做什么的呢?从名称上可能猜到它是打开网页,但是是从目前TAB页里打开呢?还是新建一个?或者使用每个TAB页一个进程呢?这些疑惑,只 ...

  9. 【转】ABP源码分析四十六:ABP ZERO中的Ldap模块

    通过AD作为用户认证的数据源.整个管理用户认证逻辑就在LdapAuthenticationSource类中实现. LdapSettingProvider:定义LDAP的setting和提供Defaut ...

  10. 【转】ABP源码分析四十五:ABP ZERO中的EntityFramework模块

    AbpZeroDbContext:配置ABP.Zero中定义的entity的Dbset EntityFrameworkModelBuilderExtensions:给PrimitiveProperty ...

最新文章

  1. first-child伪类选择器没有效果(不起作用)
  2. ORACLE工作原理小结
  3. redis连接池操作
  4. java课设电子门禁_中控门禁pullSdk Java demo 中控智慧门禁系统 - 下载 - 搜珍网
  5. H3C 模拟器 防火墙开启Web功能
  6. 语言 泰克示波器程序_示波器再升级,EMI测试不求人
  7. mysql 分表后如何扩展_MySQL横向扩展-分库分表解决方案总结
  8. Spring Boot 2.x 把 Guava 干掉了,拥抱本地缓存之王 Caffeine!
  9. 【完整matlab程序】【预测程序】狼群优化算法及BP神经网络
  10. android分屏模式_Android分屏显示总结
  11. 当幻想的小说来到现实——基于stable diffusion的小说插画生成
  12. 量化金融分析AQF(1):股票概述
  13. 计算机辅助设计论文结论,计算机辅助设计在平面设计中存在的问题论文
  14. Java配置环境变量(Windows)
  15. 美拍、秒拍短视频SDK功能实现
  16. SQL学习-2.7 SQL聚合
  17. RSD 教程 —— §3.5 观察光谱曲线
  18. c语言如何输入一篇英文文章,(急急,救命啊!c语言)输入一篇英语文章,求输出这篇文章的所有英语单词的个数。...
  19. C4D室内模型导入Unity3d灯光快速烘焙【2020】
  20. 页面实现自动保存内容功能

热门文章

  1. mysql 5.5.38_数据库的硬迁移和mysql 5.5.38源码安装
  2. Java bitset转string_Java 二进制和十进制互转,二进制和BitSet互转
  3. 减少访问量_Lazada:唯一一个访问量明显着下降、出现负增长10%的玩家
  4. i2c通信 msp430g2553_请教 AD7150 + MSP430G2553 i2C通讯问题该如何编码??
  5. 如何在自己开发的日程管理页面插入提醒功能_微信中6个藏得很深但却很有用的功能...
  6. Java实用教程笔记 输入、输出流
  7. LeetCode 860.柠檬水找零(C++)
  8. PHP5中PDO(PHP DATA OBJECT)模块基础详解
  9. Java延迟加载建议
  10. openresty读取环境变量