想让uC/OS-Ⅱ管理用户的任务,用户必须要先建立任务。用户可以通过传递任务地址和其它参数到以下两个函数之一来建立任务:OSTaskCreate() 或 OSTaskCreateExt()。OSTaskCreate()与uC/OS是向下兼容的,OSTaskCreateExt()是OSTaskCreate()的扩展版本,提供了一些附加的功能。用两个函数中的任何一个都可以建立任务。

任务可以在多任务调度开始前建立,也可以在其它任务的执行过程中被建立。在开始多任务调度(即调用OSStart())前,用户必须建立至少一个任务。任务不能由中断服务程序(ISR)来建立。

OSTaskCreate()的代码如程序清单 L4.1所述。从中可以知道,OSTaskCreate()需要四个参数:

task是任务代码的指针,

pdata是当任务开始执行时传递给任务的参数的指针,

ptos是分配给任务的堆栈的栈顶指针(参看4.02,任务堆栈),

prio是分配给任务的优先级。

OSTaskCreate函数源码

//建立一个新任务
#if OS_TASK_CREATE_EN > 0                //允许生成OSTaskCreate()函数
INT8U  OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio)
{
#if OS_CRITICAL_METHOD == 3                  //中断函数被设定为模式3  OS_CPU_SR  cpu_sr;
#endif  OS_STK    *psp;                         //初始化任务堆栈指针变量,返回新的栈顶指针  INT8U      err;                         //定义(获得并定义初始化任务控制块)是否成功  #if OS_ARG_CHK_EN > 0                        //所有参数必须在指定的参数内  if (prio > OS_LOWEST_PRIO) {            //检查任务优先级是否合法  return (OS_PRIO_INVALID);           //参数指定的优先级大于OS_LOWEST_PRIO  }
#endif  OS_ENTER_CRITICAL();            //关闭中断  if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { //确认优先级未被使用,即就绪态为0  OSTCBPrioTbl[prio] = (OS_TCB *)1;    //保留这个优先级,将就绪态设为1  OS_EXIT_CRITICAL();             //打开中断  psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, 0);    //初始化任务堆栈  err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);       //获得并初始化任务控制块  if (err == OS_NO_ERR) {     //任务控制初始化成功  OS_ENTER_CRITICAL();    //关闭中断  OSTaskCtr++;            //任务计数器加1  OS_EXIT_CRITICAL();     //打开中断  if (OSRunning == TRUE) {         //检查是否有(某个)任务在运行  OS_Sched();                  //任务调度,最高任务优先级运行  }  } else {        //否则,任务初始化失败  OS_ENTER_CRITICAL();        //关闭中断  OSTCBPrioTbl[prio] = (OS_TCB *)0;       //放弃任务,设此任务就绪态为0  OS_EXIT_CRITICAL();                     //打开中断  }  return (err);           //返回(获得并定义初始化任务控制块是否成功)  }  OS_EXIT_CRITICAL();         //打开中断  return (OS_PRIO_EXIST);     //返回(具有该优先级的任务已经存在)
}
#endif  

OSTaskCreate函数源码解析

OSTaskCreate()一开始先检测分配给任务的优先级是否有效[L4.1(1)]。任务的优先级必须在0到OS_LOWEST_PRIO之间。接着,OSTaskCreate()要确保在规定的优先级上还没有建立任务[L4.1(2)]。在使用UC/OS-Ⅱ时,每个任务都有特定的优先级。如果某个优先级是空闲的,UC/OS-Ⅱ通过放置一个非空指针在OSTCBPrioTbl[]中来保留该优先级[L4.1(3)]。这就使得OSTaskCreate()在设置任务数据结构的其他部分时能重新允许中断[L4.1(4)]。

然后,OSTaskCreate()调用OSTaskStkInit()[L4.1(5)],它负责建立任务的堆栈。该函数是与处理器的硬件体系相关的函数,可以在OS_CPU_C.C文件中找到。有关实现OSTaskStkInit()的细节可参看第8章——移植UC/OS-Ⅱ。如果已经有人在你用的处理器上成功地移植了UC/OS-Ⅱ,而你又得到了他的代码,就不必考虑该函数的实现细节了。OSTaskStkInit()函数返回新的堆栈栈顶(psp),并被保存在任务的0S_TCB中。注意用户得将传递给OSTaskStkInit()函数的第四个参数opt置0,因为OSTaskCreate()与OSTaskCreateExt()不同,它不支持用户为任务的创建过程设置不同的选项,所以没有任何选项可以通过opt参数传递给OSTaskStkInit()。

UC/OS-Ⅱ支持的处理器的堆栈既可以从上(高地址)往下(低地址)递减也可以从下往上递增。用户在调用OSTaskCreate()的时候必须知道堆栈是递增的还是递减的(参看所用处理器的OS_CPU.H中的OS_STACK_GROWTH),因为用户必须得把堆栈的栈顶传递给OSTaskCreate(),而栈顶可能是堆栈的最高地址(堆栈从上往下递减),也可能是最低地址(堆栈从下往上长)。

一旦OSTaskStkInit()函数完成了建立堆栈的任务,OSTaskCreate()就调用OSTCBInit()[L4.1(6)],从空闲的OS_TCB池中获得并初始化一个OS_TCB。OSTCBInit()的代码如程序清单 L4.2所示,它存在于0S_CORE.C文件中而不是OS_TASK.C文件中。

OSTCBInit()函数首先从OS_TCB缓冲池中获得一个OS_TCB[L4.2(1)],如果OS_TCB池中有空闲的OS_TCB[L4.2(2)],它就被初始化[L4.2(3)]。注意一旦OS_TCB被分配,该任务的创建者就已经完全拥有它了,即使这时内核又创建了其它的任务,这些新任务也不可能对已分配的OS_TCB作任何操作,所以OSTCBInit()在这时就可以允许中断,并继续初始化OS_TCB的数据单元。

OSTaskCreateExt函数源码

//建立一个新任务。与OSTaskCreate()不同的是,OSTaskCreateExt()允许用户设置更多的细节
//内容。任务的建立可以在多任务环境启动之前,也可以在正在运行的任务中建立,但中断处理
//程序中不能建立新任务。一个任务必须为无限循环结构,且不能有返回点。
#if OS_TASK_CREATE_EXT_EN > 0                //允许生成OSTaskCreateExt()函数
INT8U  OSTaskCreateExt (void   (*task)(void *pd),   //建立扩展任务(任务代码指针)  void    *pdata,             //传递参数指针  OS_STK  *ptos,              //分配任务堆栈栈顶指针  INT8U    prio,              //分配任务优先级  INT16U   id,                //(未来的)优先级标识(与优先级相同)  OS_STK  *pbos,              //分配任务堆栈栈底指针  INT32U   stk_size,          //指定堆栈的容量(检验用)  void    *pext,              //指向用户附加的数据域的指针  INT16U   opt)               //建立任务设定选项
{
#if OS_CRITICAL_METHOD == 3                  //中断函数被设定为模式3  OS_CPU_SR  cpu_sr;
#endif  OS_STK    *psp;                         //初始化任务堆栈指针变量,返回新的栈顶指针  INT8U      err;                         //定义(获得定义初始化任务控制块)是否成功  #if OS_ARG_CHK_EN > 0        //所有参数必须在指定的参数内  if (prio > OS_LOWEST_PRIO) {             //检查任务优先级是否合法  return (OS_PRIO_INVALID);            //参数指定的优先级大于OS_LOWEST_PRIO  }
#endif  OS_ENTER_CRITICAL();        //关闭中断  if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { //确认优先级未被使用,即就绪态为0  OSTCBPrioTbl[prio] = (OS_TCB *)1;    //保留这个优先级,将就绪态设为0  OS_EXIT_CRITICAL();     //打开中断  //以下两为1堆栈才能清0  if (((opt & OS_TASK_OPT_STK_CHK) != 0x0000) ||   //检验任务堆栈,CHK=1  ((opt & OS_TASK_OPT_STK_CLR) != 0x0000)) {   //任务建立时是否清0,CLR=1  #if OS_STK_GROWTH == 1          //堆栈生长方向  (void)memset(pbos, 0, stk_size * sizeof(OS_STK));       //从下向上递增  #else  (void)memset(ptos, 0, stk_size * sizeof(OS_STK));       //从下向下递减  #endif  }  psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, opt);      //初始化任务堆栈  err = OS_TCBInit(prio, psp, pbos, id, stk_size, pext, opt);     //获得并初始化任务控制块  if (err == OS_NO_ERR) { //任务控制初始化成功  OS_ENTER_CRITICAL();        //关闭中断  OSTaskCtr++;                //任务计数器加1  OS_EXIT_CRITICAL();         //打开中断  if (OSRunning == TRUE) {              //检查是否有(某个)任务在运行  OS_Sched();                       //任务调度,最高任务优先级运行  }  } else {        //否则,任务初始化失败  OS_ENTER_CRITICAL();        //关闭中断  OSTCBPrioTbl[prio] = (OS_TCB *)0;                 //放弃任务,设此任务就绪态为0  OS_EXIT_CRITICAL();         //打开中断  }  return (err);       //返回(获得并定义初始化任务控制块是否成功)  }  OS_EXIT_CRITICAL();     //打开中断  return (OS_PRIO_EXIST);     //具有该优先级的任务已经存在
}
#endif  

http://blog.csdn.net/liuhui_8989/article/details/8781407

建立任务,OSTaskCreate()源码解析相关推荐

  1. ActiveMQ源码解析 建立连接

    作为一个消息中间件,有客户端和服务端两部分代码,这次的源码解析系列主要从客户端的代码入手,分成建立连接.消息发送.消息消费三个部分.趁着我昨天弄明白了源码编译的兴奋劲头还没过去,今天研究一下建立连接的 ...

  2. 谷歌BERT预训练源码解析(二):模型构建

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_39470744/arti ...

  3. 彻底理解OkHttp - OkHttp 源码解析及OkHttp的设计思想

    OkHttp 现在统治了Android的网络请求领域,最常用的框架是:Retrofit+okhttp.OkHttp的实现原理和设计思想是必须要了解的,读懂和理解流行的框架也是程序员进阶的必经之路,代码 ...

  4. spring 注解试事物源码解析

    spring 注解试事物源码解析 基于xml注解式事务入口 public class TxNamespaceHandler extends NamespaceHandlerSupport {stati ...

  5. 2015.07.20MapReducer源码解析(笔记)

    MapReducer源码解析(笔记) 第一步,读取数据源,将每一行内容解析成一个个键值对,每个键值对供map函数定义一次,数据源由FileInputFormat:指定的,程序就能从地址读取记录,读取的 ...

  6. Guava RateLimiter限流源码解析和实例应用

    2019独角兽企业重金招聘Python工程师标准>>> 在开发高并发系统时有三把利器用来保护系统:缓存.降级和限流 缓存 缓存的目的是提升系统访问速度和增大系统处理容量 降级 降级是 ...

  7. The Wide and Deep Learning Model(译文+Tensorlfow源码解析) 原创 2017年11月03日 22:14:47 标签: 深度学习 / 谷歌 / tensorf

    The Wide and Deep Learning Model(译文+Tensorlfow源码解析) 原创 2017年11月03日 22:14:47 标签: 深度学习 / 谷歌 / tensorfl ...

  8. OkHttp3源码解析(三)——连接池复用

    OKHttp3源码解析系列 OkHttp3源码解析(一)之请求流程 OkHttp3源码解析(二)--拦截器链和缓存策略 本文基于OkHttp3的3.11.0版本 implementation 'com ...

  9. webbench源码解析

    webbench源码解析 webbench简介 webbench是一款用C编写的开源工具,主要用来在Linux下进行网站压力测试.最多可以模拟3万个连接去测试网站的负载能力,并可以设置运行的客户端数. ...

最新文章

  1. ASP.NET画图控件 Chart Control 免费控件
  2. SpringMVC注解@initbinder解决类型转换问题
  3. [CTO札记]互联网一定要免费吗?网络文学是继网络游戏后又一成功的收费模式...
  4. gorm crud简单代码示例
  5. Angular里的消息(Message)显示
  6. 继承、私有属性-Python
  7. 编程基本功:创新是贬义词,与乱搞同义
  8. xposed框架_把安卓手机开发到极致的框架xposed
  9. NetWare 客户服务禁用了欢迎屏幕和快速切换恢复方法
  10. [转]考古学家完颜晓炜——人类曾经真…
  11. linux学习shell基础
  12. 深入学习HTTP协议
  13. 【翻译论文】Understanding Reuse, Performance, and Hardware Cost of DNN......
  14. 计算机cpu的功能和作用是什么意思,cpu的功能有哪些
  15. redis setIfAbsent和 setnx 的区别与使用
  16. 王姨劝我学HarmonyOS鸿蒙2.0系列教程之五布局方法点击响应!
  17. 用 Matlab 实现 GS 算法设计计算全息图
  18. 信息管理导论 | 信息组织
  19. java bookkeeping_Java - ExecutorService shutdown系列方法 的理解
  20. NI:力争成为半导体测试领域的领导者

热门文章

  1. LC AND NC CODE
  2. 织梦开启错误提示方法
  3. jfreechart 画柱状图
  4. Java使用Itext5.5.10进行pdf签章
  5. 阿里云服务器卡顿无法响应分析及解决方法
  6. html防复制粘贴技术
  7. irobot擦地机器人故障_简单修理irobot 380T拖地机器人 后退转圈故障
  8. 【信贷业务】营销场景及模型介绍
  9. 有趣的计算机黑科技,这些不可思议又有趣好玩的黑科技,你造吗?
  10. 程序员修炼之道--读书简记