内核解读

来源:互联网 发布:郑恺潮牌淘宝店 编辑:程序博客网 时间:2024/04/28 20:02

/*****************************************************************************************************
*                                                uC/OS-II
*                                          
实时操作系统
*                                             
内核函数
*
文件: OS_CORE.C
建立: Jean J. Labrosse
修改千里冰封                   
功能操作系统核心代码
*********************************************************************************************************
*/
#ifndef  OS_MASTER_FILE
#define  OS_GLOBALS
#include "includes.h"
#endif

/*
********************************************************************************************
*   
任务就绪表优先级别获取辅助常数数组,用查表的方法加速运算
*
********************************************************************************************
*/  
 
INT8U  const  OSMapTbl[]   = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

/*    00000001    0x01     */        
/*    00000010    0x02     */
/*    00000100    0x04     */
/*    00001000    0x08     */
/*    00010000    0x10     */
/*    00100000    0x20     */
/*    01000000    0x40     */
/*    10000000    0x80     */
/*******************************************************************************************
*/           

INT8U  const  OSUnMapTbl[] = {
    0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x00 to 0x0F                             */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x10 to 0x1F                             */
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x20 to 0x2F                             */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x30 to 0x3F                             */
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x40 to 0x4F                             */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x50 to 0x5F                             */
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x60 to 0x6F                             */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x70 to 0x7F                             */
    7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x80 to 0x8F                             */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x90 to 0x9F                             */
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xA0 to 0xAF                             */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xB0 to 0xBF                             */
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xC0 to 0xCF                             */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xD0 to 0xDF                             */
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xE0 to 0xEF                             */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0        /* 0xF0 to 0xFF                             */
};

/*
********************************************************************************************
*                                       
内部函数声明
********************************************************************************************
*/
static  void  OS_InitEventList(void);               /*
初始化空事件块链表                */
static  void  OS_InitMisc(void);                        /*
操作系统运行前参数初始化*/
static  void  OS_InitRdyList(void);                  /*
初始化任务就绪表                      */
static  void  OS_InitTaskIdle(void);                 /*
初始化空闲任务                           */
static  void  OS_InitTaskStat(void);                /*
初始化统计任务                           */
static  void  OS_InitTCBList(void);                  /*
空任务控制快链表初始化    */

/*$PAGE*/
/*
********************************************************************************************
*                                            
操作系统初始化函数void  OSInit (void)
*
描述这个函数是操作系统运行前的初始化,必须在操作系统启动,创建任务
*               
前被调用。
*
功能初始化操作系统参数
*
备注 :  
*               1   OSInitHookBegin() 
OSInitHookEnd os_cpu_c.c
*               2   
创建统计任务OS_InitTaskIdle()
********************************************************************************************
*/                                            

void  OSInit (void)
{
#if OS_VERSION >= 204                                            
    OSInitHookBegin();                        /* 
调用钩子函数,用户代码 */
#endif

    OS_InitMisc();                                /*   
基础参数初始化*/

    OS_InitRdyList();                           /*  
初始化任务就绪表 */
    
    OS_InitTCBList();                           /*   
初始化任务控制块*/
    
    OS_InitEventList();                        /* 
初始化事情控制块  */
    
/****************************************
根据条件编译***************************************/
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
    OS_FlagInit();                                /*    
事件标志组初始化*/
#endif

#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
    OS_MemInit();                                 /*    
内存初始化 */
#endif

#if (OS_Q_EN > 0) && (OS_MAX_QS > 0)
    OS_QInit();                                  /*   
消息队列初始化 */
#endif

    OS_InitTaskIdle();                          /*    
创建空闲任务(无条件) */

#if OS_TASK_STAT_EN > 0
    OS_InitTaskStat();                          /*  
创建统计任务                      */
#endif

#if OS_VERSION >= 204
    OSInitHookEnd();                           /* 
钩子函数  用户代码*/
#endif
}
/*$PAGE*/
/*
********************************************************************************************
*                                              
中断进入函数            void  OSIntEnter (void)      
*
描述: uC/OS-II 操作系统下进入中断服务程序首先必须调用这个函数,它的作用
*               
是通知操作系统已经进入中断,并且记录中断嵌套的次数。
*             
功能将中断计数器OSIntNesting1
*
返回
*
备注 :  1   这个函数必须在中断禁止的情况下调用
*                2   OSIntNesting 
必须是一个全局变量。
*                3   
这个函数必须与中断退出函数OSIntExit()成对使用,有进入就必然有退出
*                4   
也可以直接就操作OSIntNesting 不调用本函数,效果一样
*                5   
退出时不可以直接将OSIntNesting1   而必须调用OSIntExit() 
*                6   
中断嵌套最多允许255
*                7   
OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL()来确保OSIntEnter () OSIntExit()在中断禁止
*                     
的环境下调用。       
*            
********************************************************************************************
*/                                                      

void  OSIntEnter (void)                                
{
    if (OSRunning == TRUE)
     {
        if (OSIntNesting < 255)                  
         { 
            OSIntNesting++;            /*    
中断进入计数主要用于中断嵌套 OSIntNesting1    */           
         }
     }
}
/*$PAGE*/
/*
********************************************************************************************
*                                                
中断退出函数        void  OSIntExit (void)
*
描述这个函数是uC/OS-II 操作系统退出中断时调用的,当系统从最后一层中断
*               
退出时调用本函数,通知操作系统,同时作一次任务调度,让任务就绪
*              
表中就绪的最高优先级任务准备进入运行
功能 : OSIntNesting1,同时让就绪的最高优先级的任务运行。
*
返回  : 
*
备注   : 1  这个函数必须与中断退出函数OSIntEnter ()成对使用,有进入就必然有退出                
*                 2  
退出时不可以直接将OSIntNesting1   而必须调用OSIntExit() 
*                 3  
OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL()来确保OSIntEnter () OSIntExit()在中断禁止
*                     
的环境下调用。
*                 4  OSIntCtxSw()
os_cpu_a.s
********************************************************************************************
*/                                                       

void  OSIntExit (void)
{
#if OS_CRITICAL_METHOD == 3                                        /*  
有些编译器可以得到处理器的状态字  */                 
    OS_CPU_SR  cpu_sr;                                                    /*    OS_CPU_SR 
这个宏就会在os_cpu.h中定义       */
#endif
    
    
    if (OSRunning == TRUE)                                                /*
判断操作系统是否已经启动                   */
   {
     OS_ENTER_CRITICAL();                                                 /*
代码临界段,不允许中断                         */
        if (OSIntNesting > 0)
         {                                                
            OSIntNesting--;                                                   /*
计数器减1                                                               */
         }
                                                                                        /*
没有了其它中断且任务调度没有锁定*/
        if ((OSIntNesting == 0) && (OSLockNesting == 0))   /*----
中断退出进行任务调度的条件         */
         {                                                                    
                                                                                       /*
获取最高优先级别的任务在任务就绪 */
                                                  /*      ___
表中的纵向位置 Y                                     */                                       
            OSIntExitY    = OSUnMapTbl[OSRdyGrp];  
                                                                                      /*
获取最高优先级别的任务的优先级别  */
            OSPrioHighRdy = (INT8U)((OSIntExitY << 3) + OSUnMapTbl[OSRdyTbl[OSIntExitY]]);    
                                                                                     /*
如果当前就绪任务中最高优先级别不等*/
                                                                                     /* ___
于当前中断的任务优先级则任务切换*/      
            if (OSPrioHighRdy != OSPrioCur)            
              {                                                                      /*
获取最高优先级别的任务控制块指针    */
                OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy];   
                OSCtxSwCtr++;                                                               /*   
任务调度切换次数计数                */
                OSIntCtxSw();                                                                /*   
进行中断级任务调度切换           */
              }
         }
      OS_EXIT_CRITICAL();                                                                /*     
打开中断                  */
   }
}
/*$PAGE*/
/*
********************************************************************************************
*                                         
任务调度锁定函数   void  OSSchedLock (void)
*
描述锁定任务调度,锁定后任务将不做切换,一直执行一个任务直到
*              
重新启动任务调度。
*
功能任务调度锁定               OSLockNesting1
*
返回
*
备注: 1   任何情况下OSSchedLock() and OSSchedUnlock() 必须成对使用
*              2   
不要轻易的锁定任务调度,这样严重破坏了 uC/OS-II 的实时性违背了本意 
*              3   
OSLockNesting  >0时系统将禁止任务调度。
*              4   
多次调用OSSchedLock() 需要同等次数OSSchedUnlock()调用才能解锁
********************************************************************************************
*/

#if OS_SCHED_LOCK_EN > 0
void  OSSchedLock (void)
{
#if OS_CRITICAL_METHOD == 3     /*  
有些编译器可以得到处理器的状态字  */
    OS_CPU_SR  cpu_sr;                 /*    OS_CPU_SR 
这个宏就会在os_cpu.h中定义       */
#endif    
    
    
    if (OSRunning == TRUE)         /*  
确认系统正在运行,若不在运行也无所谓锁定 */
     {                                             
        OS_ENTER_CRITICAL();                     /*
代码临界段                                                                        */
        if (OSLockNesting < 255)                  /* 
最到允许锁定255                                                      */
         {                                                     /*
禁止 OSLockNesting回到0  这里 255+1=0                          */
            OSLockNesting++;                       /*  
任务调度锁定次数加1                                              */
         }
        OS_EXIT_CRITICAL();
    }
}
#endif    

/*$PAGE*/
/*
********************************************************************************************
*                                       
解锁任务调度    void  OSSchedUnlock (void)
*
描述开启任务调度.
*
功能: OSLockNesting--   OSLockNesting=0打开任务调度,引发任务调度
*
返回
*
备注: 1   任何情况下OSSchedLock() and OSSchedUnlock() 必须成对使用
*              2   
要明确的是调用了这个函数并不代表就真的打开了任务调度
*                   
只是将OSLockNesting1,只有OSLockNesting=0才能打开任务调度,
*                   
任务调度锁定是可以嵌套的。
*                                
********************************************************************************************
*/
                                       
#if OS_SCHED_LOCK_EN > 0
void  OSSchedUnlock (void)
{
#if OS_CRITICAL_METHOD == 3                                /* 
参见前面 */
    OS_CPU_SR  cpu_sr;
#endif    
    
    
    if (OSRunning == TRUE)
     {                                                         /* 
确认操作系统正在运行      */
        OS_ENTER_CRITICAL();
        if (OSLockNesting > 0)
         {                                                     /* 
确认任务调度已经被锁定*/
            OSLockNesting--;                        /* 
锁定次数减1                                */
            if ((OSLockNesting == 0) && (OSIntNesting == 0))  
             {                                               /* 
没有中断,并且没有了锁定*/
                OS_EXIT_CRITICAL();
                OS_Sched();                         /* 
任务调度                                            */
                                                             /*
这里引发了一次任务调度      */
              }                                    
            else
             {
                OS_EXIT_CRITICAL();
             }
         } 
        else 
         {
            OS_EXIT_CRITICAL();
         }
    }
}
#endif    

/*$PAGE*/
/*
********************************************************************************************
*                                          
启动操作系统void  OSStart (void)
*
描述操作系统启动函数,启动操作系统之前必须调用OSInit()初始化,
*               
并且建立了至少1个任务。
*
功能获取任务就绪表中最高优先级别的任务并运行
*
返回
*
备注调用OSStartHighRdy()来运行就绪的最高优先级的任务
*               1  
设置操作系统启动 OSRunning =1
*               2  
调用钩子函数OSTaskSwHook
*               3 
加载并运行操作系统的就绪最高优先级的任务   
*           
*********************************************************************************************************
*/                                      
void  OSStart (void)
{
    INT8U y;
    INT8U x;


    if (OSRunning == FALSE)                               /*
确保操作系统没有在运行*/
     {
        y             = OSUnMapTbl[OSRdyGrp];        /* 
获取任务就绪表中就绪的最高优先级 */
        x             = OSUnMapTbl[OSRdyTbl[y]];
        OSPrioHighRdy = (INT8U)((y << 3) + x);
        OSPrioCur     = OSPrioHighRdy;
        OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy];             /* 
指向就绪的最高优先级的任务控制块*/
        OSTCBCur      = OSTCBHighRdy;
        
        OSStartHighRdy();                            
                 /*
这是的软中断函数  主要功能是告诉系统已经启动 OSRunning=1 同时装载任务*/
                 /*
函数在os_cpu_c.c中,函数通过调用os_cpu.h 中的软中断_OSStartHighRdy()
                    
实际核心代码采用汇编语言编写在Os_cpu_a.s                                                                    */
     }
}
/*$PAGE*/
/*
********************************************************************************************
*                                        
初始化统计任务 void  OSStatInit (void)
*
描述这个函数的功能是计算没有其它任务运行的情况下  计算出1S
*               
统计任务运行的次数,为用户的应用程序计算用户任务CPU使用效率
*              
做前提准备                                     
*  
功能获取1S 中计数的最大值在 OSIdleCtrMax   (系统只有统计任务的情况下)
*              
备注: 1   用户任务的CPU使用比例计算公式:
*                                                                   OSIdleCtr
*                   CPU 

原创粉丝点击