【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.6
几乎所有的小型RTOS中都会有一个空闲任务,空闲任务应该属于系统任务,是必须要执行的,用户程序不能将其关闭。不光小型系统中有空闲任务,大型的系统里面也有的,比如XP,下面的截图就是XP中的空闲进程。
空闲任务主要有以下几个作用:
l
l
11.6.1 创建空闲任务OS_IdleTaskInit
()
void
{
#ifdef OS_SAFETY_CRITICAL
#endif
}
关于任务的创建,本期教程暂时还不做介绍。
11.6.2 空闲任务OS_IdleTask
()
void
{
#if OS_CFG_STAT_TASK_EN > 0u
#endif
}
1.
#define
这个是临界代码段,在下面一个小节有详细讲解。
2.
3.
宏定义 |
数值 |
DEF_FALSE |
0u |
DEF_TRUE |
1u |
DEF_NO |
0u |
DEF_YES |
1u |
DEF_DISABLED |
0u |
DEF_ENABLED |
1u |
DEF_INACTIVE |
0u |
DEF_ACTIVE |
1u |
DEF_INVALID |
0u |
DEF_VALID |
1u |
DEF_OFF |
0u |
DEF_ON |
1u |
DEF_CLR |
0u |
DEF_SET |
1u |
DEF_FAIL |
0u |
DEF_OK |
1u |
4.
5.
6. 用户可以在钩子函数中加入待机,休眠等低功耗操作。
11.7
临界段
11.7.1
临界段基本概念
代码的临界段也称为临界区,指处理时不可分割的代码。一旦这部分代码开始执行,则不允许任何中断打入。为确保临界段代码的执行,在进入临界段之前要关中断,而临界段代码执行完以后要立即开中断。
从代码上来看,处在关中断和开中断之间的代码段就是临界段。
由于各厂商的CPU和C编译器的关中断和开中断的方法以及指令不尽相同,为增强μCOS-III的可移植性(即在μCOS-III的各个C语言函数中尽可能地不出现汇编语言代码),μCOS-III用CPU_INT_DIS()和CPU_INT_EN()这两个宏封装了与系统硬件相关的关中断和开中断指令。
另外,不要在临界段中调用μCOS-III提供的功能函数,防止系统崩溃。
11.7.2
临界段相关的宏定义
CPU_INT_DIS()和CPU_INT_EN()可以以下四种不同的实现方法。
#define
#define
#define
#define
#define
typedef
#if
#define
#else
#define
#endif
#define
#define
#ifdef
#define
CPU_IntDisMeasStart();
}
#define
CPU_INT_EN();
#else
#define
#define
#endif
1.
这种方式最简单,即直接使用处理器的开中断和关中断指令来实现宏。但是不推荐使用这种方式,因为不支持中断嵌套,但是考虑到有些处理器或者编译器仅支持这种方式,不得不选择这种方式。
2.
这种方法稍复杂些,但可使CPU中断使能标志的状态在临界段前和临界段后不发生变化。
进入临界段前:
退出临界段:
3.
这种方法的前提是,用户使用的C编译器具有扩展功能。用户可获得程序状态字的值,这样就可把该值保存在C函数的局部变量中,而不必压到堆栈里。上面的宏定义就是采用的这种方式,也就是(1),(2)注释的地方。
4.
#if
#define
#else
#define
#endif
#if
#define
#else
#define
#endif
#if OS_CFG_ISR_POST_DEFERRED_EN
>
0u
#define
#define
#define
#define
#else
#define
#define
#define
#define
#endif
11.8
关于IEC61508,大家有个了解即可,更详细的资料可以查阅wiki百科进行了解或者查找相关的文档说明。
11.8.1
IEC61508基本概念
IEC 61508是一项用于工业领域的国际标准,其名称是《电气/电子/可编程电子安全相关系统的功能安全》。由国际电工委员会发布,其目的要建立一个可应用于各种工业领域的基本功能安全标准。它将功能安全定义为:“是受控设备(EUC)或受控设备系统总体安全中的一部分;其安全性是依赖于电气/电子/可编程电子(E/E/PE)安全相关系统、其他技术的安全相关系统或外部风险降低措施的正确机能。”
(一) IEC61508中的基本定义
1.
针对规定的危险事件,为达到或保持受控设备(EUC)的安全状态,由E/E/PE安全系统、其他技术安全系统或外部风险降低设施实现的功能。
2.
在规定的条件下、规定的时间内,安全系统成功实现所要求的安全功能的概率。这一定义着重于安全系统执行安全功能的可靠性。在确定安全完整性过程中,应包括所有导致非安全状态的因素,如随机的硬件失效,软件导致的失效以及由电气干扰引起的失效,这些失效的类型,尤其是硬件失效可用测量方法来定量,如在危险模式中的失效和系统失效率,或按规定操作的安全防护系统失效的概率。但是,系统的安全完整性还取决于许多因素,这些因素无法精确定量,仅可定性考虑。
3.
基于电气/电子和可编程电子装置的用于控制、防护或监视的系统,包括系统中所有的元素如电源、传感器、所有其他输入输出装置及所有通信手段。
4.
5. 可接受凤险 (ACCeptable risk)
风险指的是出现伤害的概率及该伤害严重性的组合。可接受风险指根据当今社会的水准所能够接受的风险。
6.
不存在不可接受的风险。
7.
是用于两个目的:一是执行要求的安全功能以达到或保持EUC的安全状态;二是自身或与其他E/E/PES安全系统、其他技术安全系统或外部风险降低设施一道,对于要求的安全功能达到必要的安全完整性。安全系统是在接受命令后采取适当的动作以防止EUC进入危险状态。安全系统的失效应被包括在导致确定的危险事件中。尽管可能有其他系统具备安全功能,但仅是指用其自身能力达到要求的允许风险的安全系统。安全系统可大致分为安全控制系统和安全防护系统。
安全系统可以是EUC控制系统的组成部分,也可用传感器和/或执行器与EUC的接口,既可用在EUC控制系统中执行安全功能的方式达到要求的安全完整性水平,也可用分离的/独立的专门用于安全的系统执行安全功能。
(二)IEC61508的基本概念
IEC61508标准规定随机失效的后果必须定量评估,使用随机存取测量系统 (RAMS)方法计算有效性。量化与故障相关的系统失效是没有用的,应当通过组织指导来避免系统失效,或通过技术措施来控制。
1.风险和安全完整性慨念
2.功能安全保证的内容
功能安全保证主要包括两部分内容:失效识别和安全完整性水平。
(1)失效识别。
失效就是功能单元失去实现其功能的能力。一些功能是根据所达到的行为进行规定的,在执行功能时,某些特定的行为是不允许的,这些行为的出现就是失效。失效可能是随机失效,这种失效通常由于硬件装置的耗损所致。也可能是系统失效,这在硬件和软件中都可能出现。失效识别就是要分辨出不同部件的各种失效原因,估算出系统失效概率。
(2)安全完整性水平 (SIL) (safety integrity level)。
一种离散的水平,用于规定分配给E/E/PE安全系统的安全功能的安全完整性要求,安全系统的安全完整性水平越高,安全系统实现所要求的安全功能失败的可能性就越低。IEC61508中规定系统有4种安全完整性水平,SIL4是最高的,安全完整性水平1是最低的。
11.8.2
启动安全关键OSSafetyCriticalStart
源码中加入了部分安全关键的代码,内容如下:
#ifdef OS_SAFETY_CRITICAL_IEC61508
void
{
}
#endif
1.
#ifdef OS_SAFETY_CRITICAL_IEC61508
#endif
11.8.3
函数使用举例
void AppStartTask(void *p_arg)
{
}
}
11.9
如果大家认真学习了前面几期教程,μCOS-III中的任务切换还是很好理解的。μCOS-III中的任务切换主要分为两部分,一个是中断级任务切换,另一个是任务级中断切换。
11.9.1
任务级任务切换OSSched()
任务级的任务切换主要通过下面的函数实现:
void
{
#if OS_CFG_TASK_PROFILE_EN > 0u
#endif
#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
#endif
}
1.
2.
3.
4.
5.
6.
11.9.2
中断级任务切换OSIntExit()
中断级任务切换是由中断函数调用的,内容如下:
void
{
}
void
{
#if OS_CFG_TASK_PROFILE_EN > 0u
#endif
#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
#endif
}
1.
2.
3.
4.
11.9.3
函数使用举例
函数OSSched ()不是供用户调用的,而函数OSIntEnter() 和 OSIntExit()是供用户在中断任务中调用的,下面举个例子:
void SDIO_IRQHandler(void)
{
}