任务创建 app.c代码讲解
任务创建步骤
1、定义任务控制块
第一步我们需要在app.c中为任务定义一个任务控制块,通常我们称这个任务控制块为任务的身份证。在 C 中上,任务控制块就是一个结构体,里面有非常多的成员,这些成员共同描述了任务的全部信息。
/*
*********************************************************************************************************
* TCB(任务控制块)
*********************************************************************************************************
*/
static OS_TCB AppTaskStartTCB;//声明起始任务块
/*声明用户自定义任务块*/
static OS_TCB AppTaskLed1TCB;
static OS_TCB AppTaskLed2TCB;
2、定义任务栈
任务的栈占用的是MCU 内部的 RAM,当任务越多的时候,需要使用的栈空间就越大,即需要使用的 RAM空间就越多。一个 MCU 能够支持多少任务,就得看你的 RAM 空间有多少。任务堆栈大小单位:如果 CPU_STK 被设置为CPU_INT08U,则单位为字节,而如果 CPU_STK 被设置为 CPU_INT16U,则单位为半字,同理,如果CPU_STK 被设置为 CPU_INT32U,单位为字。在 32 位的处理器下(STM32),一个字等于 4 个字节,那么任务大小就为 APP_TASK_START_STK_SIZE * 4 字节。代码如下:
例:AppTaskStart 任务和AppTaskLed1 任务以及AppTaskLed12任务
app_cfg.h
/*
*********************************************************************************************************
* 任务堆栈大小
*********************************************************************************************************
*/
#define APP_TASK_START_STK_SIZE 128
#define APP_TASK_LED1_STK_SIZE 512
#define APP_TASK_LED2_STK_SIZE 512
app.c:
/*
*********************************************************************************************************
* STACKS(堆栈)
*********************************************************************************************************
*/
static CPU_STK AppTaskStartStk[APP_TASK_START_STK_SIZE]; //声明起始任务的堆栈
/*声明相关的任务堆栈*/
static CPU_STK AppTaskLed1Stk[APP_TASK_LED1_STK_SIZE];
static CPU_STK AppTaskLed2Stk[APP_TASK_LED2_STK_SIZE];
3、定义任务主体函数
任务实际上就是一个无限循环且不带返回值的 C 函数。目前,我们可以如下格式创建一个这样的任务。
任务主体代码格式:
static void AppTaskLed1(void * p_arg)
{
OS_ERR err;
(void)p_arg;
while (DEF_TRUE) { //任务的具体内容,通常写在无限循环里面
}
}
例程代码如下:
app.c中:
/*
*********************************************************************************************************
* 函数声明
*********************************************************************************************************
*/
static void AppTaskStart (void *p_arg);
static void AppTaskLed1 (void *p_arg);
static void AppTaskLed2 (void *p_arg);
void main()
{
}
static void AppTaskLed1(void * p_arg) //LED1 2.5s翻转一次
{
OS_ERR err;
(void)p_arg;
while (DEF_TRUE) { //任务的具体内容,通常写在无限循环里面
LED1_TOGGLE;
OSTimeDly ( 2500, OS_OPT_TIME_DLY, & err );
}
}
static void AppTaskLed2(void * p_arg) //LED2 5s翻转一次
{
OS_ERR err;
(void)p_arg;
while (DEF_TRUE) { //任务的具体内容,通常写在无限循环里面
LED2_TOGGLE;
OSTimeDly ( 5000, OS_OPT_TIME_DLY, & err );
}
}
4、定义任务优先级
app_cfg.h:
/*
*********************************************************************************************************
* TASK PRIORITIES 任务优先级
*********************************************************************************************************
*/
#define APP_TASK_START_PRIO 2
#define APP_TASK_LED1_PRIO 3
#define APP_TASK_LED2_PRIO 3
5、创建任务
uCOS 里面中通过任务创建函数 OSTaskCreate()将是任务主体函数,任务栈,任务控制块这三个要素联合在一起。让任务在创建之后可以随时被系统启动与调度。
app.c
/*创建启动任务*/
OSTaskCreate((OS_TCB *)&AppTaskStartTCB, //任务控制块
(CPU_CHAR *)"App Task Start", //任务名字 最好和任务入口函数名称一样
(OS_TASK_PTR ) AppTaskStart, //任务入口函数
/* 任务入口函数形参,不用的时候配置为 0 或者 NULL 即可,p_arg是指向可选数据区域的指针,用于将参数传递给任务,因为任务一旦执行,那必须是在一个死循环中,所以传参只在首次执行时有效。*/
(void *) 0,
(OS_PRIO ) APP_TASK_START_PRIO, //任务的优先级
(CPU_STK *)&AppTaskStartStk[0], //指向堆栈基址的指针(即堆栈的起始地址)
(CPU_STK_SIZE) APP_TASK_START_STK_SIZE / 10, //设置堆栈深度的限制位置
(CPU_STK_SIZE) APP_TASK_START_STK_SIZE, //任务堆栈大小
(OS_MSG_QTY ) 5u, //设置可以发送到任务的最大消息数,按需设置即可
(OS_TICK ) 0u, //在任务之间循环时的时间片的时间量(以滴答为单位)指定 0则使用默认值。
(void *) 0, //是指向用户提供的内存位置的指针,用作 TCB 扩展
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), //用户可选的任务特定选项
(OS_ERR *)&err); //用于保存返回的错误代码
用户可选的任务特定选项,具体见代码详情如下:
#define OS_OPT_TASK_NONE (OS_OPT)(0x0000u) //未选择任何选项
#define OS_OPT_TASK_STK_CHK (OS_OPT)(0x0001u) //启用任务的堆栈检查
#define OS_OPT_TASK_STK_CLR (OS_OPT)(0x0002u) //任务创建时清除堆栈
#define OS_OPT_TASK_SAVE_FP (OS_OPT)(0x0004u) //保存任何浮点寄存器的内容,这需要 CPU 硬件的支持
#define OS_OPT_TASK_NO_TLS (OS_OPT)(0x0008u) //指定任务不需要 TLS 支持
通过 AppTaskStart ()任务创建任务
为了方便管理,用户自定义任务均在 AppTaskStart ( )中创建,main( )中只创建AppTaskStart()任务。AppTaskStart()代码如下:
app.c
static void AppTaskStart (void *p_arg)
{
CPU_INT32U cpu_clk_freq;
CPU_INT32U cnts;
OS_ERR err;
(void)p_arg;
BSP_Init(); //初始化函数
CPU_Init(); //初始化UCOS
cpu_clk_freq = BSP_CPU_ClkFreq(); //定义SysTick系统定时器的参照频率
cnts = cpu_clk_freq / (CPU_INT32U)OSCfg_TickRate_Hz; //定义 Systick 增量
OS_CPU_SysTickInit(cnts); // 初始化系统时钟周期
Mem_Init(); //初始化内存管理模块
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err); //计算CPU容量,不运行任何任务
#endif
CPU_IntDisMeasMaxCurReset();
OSTaskCreate((OS_TCB *)&AppTaskLed1TCB, //创建LED1任务
(CPU_CHAR *)"App Task Led1",
(OS_TASK_PTR ) AppTaskLed1,
(void *) 0,
(OS_PRIO ) APP_TASK_LED1_PRIO,
(CPU_STK *)&AppTaskLed1Stk[0],
(CPU_STK_SIZE) APP_TASK_LED1_STK_SIZE / 10,
(CPU_STK_SIZE) APP_TASK_LED1_STK_SIZE,
(OS_MSG_QTY ) 5u,
(OS_TICK ) 0u,
(void *) 0,
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
(OS_ERR *)&err);
OSTaskCreate((OS_TCB *)&AppTaskLed2TCB, // 创建LED2任务
(CPU_CHAR *)"App Task Led2",
(OS_TASK_PTR ) AppTaskLed2,
(void *) 0,
(OS_PRIO ) APP_TASK_LED2_PRIO,
(CPU_STK *)&AppTaskLed2Stk[0],
(CPU_STK_SIZE) APP_TASK_LED2_STK_SIZE / 10,
(CPU_STK_SIZE) APP_TASK_LED2_STK_SIZE,
(OS_MSG_QTY ) 5u,
(OS_TICK ) 0u,
(void *) 0,
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
(OS_ERR *)&err);
OSTaskDel(&AppTaskStartTCB ,& err );
}
二、app.c与app_cfg.h 相关代码
app_cfg.h(部分)
/*
*********************************************************************************************************
* 任务优先级
*********************************************************************************************************
*/
#define APP_TASK_START_PRIO 2
#define APP_TASK_LED1_PRIO 3
#define APP_TASK_LED2_PRIO 3
/*
*********************************************************************************************************
* 任务堆栈大小
*********************************************************************************************************
*/
#define APP_TASK_START_STK_SIZE 128
#define APP_TASK_LED1_STK_SIZE 512
#define APP_TASK_LED2_STK_SIZE 512
app.c(全部)
#include <includes.h>
/*
*********************************************************************************************************
* TCB(任务控制块)
*********************************************************************************************************
*/
static OS_TCB AppTaskStartTCB;
static OS_TCB AppTaskLed1TCB;
static OS_TCB AppTaskLed2TCB;
/*
*********************************************************************************************************
* STACKS(堆栈)
*********************************************************************************************************
*/
static CPU_STK AppTaskStartStk[APP_TASK_START_STK_SIZE]; //声明起始任务的堆栈
/*声明相关的任务堆栈*/
static CPU_STK AppTaskLed1Stk[APP_TASK_LED1_STK_SIZE];
static CPU_STK AppTaskLed2Stk[APP_TASK_LED2_STK_SIZE];
static void AppTaskStart (void *p_arg);
static void AppTaskLed1 (void *p_arg);
static void AppTaskLed2 (void *p_arg);
int main (void)
{
OS_ERR err;
OSInit(&err);
OSTaskCreate((OS_TCB *)&AppTaskStartTCB,
(CPU_CHAR *)"App Task Start",
(OS_TASK_PTR ) AppTaskStart,
(void *) 0,
(OS_PRIO ) APP_TASK_START_PRIO,
(CPU_STK *)&AppTaskStartStk[0],
(CPU_STK_SIZE) APP_TASK_START_STK_SIZE / 10,
(CPU_STK_SIZE) APP_TASK_START_STK_SIZE,
(OS_MSG_QTY ) 5u,
(OS_TICK ) 0u,
(void *) 0,
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
(OS_ERR *)&err);
OSStart(&err);
}
static void AppTaskStart (void *p_arg)
{
CPU_INT32U cpu_clk_freq;
CPU_INT32U cnts;
OS_ERR err;
(void)p_arg;
BSP_Init();
CPU_Init();
cpu_clk_freq = BSP_CPU_ClkFreq();
cnts = cpu_clk_freq / (CPU_INT32U)OSCfg_TickRate_Hz;
OS_CPU_SysTickInit(cnts);
Mem_Init();
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err);
#endif
CPU_IntDisMeasMaxCurReset();
OSTaskCreate((OS_TCB *)&AppTaskLed1TCB,
(CPU_CHAR *)"App Task Led1",
(OS_TASK_PTR ) AppTaskLed1,
(void *) 0,
(OS_PRIO ) APP_TASK_LED1_PRIO,
(CPU_STK *)&AppTaskLed1Stk[0],
(CPU_STK_SIZE) APP_TASK_LED1_STK_SIZE / 10,
(CPU_STK_SIZE) APP_TASK_LED1_STK_SIZE,
(OS_MSG_QTY ) 5u,
(OS_TICK ) 0u,
(void *) 0,
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
(OS_ERR *)&err);
OSTaskCreate((OS_TCB *)&AppTaskLed2TCB,
(CPU_CHAR *)"App Task Led2",
(OS_TASK_PTR ) AppTaskLed2,
(void *) 0,
(OS_PRIO ) APP_TASK_LED2_PRIO,
(CPU_STK *)&AppTaskLed2Stk[0],
(CPU_STK_SIZE) APP_TASK_LED2_STK_SIZE / 10,
(CPU_STK_SIZE) APP_TASK_LED2_STK_SIZE,
(OS_MSG_QTY ) 5u,
(OS_TICK ) 0u,
(void *) 0,
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
(OS_ERR *)&err);
OSTaskDel(&AppTaskStartTCB ,& err );
}
static void AppTaskLed1(void * p_arg)
{
OS_ERR err;
(void)p_arg;
while (DEF_TRUE) { //任务的具体内容,通常写在无限循环里面
LED1_TOGGLE;
OSTimeDly ( 2500, OS_OPT_TIME_DLY, & err );
}
}
static void AppTaskLed2(void * p_arg)
{
OS_ERR err;
(void)p_arg;
while (DEF_TRUE) { //任务的具体内容,通常写在无限循环里面
LED2_TOGGLE;
OSTimeDly ( 5000, OS_OPT_TIME_DLY, & err );
}
}