• uCOSIII实时操作系统 五 任务API(任务创建和删除)


    任务创建和删除

    引入:一个任务的三要素是任务主体函数,任务栈,任务控制块,那么怎样吧这个三要素联系在一起呐?

    任务创建:

    在UCOSIII中我们通过函数OSTaskCreate()来创建任务。

    作用:任务控制块,任务堆栈,任务代码等联系在一起,并初始化控制块的相应字段。

    位置:os_task.c中定义原型函数

    先不深究源码,先看看怎么用起来。

    1. //任务创建函数入口参数解释
    2. void OSTaskCreate (OS_TCB *p_tcb,//指向任务控制块OS_TCB
    3. CPU_CHAR *p_name,//指向任务的名字(字符串类型),每个任务都有不同的名字
    4. OS_TASK_PTR p_task,//执行任务代码,任务函数名
    5. void *p_arg,//传递任务主体函数的参数
    6. OS_PRIO prio,//任务优先级(一般从3开始,不用0/1/2)
    7. CPU_STK *p_stk_base,//指向堆栈基地址
    8. CPU_STK_SIZE stk_limit,//任务堆栈的最大深度(堆栈限制)
    9. CPU_STK_SIZE stk_size,//任务堆栈的大小
    10. OS_MSG_QTY q_size,//内嵌消息队列,0默认不用
    11. OS_TICK time_quanta,//时间片的长度,0默认时间节数除以10,// 轮转时间=time_quanta*时间长度
    12. void *p_ext,指向用户补充内存区,填0即可
    13. OS_OPT opt,//选项
    14. /*选项:
    15. OS_OPT_TASK_NONE //不使用任何选项
    16. OS_OPT_TASK_STK_CHK //检查栈
    17. OS_OPT_TASK_STK_CLR //清除栈
    18. OS_OPT_TASK_SAVE_FP //保存浮点寄存器中的内容
    19. */
    20. OS_ERR *p_err)//错误码

    注意:为什么任务优先级一般从3开始

    //UCOSIII中以下优先级用户程序不能使用,ALIENTEK
    //将这些优先级分配给了UCOSIII的5个系统内部任务
    //优先级0:中断服务服务管理任务 OS_IntQTask()
    //优先级1:时钟节拍任务 OS_TickTask()
    //优先级2:定时任务 OS_TmrTask()
    //优先级OS_CFG_PRIO_MAX-2:统计任务 OS_StatTask()
    //优先级OS_CFG_PRIO_MAX-1:空闲任务 OS_IdleTask()

    任务创建应用模版:

    1. //任务优先级
    2. #define START_TASK_PRIO 3
    3. //任务控制块
    4. OS_TCB StartTaskTCB;
    5. //任务堆栈大小
    6. #define START_STK_SIZE 512
    7. //任务堆栈
    8. CPU_STK START_TASK_STK[START_STK_SIZE];
    9. //任务函数
    10. void start_task(void *p_arg);
    11. int main(void)
    12. {
    13. OS_ERR err;//定义一个错误码
    14. CPU_SR_ALLOC();//进入临界区,定义临界区需要的变量
    15. //硬件初始化
    16. /*
    17. delay_init(); //延时初始化
    18. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组配置
    19. uart_init(115200); //串口波特率设置
    20. LED_Init(); //LED初始化
    21. */
    22. OSInit(&err); //初始化UCOSIII
    23. OS_CRITICAL_ENTER();//进入临界区(关闭中断)
    24. //创建开始任务
    25. /*
    26. OSTaskCreate((OS_TCB * )&StartTaskTCB, //任务控制块
    27. (CPU_CHAR * )"start task", //任务名字
    28. (OS_TASK_PTR )start_task, //任务函数
    29. (void * )0, //传递给任务函数的参数
    30. (OS_PRIO )START_TASK_PRIO, //任务优先级
    31. (CPU_STK * )&START_TASK_STK[0], //任务堆栈基地址
    32. (CPU_STK_SIZE)START_STK_SIZE/10, //任务堆栈深度限位
    33. (CPU_STK_SIZE)START_STK_SIZE, //任务堆栈大小
    34. (OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
    35. (OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度,
    36. (void * )0, //用户补充的存储区
    37. (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项
    38. (OS_ERR * )&err); //存放该函数错误时的返回值
    39. */
    40. OS_CRITICAL_EXIT(); //退出临界区(开启中断)
    41. OSStart(&err); //开启UCOSIII
    42. while(1);
    43. }

    任务删除:

    OSTaskDel()函数用来删除当前任务。删除的任务将从所有就绪堵塞挂起和事件列表中删除。

    作用: 用来删除任务,当一个任务不需要运行时候可以利用此函数删掉。  

    位置:os_task.c中定义 函数原型:

    1. void OSTaskDel (OS_TCB *p_tcb,//删除任务TCB,也可以传递NULL指针删除自身函数
    2. OS_ERR *p_err)//返回错误码

    eg:

    OSTaskDel((OS_TCB*)0,&err); //删除任务自身 OSTaskDel((OS_TCB*)&Task2_TaskTCB,&err); //删除指定任务

    任务创建和删除实验

    实验要求:

    1. 1、主函数创建任务1负责创建任务2和任务3执行完函数之后删掉自身。
    2. 2、任务2和任务3在任务运行过程中要将自身运行次数通过串口打印。
    3. 3、任务2在执行任务超过十次后删除任务3

    先准备一个移植好的空白模版:

    先定义一下任务1:

    在main函数当中根据之前的模版输入

    此时在创建任务1的各个入口参数与定义的任务1对应

    编写任务1,因为要求我们在任务1中创建任务2任务3

    此时任务2任务3还未被定义,返回定义任务1的下方定义任务2任务3 :

    编写任务2任务3 函数。

    又裸机基础的上边要求的逻辑很好理解,这里就不在解释。

    注意:在任务2/3都是运行在while(1)循环当中,要是任务一直在while(1)中没法挂起,退出死循环,那这样就不会进行任务3,所以while(1)中一定要加阻塞。所以用OSTimeDlyHMSM();函数进行延时阻塞。

    这样实验就进行成功了查看一下运行结果:

    实验源码:

    1. #include "led.h"
    2. #include "delay.h"
    3. #include "sys.h"
    4. #include "usart.h"
    5. #include "includes.h"
    6. //UCOSIII中以下优先级用户程序不能使用,ALIENTEK
    7. //将这些优先级分配给了UCOSIII的5个系统内部任务
    8. //优先级0:中断服务服务管理任务 OS_IntQTask()
    9. //优先级1:时钟节拍任务 OS_TickTask()
    10. //优先级2:定时任务 OS_TmrTask()
    11. //优先级OS_CFG_PRIO_MAX-2:统计任务 OS_StatTask()
    12. //优先级OS_CFG_PRIO_MAX-1:空闲任务 OS_IdleTask()
    13. //创建任务1
    14. //定义任务优先级
    15. #define TASK_1_PRIO 3
    16. //定义任务控制块
    17. OS_TCB TASK_1_TCB;
    18. //定义任务堆栈大小
    19. #define TASK_1_STK_SIZE 128
    20. //定义任务堆栈
    21. CPU_STK TASK_1_STK[TASK_1_STK_SIZE];
    22. //定义任务函数
    23. void TASK_1(void *arg);
    24. //创建任务2
    25. //定义任务优先级
    26. #define TASK_2_PRIO 4
    27. //定义任务控制块
    28. OS_TCB TASK_2_TCB;
    29. //定义任务堆栈大小
    30. #define TASK_2_STK_SIZE 128
    31. //定义任务堆栈
    32. CPU_STK TASK_2_STK[TASK_2_STK_SIZE];
    33. //定义任务函数
    34. void TASK_2(void *arg);
    35. //创建任务3
    36. //定义任务优先级
    37. #define TASK_3_PRIO 5
    38. //定义任务控制块
    39. OS_TCB TASK_3_TCB;
    40. //定义任务堆栈大小
    41. #define TASK_3_STK_SIZE 128
    42. //定义任务堆栈
    43. CPU_STK TASK_3_STK[TASK_3_STK_SIZE];
    44. //定义任务函数
    45. void TASK_3(void *arg);
    46. int main(void)
    47. {
    48. OS_ERR err1;//错误码变量
    49. CPU_SR_ALLOC();//定义临界区需要的变量
    50. //硬件初始化
    51. delay_init(); //延时初始化
    52. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组配置
    53. uart_init(115200); //串口波特率设置
    54. OSInit(&err1);//初始化UCOSIII
    55. OS_CRITICAL_ENTER();//进入临界区代码
    56. //创建开始任务1
    57. OSTaskCreate((OS_TCB * )&TASK_1_TCB, //任务控制块
    58. (CPU_CHAR * )"main TASK1", //任务名字
    59. (OS_TASK_PTR )TASK_1, //任务函数
    60. (void * )0, //传递给任务函数的参数
    61. (OS_PRIO )TASK_1_PRIO, //任务优先级
    62. (CPU_STK * )&TASK_1_STK[0], //任务堆栈基地址
    63. (CPU_STK_SIZE)TASK_1_STK_SIZE/10, //任务堆栈深度限位
    64. (CPU_STK_SIZE)TASK_1_STK_SIZE, //任务堆栈大小
    65. (OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
    66. (OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度,
    67. (void * )0, //用户补充的存储区
    68. (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项
    69. (OS_ERR * )&err1); //存放该函数错误时的返回值
    70. OS_CRITICAL_EXIT();//退出临界区代码
    71. OSStart(&err1);//开启UCOSIII
    72. while(1);
    73. }
    74. void TASK_1(void *arg)
    75. {
    76. OS_ERR err2_3;//错误码变量
    77. CPU_SR_ALLOC();//定义临界区需要的变量
    78. OS_CRITICAL_ENTER();//进入临界区代码
    79. //创建开始任务2
    80. OSTaskCreate((OS_TCB * )&TASK_2_TCB, //任务控制块
    81. (CPU_CHAR * )"main TASK2", //任务名字
    82. (OS_TASK_PTR )TASK_2, //任务函数
    83. (void * )0, //传递给任务函数的参数
    84. (OS_PRIO )TASK_2_PRIO, //任务优先级
    85. (CPU_STK * )&TASK_2_STK[0], //任务堆栈基地址
    86. (CPU_STK_SIZE)TASK_2_STK_SIZE/10, //任务堆栈深度限位
    87. (CPU_STK_SIZE)TASK_2_STK_SIZE, //任务堆栈大小
    88. (OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
    89. (OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度,
    90. (void * )0, //用户补充的存储区
    91. (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项
    92. (OS_ERR * )&err2_3); //存放该函数错误时的返回值
    93. //创建开始任务3
    94. OSTaskCreate((OS_TCB * )&TASK_3_TCB, //任务控制块
    95. (CPU_CHAR * )"main TASK3", //任务名字
    96. (OS_TASK_PTR )TASK_3, //任务函数
    97. (void * )0, //传递给任务函数的参数
    98. (OS_PRIO )TASK_3_PRIO, //任务优先级
    99. (CPU_STK * )&TASK_3_STK[0], //任务堆栈基地址
    100. (CPU_STK_SIZE)TASK_3_STK_SIZE/10, //任务堆栈深度限位
    101. (CPU_STK_SIZE)TASK_3_STK_SIZE, //任务堆栈大小
    102. (OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
    103. (OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度,
    104. (void * )0, //用户补充的存储区
    105. (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项
    106. (OS_ERR * )&err2_3); //存放该函数错误时的返回值
    107. OS_CRITICAL_EXIT();//退出临界区代码
    108. //任务一执行完函数之后删掉自身
    109. OSTaskDel((OS_TCB *)0,&err2_3);
    110. }
    111. void TASK_2(void *arg)
    112. {
    113. int num = 0;//任务2运行次数
    114. OS_ERR err2;
    115. while(1)
    116. {
    117. num++;
    118. if(num==10)
    119. {
    120. OSTaskDel((OS_TCB *)&TASK_3_TCB,&err2);
    121. printf("删除任务三\r\n");
    122. }
    123. printf("任务2运行次数:%d\r\n",num);
    124. OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err2);//延时1S
    125. }
    126. }
    127. void TASK_3(void *arg)
    128. {
    129. int num = 0;//任务2运行次数
    130. OS_ERR err3;
    131. while(1)
    132. {
    133. num++;
    134. printf("任务3运行次数:%d\r\n",num);
    135. OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err3);//延时500ms
    136. }
    137. }

     

      

  • 相关阅读:
    Java String之正则表达式
    springboot搭建微服务
    【Netty 从成神到升仙系列 四】让我们一起探索 Netty 中的零拷贝
    vsftp文件服务器的搭建与使用案例
    安装配置ingress-nginx支持https访问
    Asp.Net Core 7 preview 4 重磅新特性--限流中间件
    node-sass为什么一直安装不上、安装失败?
    【网络安全】beef-xss实操以及xss修复方案
    为什么从没有负值的数据中绘制的小提琴图(Violin Plot)会出现负值部分?
    UE5学习笔记(1)——从源码开始编译安装UE5
  • 原文地址:https://blog.csdn.net/ttdffmm/article/details/133760006