【ucos-III教程】第11章 uCOS-III内核函数分析(上)

标签:
stm32f7ucos-iiiucguiemwindsp |
分类: uC0S-III |
1.
2.
3.
第11章
uCOS-III内核函数分析(上)
本期教程开始分析μCOS-III的内核函数,源码的分析采用先对源码进行注释,然后讲解函数实现的功能和相关的原理分析,最后是举一个例子(如果这个函数是供外部函数调用的)。内核函数很重要,是学习任务管理,任务间通信机制的基础。希望初学的同学认真学习,这部分应该算是μCOS-III的核心代码。
11.1 系统配置文件
11.2 源码文件
11.3 μCOS-III初始化
11.4 μCOS-III启动
11.5 获取系统版本
11.6 空闲任务
11.7 临界段
11.8 安全关键IEC61508
11.9 任务切换
11.10 调度锁
11.11 Round-Robin调度
11.12 总结
11.1
下面先简单说明下μCOS-III中几个配置文件的作用,方便分析源码的时候查看,配置文件主要有以下几个:
11.1.1
lib_cfg.h配置文件
lib_cfg.h文件内容如下:
#ifndef
#define
#define
#define
#define
#define
#endif
lib_cfg.h是用于给uC/LIB做配置的头文件。如果程序中使用uC/LIB的话,需要调用函数Mem_Init()进行初始化。
11.1.2
os_cfg.h配置文件
os_cfg.h文件中的内容如下:
#ifndef OS_CFG_H
#define OS_CFG_H
#define
OS_CFG_APP_HOOKS_EN
#define
OS_CFG_ARG_CHK_EN
#define
OS_CFG_CALLED_FROM_ISR_CHK_EN
#define
OS_CFG_DBG_EN
#define
OS_CFG_ISR_POST_DEFERRED_EN
#define
OS_CFG_OBJ_TYPE_CHK_EN
#define
OS_CFG_TS_EN
#define
OS_CFG_PEND_MULTI_EN
#define
OS_CFG_PRIO_MAX
#define
OS_CFG_SCHED_LOCK_TIME_MEAS_EN
#define
OS_CFG_SCHED_ROUND_ROBIN_EN
#define
OS_CFG_STK_SIZE_MIN
#define
OS_CFG_FLAG_EN
#define
OS_CFG_FLAG_DEL_EN
#define OS_CFG_FLAG_MODE_CLR_EN
1u
#define OS_CFG_FLAG_PEND_ABORT_EN 1u
#define
OS_CFG_MEM_EN
#define
OS_CFG_MUTEX_EN
#define
OS_CFG_MUTEX_DEL_EN
#define
OS_CFG_MUTEX_PEND_ABORT_EN
#define
OS_CFG_Q_EN
#define
OS_CFG_Q_DEL_EN
#define
OS_CFG_Q_FLUSH_EN
#define
OS_CFG_Q_PEND_ABORT_EN
#define
OS_CFG_SEM_EN
#define
OS_CFG_SEM_DEL_EN
#define
OS_CFG_SEM_PEND_ABORT_EN
#define
OS_CFG_SEM_SET_EN
#define
OS_CFG_STAT_TASK_EN
#define
OS_CFG_STAT_TASK_STK_CHK_EN
#define
OS_CFG_TASK_CHANGE_PRIO_EN
#define
OS_CFG_TASK_DEL_EN
#define
OS_CFG_TASK_Q_EN
#define
OS_CFG_TASK_Q_PEND_ABORT_EN
#define
OS_CFG_TASK_PROFILE_EN
#define
OS_CFG_TASK_REG_TBL_SIZE
#define
OS_CFG_TASK_SEM_PEND_ABORT_EN
#define
OS_CFG_TASK_SUSPEND_EN
#define
OS_CFG_TIME_DLY_HMSM_EN
#define
OS_CFG_TIME_DLY_RESUME_EN
#define
OS_CFG_TMR_EN
#define
OS_CFG_TMR_DEL_EN
#endif
这个配置文件比较的重要,主要用于μCOS-III源码中相关函数的配置。
11.1.3
os_cfg_app.h配置文件
os_cfg_app.h文件的内容如下:
#ifndef OS_CFG_APP_H
#define OS_CFG_APP_H
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#endif
这个文件主要是内核任务的配置,包括中断管理任务,空闲任务,统计任务,嘀嗒定时器任务已经定时器任务。
11.1.4
app_cfg.h配置文件
app_cfg.h文件夹中的内容如下:
#ifndef
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#endif
这个文件主要用于用户任务的配置。
11.1.5
cpu_cfg.h配置文件
cpu_cfg.h文件中的内容如下:
#ifndef
#define
#define
#define
#define
#define
#define
#if
0
#define
#endif
#define
#if
1
#define
#endif
#if
0
#define
#endif
#endif
这个文件里面主要是uC/CPU相关的配置。
11.2
μCOS-III中的源码主要包含如下文件:
上面截图中是μCOS-III相关的源码文件,后面的几期教程就是把这几个文件讲清楚。本期教程主要是讲解os_core文件中的相关函数。学期源码前还有看一下os_type.h文件中的内容(主要是变量的类型,这个一定得了解下):
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
11.3
下面开始讲解os_core.c文件中的函数,这个文件里面的函数比较多,为了方便大家更好的学习这个文件中的相关函数,这里对其进行了分类,先从μCOS-III的初始化开始讲解。
11.3.1
初始化
根据前面os_cfg.h文件中的配置,用户可以配置程序中需要执行的函数。μCOS-III的初始化函数OSInit()中涉及的全局变量和函数的初始化比较多,这里将其汇总一下,下面是全局变量的初始化:
全局变量 |
初始值 |
变量说明 |
OSIntNestingCtr |
0 |
中断嵌套的层数(0~250) |
OSRunning |
OS_STATE_OS_STOPPED |
系统是否开始运行标志 |
OSSchedLockNestingCtr |
0 |
调用了调度锁的嵌套层数 |
OSTCBCurPtr |
0 |
指向当前正在运行任务控制块指针 |
OSTCBHighRdyPtr |
0 |
指向最高优先级就绪任务控制块指针 |
OSPrioCur |
0 |
当前正在运行的任务优先级 |
OSPrioHighRdy |
0 |
具有最高优先级别的就绪任务的优先级 |
OSPrioSaved |
0 |
保存任务优先级 |
OSSchedLockTimeBegin |
0 |
使用调度锁起始时间 |
OSSchedLockTimeMax |
0 |
调度器被锁的最长时间 |
OSSchedLockTimeMaxCur |
0 |
当前调度器被锁的最长时间 |
OSSafetyCriticalStartFla |
DEF_FALSE |
系统安全关键开始标志 |
OSSchedRoundRobinEn |
DEF_FALSE |
使能Round-Robin调度 |
OSSchedRoundRobinDfltTim |
OSCfg_TickRate_Hz / 10u |
默认Round-Robin调度时间片大小 |
OS_AppTaskCreateHookPtr |
0 |
任务创建钩子函数指针 |
OS_AppTaskDelHookPtr |
0 |
任务删除钩子函数指针 |
OS_AppTaskReturnHookPtr |
0 |
任务返回钩子函数指针 |
OS_AppIdleTaskHookPtr |
0 |
空闲钩子函数指针 |
OS_AppStatTaskHookPtr |
0 |
启动任务钩子函数指针 |
OS_AppTaskSwHookPtr |
0 |
任务切换钩子函数指针 |
OS_AppTimeTickHookPtr |
0 |
滴答定时器钩子函数指针 |
OSTaskRegNextAvailID |
0 |
任务寄存器下一个有效ID |
11.3.2
初始化函数OSInit()
void
{
#ifdef
OS_SAFETY_CRITICAL
#endif
#if
OS_CFG_SCHED_LOCK_TIME_MEAS_EN >
0u
#endif
#ifdef
OS_SAFETY_CRITICAL_IEC61508
#endif
#if OS_CFG_SCHED_ROUND_ROBIN_EN
>
0u
#endif
#if OS_CFG_APP_HOOKS_EN >
0u
#endif
#if OS_CFG_TASK_REG_TBL_SIZE > 0u
#endif
#if OS_CFG_FLAG_EN >
0u
#endif
#if OS_CFG_MEM_EN >
0u
#endif
#if (OS_MSG_EN) >
0u
#endif
#if OS_CFG_MUTEX_EN >
0u
#endif
#if OS_CFG_Q_EN > 0u
#endif
#if OS_CFG_SEM_EN >
0u
#endif
#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
#endif
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
#endif
#endif
#if OS_CFG_TMR_EN >
0u
#endif
#endif
}
1.
2.
void
{
CPU_SR_ALLOC();
CPU_CRITICAL_ENTER();
OSIntNestingCtr++;
CPU_CRITICAL_EXIT();
//添加用户代码
OSIntExit();
}
也就是说进入中断后,先将OSIntNestingCtr加一,退出的时候再执行减一。为什么要这么做?为了说明这个问题,这里举一个例子,假如有低优先级中断A和高优先级中断B,A中断执行的时候,中断B抢占了A的执行,中断B执行完退出的时候会执行函数OSIntExit();(这个函数最主要的作用就是中断级任务切换)。可以想象,如果没有中断嵌套计数变量,退出高优先级中断B的时候运行函数OSIntExit();有可能会执行中断级任务切换,此时执行任务切换的话就会破换正常的寄存器入栈和出栈顺序,从而使得系统崩溃。其实进入Cortex-M3/M4时代已经不存在这个问题了,因为我们设置PendSV中断为最低的优先级(任务切换是在PendSV中断里面执行的),PendSV中断会在所有其它高优先级中断执行完后才会得到执行。
为了使得μCOS-III可以适应各种处理器内核和复杂的系统设置,中断嵌套计数还是很有必要的。
3.
4.
5.
OSSchedRoundRobinDfltTim
是用于配置时间片的,默认时间片调度是关闭的,时间片大小是OSCfg_TickRate_Hz / 10u。这两个
关于时间片的配置变量大家一定要记住。
6.
函数中还有有很多其它的初始化,我们会在后面再跟大家详细的讲述。
11.4
μCOS-III启动
11.4.1
启动
不像其它RTOS,μCOS-III有一个标准的初始化过程,所以特别建议初学的同学按照这个过程进行初始化,如果不按照这个过程进行初始化,往往会出现莫名其妙的后果,标准的初始化流程如下:
int main(void)
{
OSTaskCreate((OS_TCB
}
static
{
OS_ERR
#if OS_CFG_STAT_TASK_EN > 0u
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN
#endif
}
11.4.2
启动函数OSStart ()
void
{
#ifdef
OS_SAFETY_CRITICAL
#endif
}
1.
2.
3.
4.
5.
6.
7.
8.
11.5
有时候我们需要获取系统的版本号,下面就是系统版本的获取函数。这个函数比较简单,特别注意函数注释。
CPU_INT16U
{
#ifdef OS_SAFETY_CRITICAL
#endif
}