μC/OS-II临界区管理机制
OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()
同样是通过关中断来保护临界区,OS_ENTER_CRITICAL/OS_EXIT_CRITICAL一共实现了三种实现方式,如下所示:
#if OS_CRITICAL_METHOD == 1
#define OS_ENTER_CRITICAL() __asm__("cli")
#define OS_EXIT_CRITICAL() __asm__("sti")
#endif
#if OS_CRITICAL_METHOD == 2
#define OS_ENTER_CRITICAL() __asm__("pushf \n\t cli")
#define OS_EXIT_CRITICAL() __asm__("popf")
#endif
#if OS_CRITICAL_METHOD == 3
#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR())
#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr))
#endif
移植
一、 μC/OS-II的文件结构
第一种方式,OS_ENTER_CRITICAL()简单地关中断,OS_EXIT_CRITICAL()简单地开中断。这种方式虽然简单高效,但无法满足嵌套的情况。如果有两层临界区保护,在退出内层临界区时就会开中断,使外层的临界区也失去保护。虽然ucos的内核写的足够好,没有明显嵌套临界区的情况,但谁也无法保证一定没有,无法保证今后没有,无法保证在附加的驱动或什么位置没有,所以基本上第一种方法是没有人用的。ucos的系统函数中通常含会有一段代码进入临界状态,故使用这种方式非常不可靠。
第二种方式,先将中断状态保存到堆栈,再关中断;执行OS_EXIT_CRITICAL时,从堆栈中恢复原来的中断状态。缺点,当用户使用的处理器有堆栈指针相对寻址模式时,可能出现严重错误。
第三种方式,些编译器提供了扩展功能,用户可以得到当前处理器状态字的值,并将其保存在C函数局部变量之中。
相关临界代码如下
OS_CPU_SR cpu_sr
cpu_sr = get_processor_psw();//获取状态字
disable_interrupts();//关中断
set_processor_psw();//恢复状态字
文件结构
μC/OS-II提供有11或12个内核文件:
·<os_core.c>
·<os_flag.c>
·<os_mbox.c>
·<os_mem.c>
·<os_mutex.c>
·<os_q.c>
·<os_sem.c>
·<os_task.c>
·<os_time.c>
·<os_tmr.c>
·<ucos_ii.h>
·可能还有<ucos_ii.c>
注意到,在11或12个内核文件中,只有1个.H文件<ucos_ii.h>,在此头文件中,有
|
/* ********************************************************************************************************* * INCLUDE HEADER FILES ********************************************************************************************************* */
#include <app_cfg.h> #include <os_cfg.h> #include <os_cpu.h>
|
注意到,此处的三个头文件<app_cfg.h>、 <os_cfg.h>、 <os_cpu.h>在μC/OS-II官方都没有提供。
<app_cfg.h> :用户配置文件,旧版本用<includes.h>表示
<os_cfg.h> :用于对ucos-ii内核的裁剪。可以直接参考<os_cfg_r.h>文件,若没有,则可在工程模板中寻找,然后根据自己的徐秀
<os_cpu.h> :与CPU或编译平台相关的配置,如变量类型定义、进入临界状态的方式、任务调度的实现等。需用户自行建立,而有些cpu官方有提供模板。
μC/OS-II除了提供上面11或12个内核文件外,可能还提供了:
·<os_cfg_r.h>
作为<os_cfg.h>的参考,ucos-ii的配置头文件,如果没有提供,可以在ucos-ii的工程模板中寻找<os_cfg.h>文件;
·<os_dbg_r.c>
作为<os_dbg.h>的参考,ucos-ii的调试文件。
继续观察<ucos_ii.h>
|
/* ********************************************************************************************************* * FUNCTION PROTOTYPES * * IMPORTANT: These prototypes MUST be placed in OS_CPU.H ********************************************************************************************************* */
#if 0 void OSStartHighRdy (void); void OSIntCtxSw (void); void OSCtxSw (void); #endif
|
这3个函数要在<OS_CPU.H>中创建
二、 OS_CPU.H的编写
//////////////////////////////////////////////////////////
// OS_CPU.H文件的移植
//////////////////////////////////////////////////////////
OS_CPU.H 文件中包含与处理器相关的常量,宏和结构体的定义。
#ifdef OS_CPU_GLOBALS
#define OS_CPU_EXT //全局变量
#else
#define OS_CPU_EXT extern
#endif
/******************************************************************************
* 定义与编译器无关的数据类型
******************************************************************************/typedef unsigned char BOOLEAN;
typedef unsigned char INT8U; /* Unsigned 8 bit quantity */
typedef signed char INT8S; /* Signed 8 bit quantity */
typedef unsigned short INT16U; /* Unsigned 16 bit quantity */
typedef signed short INT16S; /* Signed 16 bit quantity */
typedef unsigned int INT32U; /* Unsigned 32 bit quantity */
typedef signed int INT32S; /* Signed 32 bit quantity */
typedef float FP32; /* Single precision floating point*/
typedef double FP64; /* Double precision floating point*/
//STM32是32位位宽的,这里OS_STK和OS_CPU_SR都应该为32位数据类型typedef unsigned int OS_STK; //定义堆栈的宽度,
typedef unsigned int OS_CPU_SR; //定义状态寄存器的宽度
//////////////////////////////////////////////////////////
下面的部分主要是为了和UC/OS 第一版的兼容
#define BYTE INT8S
#define UBYTE INT8U
#define WORD INT16S
#define UWORD INT16U
#define LONG INT32S
#define ULONG NT32U
//////////////////////////////////////////////////////////
/*
*******************************************************************************
* ARM Miscellaneous
*******************************************************************************
*/
//定义栈的增长方向.
//CM3中,栈是由高地址向低地址增长的,所以OS_STK_GROWTH设置为1
#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on ARM */
//任务切换宏,由汇编实现.
#define OS_TASK_SW() OSCtxSw()
/*
*******************************************************************************
* PROTOTYPES
* (see OS_CPU_A.ASM)
*******************************************************************************
*/
//OS_CRITICAL_METHOD = 1 :直接使用处理器的开关中断指令来实现宏
//OS_CRITICAL_METHOD = 2 :利用堆栈保存和恢复CPU的状态
//OS_CRITICAL_METHOD = 3 :利用编译器扩展功能获得程序状态字,保存在局部变量cpu_sr
#define OS_CRITICAL_METHOD 3 //进入临界段的方法
#if OS_CRITICAL_METHOD == 3
#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();}
#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);}
#endif
这篇博客详细介绍了μC/OS-II操作系统在不同CPU上的临界区管理机制,包括OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()的三种实现方式。同时,讲解了μC/OS-II的文件结构,特别是OS_CPU.H的编写,包括数据类型的定义和任务切换宏的配置,以及进入和退出临界区的方法。内容适合嵌入式开发者参考。
2474

被折叠的 条评论
为什么被折叠?



