UCOS III 系统内部任务

在 UCOSII 中有两个系统任务:统计任务和空闲任务,在但是UCOSIII中系统内部任务扩展到了 。

空闲任务、时钟节拍任务、统计任务定时任务中断服务管理任务钩子函数 。


1.空闲任务:

OS_IdleTask(),在os_core.c 文件中定义。
调用 OS_Init()初始化UCOS 的时候就会被创建。在 OS_Init() 中 调 用 了 函 数OS_IdleTaskInit() 
void OS_IdleTaskInit (OS_ERR *p_err)
{
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
OSIdleTaskCtr = (OS_IDLE_CTR)0; 
(1)
OSTaskCreate((OS_TCB * )&OSIdleTaskTCB,
(CPU_CHAR * )((void *)"uC/OS-III Idle Task"),
(OS_TASK_PTR )OS_IdleTask,
(void * )0,
(OS_PRIO )(OS_CFG_PRIO_MAX - 1u),
(CPU_STK * )OSCfg_IdleTaskStkBasePtr,
(CPU_STK_SIZE )OSCfg_IdleTaskStkLimit,
(CPU_STK_SIZE )OSCfg_IdleTaskStkSize,
(OS_MSG_QTY )0u,
(OS_TICK )0u,
(void * )0,
(OS_OPT )(OS_OPT_TASK_STK_CHK | \
OS_OPT_TASK_STK_CLR | OS_OPT_TASK_NO_TLS),
(OS_ERR * )p_err);
}
 
任 务 优 先 级 为 OS_CFG_PRIO_MAX – 1OS_CFG_PRIO_MAX 是一个宏,在文件 os_cfg.h 中定义,OS_CFG_PRIO_MAX 定义了 UCOSIII可用的任务数。 

默认情况下  OS_CFG_PRIO_MAX 为  64 。空闲任务优先级为 OS_CFG_PRIO_MAX-1 ,说明空闲任务的优先级为最低的。
空闲任务堆栈大小为 
OSCfg_IdleTaskStkSize OSCfg_IdleTaskStkSize  也是一个宏,在 os_cfg_app.c 文件中定义,默认为  128 ,则空闲任务堆栈默认为 128*4=512  字节。

空闲任务的任务函数为任务函数为  OS_IdleTask() OS_IdleTask() 函数代码如下:

void OS_IdleTask (void *p_arg)
{
CPU_SR_ALLOC();
p_arg = p_arg;
while (DEF_ON) {
CPU_CRITICAL_ENTER(); 
(1)
OSIdleTaskCtr++;  (2)
#if OS_CFG_STAT_TASK_EN > 0u  (3)
OSStatTaskCtr++;  (4)
#endif
CPU_CRITICAL_EXIT(); 
(5)
OSIdleTaskHook();  (6)
}
}
(1)
(5) 、临界段代码保护
(2) 、  OSIdleTaskCtr 加一,每进入一次空闲任务,  OSIdleTaskCtr 就加一。我们可以通过查看  OSIdleTaskCtr 变量的递增速度来判断  CPU  执行应用任务的繁忙程度,如果递增的快的话说明应用任务花费时间少,很快就执行完了。
(3) 、宏  OS_CFG_STAT_TASK_EN 大于  说明开启了统计任务。
(4) 、  OSStatTaskCtr 默认也是一个  32  位的无符号整形变量,在文件  os.h  中定义。这里将 OSStatTaskCtr 加一,统计任务中用到  OSStatTaskCtr ,用来统计 CPU  的使用率。
(6) 、  OSIdleTaskHook() 叫做钩子函数,我们可以在钩子函数中干一些其他的事情。  


2.时钟节拍任务 
OS_Ticktask(),在 OS_Init()中调用了一个函数OS_TickTaskInit(),函数代码如下: 

void OS_TickTaskInit (OS_ERR *p_err)
{
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
OSTickCtr = (OS_TICK)0u;
OSTickTaskTimeMax = (CPU_TS)0u;
 

OS_TickListInit();
if (OSCfg_TickTaskStkBasePtr == (CPU_STK *)0) {
*p_err = OS_ERR_TICK_STK_INVALID;
return;
}
if (OSCfg_TickTaskStkSize < OSCfg_StkSizeMin) {
*p_err = OS_ERR_TICK_STK_SIZE_INVALID;
return;
}
if (OSCfg_TickTaskPrio >= (OS_CFG_PRIO_MAX - 1u)) {
*p_err = OS_ERR_TICK_PRIO_INVALID;
return;
}
OSTaskCreate((OS_TCB * )&OSTickTaskTCB,
(CPU_CHAR* )((void *)"uC/OS-III Tick Task"),
(OS_TASK_PTR )OS_TickTask,
(void* )0,
(OS_PRIO )OSCfg_TickTaskPrio,
(CPU_STK* )OSCfg_TickTaskStkBasePtr,
(CPU_STK_SIZE )OSCfg_TickTaskStkLimit,
(CPU_STK_SIZE )OSCfg_TickTaskStkSize,
(OS_MSG_QTY )0u,
(OS_TICK )0u,
(void* )0,
(OS_OPT )(OS_OPT_TASK_STK_CHK |\
OS_OPT_TASK_STK_CLR | OS_OPT_TASK_NO_TLS),
(OS_ERR *)p_err);
}
 
时钟节拍任务的优先级尽可能的高一点  , 时钟节拍任务的作用是跟踪正在延时的任务,以及在指定时间内等待某个内核对象的任务, OS_TickTask() 任务函数代码如下:  

void OS_TickTask (void *p_arg)
{
OS_ERR err;
CPU_TS ts;
 
p_arg = p_arg;
while (DEF_ON) {
(void)OSTaskSemPend((OS_TICK )0, 
(1)
(OS_OPT )OS_OPT_PEND_BLOCKING,
(CPU_TS * )&ts,
(OS_ERR * )&err);
if (err == OS_ERR_NONE) {
if (OSRunning == OS_STATE_OS_RUNNING) {
OS_TickListUpdate(); 
(2)
}
}
}
}
 
(1) 、请求信号量,  OSTaskSemPend() 是请求任务内建信号量的,信号量会在  OSTimeTick() 中  POST ,这里的信号量是用来做任务同步的 。 OSTimeTick() 会在滴答定时器中断服务函数中调用。 
(2) 、信号量请求成功的话就调用函数  OS_TickListUpdate() 函数。
时钟节拍列表是由一个数据表 OSCfg_TickWheel(在 os_cfg_app.c 中定义)和一个计数器
OSTickCtr 组 成 , 表 OSCfg_TickWheel 是 一 个 数 组 , 数 组 元 素 个 数 由 宏OS_CFG_TICK_WHEEL_SIZE 定义,宏 OS_CFG_TICK_WHEEL_SIZE 在 os_cfg_app.h 中定义了。表 OSCfg_TickWheel 中的元素为 os_tick_spoke 类型的, os_tick_spoke 是一个结构体,结构体定义如下:
struct os_tick_spoke {
OS_TCB *FirstPtr;
OS_OBJ_QTY NbrEntries;
OS_OBJ_QTY NbrEntriesMax;
};
FirstPtr: 指针变量,在表头上并属于该表。
NbrEntries: 表示在该表项上等待的任务的数目。
NbrEntriesMax: 表示在该表项上等待的任务的最大数目。
在使用时钟节拍列表时需要先初始化时钟节拍列表,在 
OS_TickTaskInit()函数中会调用OS_TickListInit 来初始化时钟节拍列表 。


3.统计任务 
在  UCOSIII  中统计任务可用来统计  CPU  的使用率、各个任务的  CPU  使用率和各任务的堆栈使用情况,默认情况下统计任务是不会创建的,如果要使能统计任务的话需要将宏
OS_CFG_STAT_TASK_EN  置  1 ,宏  OS_CFG_STAT_TASK_EN  在  os_cfg.h  文件中有定义。 

OS_StatTaskInit() 函 数 用 来 创 建 统 计 任 务 , 统 计 任 务 的 优 先 级 通 过 宏OS_CFG_STAT_TASK_PRIO 设 置  。

如果要使用统计任务的话就需要在 main()函数创建的第一个也是唯一一个应用任务中调用OSStatTaskCPUUsageInit()函数。 

#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err); // 统计任务
#endif 
创建其他任务只能在
OSStatTaskCPUUsageInit() 函数之后。 CPU  的总的使用率会保存在变量  OSStatTaskCPUUsage  中,我们可以通过读取这个值来获取  CPU  的使用率。 

V3.03.00 版本起, CPU 的使用率 0~10000  之间的整数 。 在这之前的版本 ,CPU  使用率是  0~100  之间的整数表示。 

4. 定时任务 
UCOSIII  提供软件定时器功能,定时任务是可选的,将宏  OS_CFG_TMR_EN  设置为  就会使能定时任务,在  OSInit() 中将会调用函数  OS_TmrInit() 来创建定时任务。定时任务的优先级通过宏  OS_CFG_TMR_TASK_PRIO  定义。

5. 中断服务管理任务 
当把  os_cfg.h  文件中的宏  OS_CFG_ISR_POST_DEFERRED_EN  置  就会使能中断服务管理任务,  UCOSIII  会创建一个名为  OS_IntQTask() 的任务,该任务负责“延迟”在  ISR  中调用的系统  post  服务函数的行为。中断服务管理任务的任务优先级永远是最高的,为  0  

当  ISR( 中断服务函数 ) 调用  UCOSIII  提供的“  post ”函数时,要发送的数据和发送的目的地都会存入一个特别的缓冲队列中,当所有嵌套的  ISR  都执行完成以后  UCOSIII  会做任务切换,运行中断服务管理任务,该任务会把缓存队列中存放的信息重发给相应的任务。这样做的好处就是可以减少中断关闭的时间,否则,在  ISR  中还需要把任务从等待列表中删除,并把任务放入就绪表,以及做一些其他的耗时操作。

猜你喜欢

转载自blog.csdn.net/qq_38220557/article/details/80061248
今日推荐