⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_cpu.h

📁 ucos注解版 内容大都是从邵贝贝和网上摘取的 有参考价值
💻 H
字号:
/*
*********************************************************************************************************
*                                               uC/OS-II
*                                        The Real-Time Kernel
*
*                         (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL
*                                          All Rights Reserved
*
*                                       80x86/80x88 Specific code
*                                          LARGE MEMORY MODEL
*
*                                          Borland C/C++ V4.51
*
* File         : OS_CPU.H
* By           : Jean J. Labrosse
*********************************************************************************************************
*/

#ifdef  OS_CPU_GLOBALS
#define OS_CPU_EXT
#else
#define OS_CPU_EXT  extern
#endif

/*
*********************************************************************************************************
*                                              DATA TYPES
*                                         (Compiler Specific)
*********************************************************************************************************
*/

typedef unsigned char  BOOLEAN;
typedef unsigned char  INT8U;                    /* Unsigned  8 bit quantity                           */
typedef signed   char  INT8S;                    /* Signed    8 bit quantity                           */
typedef unsigned int   INT16U;                   /* Unsigned 16 bit quantity                           */
typedef signed   int   INT16S;                   /* Signed   16 bit quantity                           */
typedef unsigned long  INT32U;                   /* Unsigned 32 bit quantity                           */
typedef signed   long  INT32S;                   /* Signed   32 bit quantity                           */
typedef float          FP32;                     /* Single precision floating point                    */
typedef double         FP64;                     /* Double precision floating point                    */

typedef unsigned int   OS_STK;                   /* Each stack entry is 16-bit wide                    */
typedef unsigned short OS_CPU_SR;                /* Define size of CPU status register (PSW = 16 bits) */

#define BYTE           INT8S                     /* Define data types for backward compatibility ...   */
#define UBYTE          INT8U                     /* ... to uC/OS V1.xx.  Not actually needed for ...   */
#define WORD           INT16S                    /* ... uC/OS-II.                                      */
#define UWORD          INT16U
#define LONG           INT32S
#define ULONG          INT32U

/* 
*********************************************************************************************************
*                              Intel 80x86 (Real-Mode, Large Model)
*
* Method #1:  Disable/Enable interrupts using simple instructions.  After critical section, interrupts
*             will be enabled even if they were disabled before entering the critical section.
*
* Method #2:  Disable/Enable interrupts by preserving the state of interrupts.  In other words, if 
*             interrupts were disabled before entering the critical section, they will be disabled when
*             leaving the critical section.
*
* Method #3:  Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
*             would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
*             disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to 
*             disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
*             into the CPU's status register.
*********************************************************************************************************
*/
#define  OS_CRITICAL_METHOD    2

#if      OS_CRITICAL_METHOD == 1                          /*第一种方法是以最简单的方式来实现这2个宏调用的:用
处理器指令关中断,然而这种方法有点小问题,如果调用UCOS的功能函数时,中断是关掉的,则从UCOS的函数返回时,中断
就打开了。若调用UCOS的函数之前已将中断关掉,那么用户往往希望从UCOS的函数返回时,中断仍然是关掉的。在此情况下
,这种实现方法就不妥当;但是对于一些特定的处理器和编译器,使用这种方法是唯一的选择*/
#define  OS_ENTER_CRITICAL()  asm  CLI                    /* Disable interrupts                        */
#define  OS_EXIT_CRITICAL()   asm  STI                    /* Enable  interrupts                        */
#endif

#if      OS_CRITICAL_METHOD == 2                          /*实现OS_ENTER_CRITICAL()的第二种方法是在堆栈中保存
中断的开关状态,然后再关中断。在实现OS_EXIT_CRITICAL()时,只需简单的从堆栈中弹出原来中断的开关状态即可。利用这种
机制,不论用户在调用UCOS的函数之前中断是开着的还是关着的,函数的进入和返回状态都得到了保护。换句话说,如果调用前
中断是关掉的,则调用后扔是关掉的。关中断后调用UCOS的函数要特别小心,因为关中断延长了应用程序的中断延迟时间;
任务切换时间和中断延迟时间是评估RTOS性能的两个重要指标。任务切换时间可以反映出RTOS执行任务的速度,而中断延迟时间
可以反映出RTOS对外界变化的反应速度。表3为这两种操作系统任务切换时间和中断延迟时间的比较 :任务切换时间/us 中断延迟
时间/μs 测试环境 
μC/OS-II 29.7~34.2 78.8 Intel80186(33MHz) 
eCos 15.84 19.2 MPC860A3(33MHz) 
。*/
#define  OS_ENTER_CRITICAL()  asm {PUSHF; CLI}            /* Disable interrupts                        */
#define  OS_EXIT_CRITICAL()   asm  POPF                   /* Enable  interrupts                        */
#endif

#if      OS_CRITICAL_METHOD == 3                          /*一些编译器提供了扩展功能,用户可以得到当前处理器状态字
的值,并保存在C函数的局部变量中这个变量可以用于恢复PSW*/
#define  OS_ENTER_CRITICAL()  (cpu_sr = OSCPUSaveSR())    /* Disable interrupts                        */
#define  OS_EXIT_CRITICAL()   (OSCPURestoreSR(cpu_sr))    /* Enable  interrupts                        */
#endif

/*
*********************************************************************************************************
*                           Intel 80x86 (Real-Mode, Large Model) Miscellaneous
*********************************************************************************************************
*/

#define  OS_STK_GROWTH        1                       /* Stack grows from HIGH to LOW memory on 80x86绝大多数微处理器和
微控制器的堆栈是从上往下递减的,但是也有某些处理器使用的是相反的方式。UCOS被设计成2种情况都可以处理,只要在用被指常数
OS_STK_GROWTH指定堆栈的方向就可以了。OS_STK_GROWTH为0,表示堆栈从下(低地址)往上(高地址)递增;置OS_STK_GROWTH为1,表示堆栈
从上(高地址)往下(低地址)递减。之所以这样处理,是出于2个原因:首先,OSInit()需要知道,当OS_TaskIdle()和OS_TaskStat()函数建立
任务时,堆栈的顶端地址在哪里;其次,在调用OSTaskStkChk()时,UCOS需要知道堆栈的底端地址在哪里,从而得到堆栈的使用情况。*/

#define  uCOS                 0x80                    /* Interrupt vector # used for context switch ;OS_TASK_SW()是一个宏
,是在UCOS从低优先级任务切换到高优先级任务时须用到的。OS_TASK_SW()总是在任务级代码中调用。另一个函数OSIntExit()用在中断服
务子程序ISR中。当中断服务子程序使更高优先级任务进入就绪态时,OSIntExit()完成任务切换功能。任务切换只是简单的将处理器的寄存
器保存到将被挂起的任务的堆栈中,并且从堆栈中恢复要运行的更高优先级的任务。
     在UCOS中,处于就绪态任务的堆栈结构看起来就像刚刚发生过中断一样,所有的寄存器都保存在堆栈中。换句话说,UCOS要运行处于
就绪态的任务必须要作的事就是,从任务堆栈中恢复处理器所有的寄存器,并且执行中断返回指令。为了任务调度,可以通过执行
OS_TASK_SW()模仿中断的产生。绝大多数处理器会提供软中断或指令陷阱(TRAP)来完成这项功能。中断服务子程序或指令陷阱处理函数
也叫做异常处理函数的中断向量地址必须指向汇编语言函数OSCtxSw()。用户必须知道自己所使用的编译器和处理器是如何实现让中断向量
指向OSCtxSw()的。80X86有256个软中断可供选用。中断服务子程序ISR也称为异常处理的入口地址必须指向汇编函数OSCtxSw()见
OS_CPU_A.ASM文件。这里需要确认0x80中断向量指向OSCtxSw()。作者在PC机上做了测试,本章的代码用到了向量号为128(0x80)的中断,
因此此中断是提供给用户使用的。实际上,最初的PC将0x80~0xF0的中断给BASIC解释程序使用,后来机会在没有内植BASIC解释程序的PC机了
,所以用这些中断向量是安全的。类似的,可用的中断号还有0x4B~0x5B,0x5D~0x66以及0x68~0x6F。如果用的不是PC,而是其他嵌入式系统
,如80186处理器,则可能有更多的终端资源可供选用。*/

#define  OS_TASK_SW()         asm  INT   uCOS         

/*
*********************************************************************************************************
*                                            GLOBAL VARIABLES
*********************************************************************************************************
*/

OS_CPU_EXT  INT8U  OSTickDOSCtr;       /* Counter used to invoke DOS's tick handler every 'n' ticks 在这里声明了一个8位
变量OSTickDOSCtr,用来保存时钟节拍发生的次数。每发生11次,调用1次DOS的时钟节拍函数,从而实现与DOS时钟的同步。OSTickDOSCtr
在OS_CPU_A.ASM中使用,是专门为PC环境而定义的。如果在其他非PC的嵌入式系统中运行UCOS,就不必使用这种方法了,直接设定时钟节拍
频率就可以了。*/
                                       /*实时系统中时钟节拍的频率应该置为10~100HZ。通常但不是必须为了方便计
算,设为整数。不幸的是,在PC中,系统默认的时钟节拍频率是18.20648HZ,这对于计算和设置都不方便。本章中,将PC的时钟节拍频率从
18.20648HZ改为200HZ(间隔5ms)。这样做的原因有3个:
1,200HZ近似18.206 48HZ的11倍,可以经过11次延时,在调用DOS中断。在DOS中,时钟节拍处理程序要求每隔54.93ms进行一次有关系统
维护的操作;
2,设定的间隔5ms对于时间延时和时间超时设置都很有用。若pc机处理器是80386,那么时钟节拍最快也只能到200HZ;而如果是PentiumII
处理器,则很容易达到200HZ以上。
3,虽然将时钟节拍频率设定为20HZ或者100HZ也是可以的,但是这样将难以产生18.206 48HZ的DOS中断。这就是选择整数倍频,即选择200hz
的原因。当然也可以选择22倍频,这样就是400HZ间隔2.5ms。在一台更快的PC上,使用这种时钟节拍频率甚至更高的频率都不会有问题。
*/

/*
*********************************************************************************************************
*                                              PROTOTYPES
*********************************************************************************************************
*/

void       OSTaskStkInit_FPE_x86(OS_STK **pptos, OS_STK **ppbos, INT32U *psize); 
                                                 /*如前面所述,Borland编译器提供了一个浮点仿真库。但是该库不具备可重入性。
           增加了一个函数,使用户可以预处理任务的堆栈。这样使BorlandC任务只有一个任务在使用浮点仿真库,于是让浮点仿真库
           具备可重入性*/

#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
OS_CPU_SR  OSCPUSaveSR(void);
void       OSCPURestoreSR(OS_CPU_SR cpu_sr);
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -