加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

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

(2014-12-29 12:31:34)
标签:

stm32f7

ucos-iii

ucgui

emwin

dsp

分类: uC0S-III
特别说明:
1.  本教程是安富莱电子原创。
2.  安富莱STM32F407开发板资料已经全部开源,开源地址:地址链接
3.  当前共配套300多个实例,4套用户手册。

第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中几个配置文件的作用,方便分析源码的时候查看,配置文件主要有以下几个:

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

11.1.1       lib_cfg.h配置文件

lib_cfg.h文件内容如下:

  

#ifndef  LIB_CFG_MODULE_PRESENT

#define  LIB_CFG_MODULE_PRESENT

 

  

#define  LIB_MEM_CFG_ARG_CHK_EXT_EN     DEF_ENABLED

                                         

 

#define  LIB_MEM_CFG_OPTIMIZE_ASM_EN    DEF_ENABLED

                                         

 

#define  LIB_MEM_CFG_ALLOC_EN           DEF_ENABLED

                                         

 

#define  LIB_MEM_CFG_HEAP_SIZE          23u * 1024u    

 

  

#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             1u  

#define OS_CFG_ARG_CHK_EN               1u  

#define OS_CFG_CALLED_FROM_ISR_CHK_EN   1u  

#define OS_CFG_DBG_EN                   1u  

#define OS_CFG_ISR_POST_DEFERRED_EN     0u  

#define OS_CFG_OBJ_TYPE_CHK_EN          1u  

#define OS_CFG_TS_EN                    1u  

 

#define OS_CFG_PEND_MULTI_EN  1u  

 

#define OS_CFG_PRIO_MAX       64u 

 

#define OS_CFG_SCHED_LOCK_TIME_MEAS_EN  0u  

#define OS_CFG_SCHED_ROUND_ROBIN_EN     0u  

#define OS_CFG_STK_SIZE_MIN            64u  

 

 

#define OS_CFG_FLAG_EN          1u  

#define OS_CFG_FLAG_DEL_EN      1u  

#define OS_CFG_FLAG_MODE_CLR_EN 1u  

#define OS_CFG_FLAG_PEND_ABORT_EN 1u

 

 

#define OS_CFG_MEM_EN           1u  

 

 

#define OS_CFG_MUTEX_EN                 1u  

#define OS_CFG_MUTEX_DEL_EN             1u   

#define OS_CFG_MUTEX_PEND_ABORT_EN      1u  

 

 

#define OS_CFG_Q_EN                     1u  

#define OS_CFG_Q_DEL_EN                 1u  

#define OS_CFG_Q_FLUSH_EN               1u  

#define OS_CFG_Q_PEND_ABORT_EN          1u  

 

 

#define OS_CFG_SEM_EN                   1u  

#define OS_CFG_SEM_DEL_EN               1u  

#define OS_CFG_SEM_PEND_ABORT_EN        1u  

#define OS_CFG_SEM_SET_EN               1u  

 

 

 

#define OS_CFG_STAT_TASK_EN             1u  

#define OS_CFG_STAT_TASK_STK_CHK_EN     1u  

 

#define OS_CFG_TASK_CHANGE_PRIO_EN      1u  

#define OS_CFG_TASK_DEL_EN              1u  

#define OS_CFG_TASK_Q_EN                1u  

#define OS_CFG_TASK_Q_PEND_ABORT_EN     1u  

#define OS_CFG_TASK_PROFILE_EN          1u   

#define OS_CFG_TASK_REG_TBL_SIZE        1u  

#define OS_CFG_TASK_SEM_PEND_ABORT_EN   1u  

#define OS_CFG_TASK_SUSPEND_EN          1u  

 

 

 

#define OS_CFG_TIME_DLY_HMSM_EN         1u  

#define OS_CFG_TIME_DLY_RESUME_EN       1u  

 

 

 

#define OS_CFG_TMR_EN         1u  

#define OS_CFG_TMR_DEL_EN     1u  

 

#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  OS_CFG_MSG_POOL_SIZE            100u      

#define  OS_CFG_ISR_STK_SIZE             256u      

#define  OS_CFG_TASK_STK_LIMIT_PCT_EMPTY  10u      

 

 

 

#define  OS_CFG_IDLE_TASK_STK_SIZE       128u            

 

 

 

#define  OS_CFG_INT_Q_SIZE                10u            

#define  OS_CFG_INT_Q_TASK_STK_SIZE      128u            

 

 

#define  OS_CFG_STAT_TASK_PRIO     (OS_CFG_PRIO_MAX - 2u)

#define  OS_CFG_STAT_TASK_RATE_HZ         10u             

#define  OS_CFG_STAT_TASK_STK_SIZE       128u             

 

 

 

#define  OS_CFG_TICK_RATE_HZ            1000u  

#define  OS_CFG_TICK_TASK_PRIO             1u  

#define  OS_CFG_TICK_TASK_STK_SIZE       128u  

#define  OS_CFG_TICK_WHEEL_SIZE           16u  

 

 

#define  OS_CFG_TMR_TASK_PRIO      (OS_CFG_PRIO_MAX - 2u)  

#define  OS_CFG_TMR_TASK_RATE_HZ          10u              

#define  OS_CFG_TMR_TASK_STK_SIZE        128u              

#define  OS_CFG_TMR_WHEEL_SIZE            17u              

 

#endif

这个文件主要是内核任务的配置,包括中断管理任务,空闲任务,统计任务,嘀嗒定时器任务已经定时器任务。

11.1.4       app_cfg.h配置文件

app_cfg.h文件夹中的内容如下:

#ifndef  APP_CFG_MODULE_PRESENT

#define  APP_CFG_MODULE_PRESENT

 

 

#define  APP_CFG_TASK_START_PRIO                              2u

#define  APP_CFG_TASK_UPDATE_PRIO                             3u

#define  APP_CFG_TASK_COM_PRIO                                4u

#define  APP_CFG_TASK_USER_IF_PRIO                            5u

#define  APP_CFG_TASK_GUI_PRIO                        (OS_CFG_PRIO_MAX - 4u)

#define  APP_CFG_TASK_GUIRefresh_PRIO                 (OS_CFG_PRIO_MAX - 4u)

 

 

#define  APP_CFG_TASK_START_STK_SIZE                      1024u

#define  APP_CFG_TASK_UPDATE_STK_SIZE                     1024u

#define  APP_CFG_TASK_COM_STK_SIZE                        1024u

#define  APP_CFG_TASK_USER_IF_STK_SIZE                    1024u

#define  APP_CFG_TASK_GUI_STK_SIZE                        1024u

#define  APP_CFG_TASK_GUIRefresh_STK_SIZE                 1024u

 

#endif

这个文件主要用于用户任务的配置。

11.1.5       cpu_cfg.h配置文件

cpu_cfg.h文件中的内容如下:

#ifndef  CPU_CFG_MODULE_PRESENT

#define  CPU_CFG_MODULE_PRESENT

 

                            

#define  CPU_CFG_NAME_EN                         DEF_ENABLED

                                            

            

                                           

#define  CPU_CFG_NAME_SIZE                                16   

 

                                     

#define  CPU_CFG_TS_32_EN                       DEF_ENABLED

#define  CPU_CFG_TS_64_EN                       DEF_DISABLED

                                               

                                            

#define  CPU_CFG_TS_TMR_SIZE                    CPU_WORD_SIZE_32

 

 

#if 0                                             

#define  CPU_CFG_INT_DIS_MEAS_EN                   

#endif

 

#define  CPU_CFG_INT_DIS_MEAS_OVRHD_NBR      1u    

 

  

#if 1                                             

#define  CPU_CFG_LEAD_ZEROS_ASM_PRESENT           

#endif

 

#if 0                                             

#define  CPU_CFG_TRAIL_ZEROS_ASM_PRESENT           

#endif

 

#endif                                        

这个文件里面主要是uC/CPU相关的配置。

11.2  源码文件

μCOS-III中的源码主要包含如下文件:

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

上面截图中是μCOS-III相关的源码文件,后面的几期教程就是把这几个文件讲清楚。本期教程主要是讲解os_core文件中的相关函数。学期源码前还有看一下os_type.h文件中的内容(主要是变量的类型,这个一定得了解下):

 

typedef   CPU_INT16U      OS_CPU_USAGE;

 

typedef   CPU_INT32U      OS_CTR;      

 

typedef   CPU_INT32U      OS_CTX_SW_CTR;

 

typedef   CPU_INT32U      OS_CYCLES;   

 

typedef   CPU_INT32U      OS_FLAGS;    

 

typedef   CPU_INT32U      OS_IDLE_CTR; 

 

typedef   CPU_INT16U      OS_MEM_QTY;  

typedef   CPU_INT16U      OS_MEM_SIZE; 

 

typedef   CPU_INT16U      OS_MSG_QTY;  

typedef   CPU_INT16U      OS_MSG_SIZE; 

 

typedef   CPU_INT08U      OS_NESTING_CTR;

 

typedef   CPU_INT16U      OS_OBJ_QTY;    

typedef   CPU_INT32U      OS_OBJ_TYPE;   

 

typedef   CPU_INT16U      OS_OPT;        

 

typedef   CPU_INT08U      OS_PRIO;        

 

typedef   CPU_INT16U      OS_QTY;        

 

typedef   CPU_INT32U      OS_RATE_HZ;    

 

typedef   CPU_INT32U      OS_REG;        

typedef   CPU_INT08U      OS_REG_ID;     

 

typedef   CPU_INT32U      OS_SEM_CTR;    

 

typedef   CPU_INT08U      OS_STATE;      

 

typedef   CPU_INT08U      OS_STATUS;     

 

typedef   CPU_INT32U      OS_TICK;       

typedef   CPU_INT16U      OS_TICK_SPOKE_IX;

 

typedef   CPU_INT16U      OS_TMR_SPOKE_IX;

11.3  μCOS-III初始化

下面开始讲解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

当前调度器被锁的最长时间

OSSafetyCriticalStartFlag

DEF_FALSE

系统安全关键开始标志

OSSchedRoundRobinEn

DEF_FALSE

使能Round-Robin调度

OSSchedRoundRobinDfltTimeQuanta

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

    函数OSInit()中的其它初始化会在后面讲到的时候再做详细阐述。下面把初始化函数做一下分析。

11.3.2       初始化函数OSInit()

 

void  OSInit (OS_ERR  *p_err)

{

    CPU_STK      *p_stk;

    CPU_STK_SIZE  size;

 

 

 

#ifdef OS_SAFETY_CRITICAL                                                        1

    if (p_err == (OS_ERR *)0) {

        OS_SAFETY_CRITICAL_EXCEPTION();

        return;

    }

#endif

 

    OSInitHook();                                                                                 

 

    OSIntNestingCtr                 = (OS_NESTING_CTR)0;                      2

 

    OSRunning                       OS_STATE_OS_STOPPED;

 

    OSSchedLockNestingCtr           = (OS_NESTING_CTR)0;   

 

    OSTCBCurPtr                     = (OS_TCB *)0;               3

    OSTCBHighRdyPtr                 = (OS_TCB *)0;

 

    OSPrioCur                       = (OS_PRIO)0;     

    OSPrioHighRdy                   = (OS_PRIO)0;

    OSPrioSaved                     = (OS_PRIO)0;

 

#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u              

    OSSchedLockTimeBegin            = (CPU_TS)0;

    OSSchedLockTimeMax              = (CPU_TS)0;

    OSSchedLockTimeMaxCur           = (CPU_TS)0;

#endif

 

#ifdef OS_SAFETY_CRITICAL_IEC61508                                           4

    OSSafetyCriticalStartFla      DEF_FALSE;

#endif

 

#if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u                                       5

    OSSchedRoundRobinEn             = DEF_FALSE;

    OSSchedRoundRobinDfltTimeQuanta = OSCfg_TickRate_Hz / 10u;

#endif

 

    if (OSCfg_ISRStkSize > (CPU_STK_SIZE)0) {                                                                                                  6

        p_stk = OSCfg_ISRStkBasePtr;                 

        if (p_stk != (CPU_STK *)0) {

            size  = OSCfg_ISRStkSize;

            while (size > (CPU_STK_SIZE)0) {

                size--;

               *p_stk = (CPU_STK)0;

                p_stk++;

            }

        }

    }

 

#if OS_CFG_APP_HOOKS_EN > 0u                                                                      7

    OS_AppTaskCreateHookPtr = (OS_APP_HOOK_TCB )0;    

    OS_AppTaskDelHookPtr    = (OS_APP_HOOK_TCB )0;

    OS_AppTaskReturnHookPtr = (OS_APP_HOOK_TCB )0;

 

    OS_AppIdleTaskHookPtr   = (OS_APP_HOOK_VOID)0;

    OS_AppStatTaskHookPtr   = (OS_APP_HOOK_VOID)0;

    OS_AppTaskSwHookPtr     = (OS_APP_HOOK_VOID)0;

    OS_AppTimeTickHookPtr   = (OS_APP_HOOK_VOID)0;

#endif

 

#if OS_CFG_TASK_REG_TBL_SIZE > 0u

    OSTaskRegNextAvailID    = (OS_REG_ID)0;    

#endif

 

    OS_PrioInit();                             

 

    OS_RdyListInit();                          

 

   

#if OS_CFG_FLAG_EN > 0u                        

    OS_FlagInit(p_err);

    if (*p_err != OS_ERR_NONE) {

        return;

    }

#endif

 

 

#if OS_CFG_MEM_EN > 0u                        

    OS_MemInit(p_err);

    if (*p_err != OS_ERR_NONE) {

        return;

    }

#endif

 

 

#if (OS_MSG_EN) > 0u                         

    OS_MsgPoolInit(p_err);

    if (*p_err != OS_ERR_NONE) {

        return;

    }

#endif

 

 

#if OS_CFG_MUTEX_EN > 0u                     

    OS_MutexInit(p_err);

    if (*p_err != OS_ERR_NONE) {

        return;

    }

#endif

 

 

#if OS_CFG_Q_EN > 0u

    OS_QInit(p_err);                        

    if (*p_err != OS_ERR_NONE) {

        return;

    }

#endif

 

 

#if OS_CFG_SEM_EN > 0u                      

    OS_SemInit(p_err);

    if (*p_err != OS_ERR_NONE) {

        return;

    }

#endif

 

 

#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)

    OS_TLS_Init(p_err);                   

    if (*p_err != OS_ERR_NONE) {

        return;

    }

#endif

 

 

    OS_TaskInit(p_err);                   

    if (*p_err != OS_ERR_NONE) {

        return;

    }

 

 

#if OS_CFG_ISR_POST_DEFERRED_EN > 0u

    OS_IntQTaskInit(p_err);               

    if (*p_err != OS_ERR_NONE) {

        return;

    }

#endif

 

   

    OS_IdleTaskInit(p_err);               

    if (*p_err != OS_ERR_NONE) {

        return;

    }

 

 

    OS_TickTaskInit(p_err);               

    if (*p_err != OS_ERR_NONE) {

        return;

    }

 

 #if OS_CFG_STAT_TASK_EN > 0u              

    OS_StatTaskInit(p_err);

    if (*p_err != OS_ERR_NONE) {

        return;

    }

#endif

 

 

#if OS_CFG_TMR_EN > 0u                    

    OS_TmrInit(p_err);

    if (*p_err != OS_ERR_NONE) {

        return;

    }

#endif

 

 #if OS_CFG_DBG_EN > 0u

    OS_Dbg_Init();                         

#endif

 

 

    OSCfg_Init();                          

}

1.     如果用户在工程预定义中加入了OS_SAFETY_CRITICAL,那么函数就会执行参数检查功能,如果参数不满足条件的话就会进入安全关键异常OS_SAFETY_CRITICAL_EXCEPTION()。安全关键的代码是需要用户去实现的。

2.     OSIntNestingCtr  用于记录中断嵌套次数,在μCOS-III中使用中断的话,一般采用如下的方式:

void  OS_CPU_SysTickHandler (void)

{

CPU_SR_ALLOC();

 

CPU_CRITICAL_ENTER();

OSIntNestingCtr++;                                         

CPU_CRITICAL_EXIT();

 

//添加用户代码

 

OSIntExit();                                           

}

也就是说进入中断后,先将OSIntNestingCtr加一,退出的时候再执行减一。为什么要这么做?为了说明这个问题,这里举一个例子,假如有低优先级中断A和高优先级中断BA中断执行的时候,中断B抢占了A的执行,中断B执行完退出的时候会执行函数OSIntExit();这个函数最主要的作用就是中断级任务切换)。可以想象,如果没有中断嵌套计数变量,退出高优先级中断B的时候运行函数OSIntExit();有可能会执行中断级任务切换,此时执行任务切换的话就会破换正常的寄存器入栈和出栈顺序,从而使得系统崩溃。其实进入Cortex-M3/M4时代已经不存在这个问题了,因为我们设置PendSV中断为最低的优先级(任务切换是在PendSV中断里面执行的),PendSV中断会在所有其它高优先级中断执行完后才会得到执行。

为了使得μCOS-III可以适应各种处理器内核和复杂的系统设置,中断嵌套计数还是很有必要的。

3.     当前任务控制块指针OSTCBCurPtr和最高就绪任务的任务控制块指针OSTCBHighRdyPtr都指向了0地址空间。初始为指向0地址空间主要是为了使这两个指针变量都有个初始量。而且方便后面用到这两个指针变量的函数进行检测。

4.     默认安全关键的标志OSSafetyCriticalStartFlag是关闭的。

5.     这里个两个变量:OSSchedRoundRobinEn             = DEF_FALSE;

OSSchedRoundRobinDfltTimeQuanta = OSCfg_TickRate_Hz / 10u;

是用于配置时间片的,默认时间片调度是关闭的,时间片大小是OSCfg_TickRate_Hz / 10u。这两个

关于时间片的配置变量大家一定要记住。

6.     这里是几个钩子函数指针,初始化钩子函数,关于钩子函数,咱们在上期教程有详细讲解。

函数中还有有很多其它的初始化,我们会在后面再跟大家详细的讲述。

11.4   μCOS-III启动

11.4.1       启动

不像其它RTOSμCOS-III有一个标准的初始化过程,所以特别建议初学的同学按照这个过程进行初始化,如果不按照这个过程进行初始化,往往会出现莫名其妙的后果,标准的初始化流程如下:

 

int main(void)

{

    OS_ERR  err;

   

   

    OSInit(&err);                                            

 

    

OSTaskCreate((OS_TCB       *)&AppTaskStartTCB,            

                 (CPU_CHAR     *)"App Task Start",

                 (OS_TASK_PTR   )AppTaskStart,

                 (void         *)0,

                 (OS_PRIO       )APP_CFG_TASK_START_PRIO,

                 (CPU_STK      *)&AppTaskStartStk[0],

                 (CPU_STK_SIZE  )APP_CFG_TASK_START_STK_SIZE / 10,

                 (CPU_STK_SIZE  )APP_CFG_TASK_START_STK_SIZE,

                 (OS_MSG_QTY    )0,

                 (OS_TICK       )0,

                 (void         *)0,

                 (OS_OPT        )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),

                 (OS_ERR       *)&err);

 

    

    OSStart(&err);                                               

    (void)&err;

   

    return (0);

}

 

 

static  void  AppTaskStart (void *p_arg)

{

OS_ERR      err;   

   (void)p_arg;

 

     

     bsp_Init();

     CPU_Init();

    

     BSP_Tick_Init();                     

 

#if OS_CFG_STAT_TASK_EN > 0u

     OSStatTaskCPUUsageInit(&err);  

#endif

 

#ifdef CPU_CFG_INT_DIS_MEAS_EN

    CPU_IntDisMeasMaxCurReset();

#endif

                                       

    AppTaskCreate();                                          

    while (1)

                                           

         bsp_LedToggle(1);

         OSTimeDly(1000, OS_OPT_TIME_DLY, &err);

    }

}

     上面的五步就是标准的初始化流程,一定要按照这个顺序进行,这个流程是官方推荐的。为什么要按照这个流程进行初始化? 随着后面源码的讲解,大家会深刻的领悟到这一点。

11.4.2       启动函数OSStart ()

 

 

void  OSStart (OS_ERR  *p_err)

{

#ifdef OS_SAFETY_CRITICAL                                                                           1                                                                               

    if (p_err == (OS_ERR *)0) {

        OS_SAFETY_CRITICAL_EXCEPTION();

        return;

    }

#endif

 

    if (OSRunning == OS_STATE_OS_STOPPED) {                                                         2

        OSPrioHighRdy   = OS_PrioGetHighest();                   3

        OSPrioCur       = OSPrioHighRdy;

        OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;                                         4

        OSTCBCurPtr     = OSTCBHighRdyPtr;

        OSRunning       = OS_STATE_OS_RUNNING;                                                      6

        OSStartHighRdy();                                 7

       *p_err           = OS_ERR_FATAL_RETURN;                              8

    } else {

       *p_err           = OS_ERR_OS_RUNNING;                                       9

    }

}

1.     后面大家会看到,只要是供用户调用的函数和部分内部函数里面都会有这个安全关键代码,主要是用来防止错误的输入形参。

2.     前面初始化的时候,设置OSRunning = OS_STATE_OS_STOPPED,所以按照正常的初始化顺序,程序会进入到if语句中。

3.     通过函数OS_PrioGetHighest()可以获得当前需要执行的最高优先级任务,这个会在下期教程跟大家详细讲述。

4.     从任务的就绪链表中获得当前需要执行的最高优先级任务。

5.     设置系统的运行状态为OSRunning = OS_STATE_OS_RUNNING,然后开始μCOS-III多任务的执行。

6.     关于这个函数,咱们在上期教程中有详细的讲解,这个函数执行完就会进入到PendSV中断。

7.     正常情况下程序是不会执行到这里的。

8.     如果系统已经启动了,用户程序要是再次调用这个函数会进入到这里。

11.5  获取系统版本

有时候我们需要获取系统的版本号,下面就是系统版本的获取函数。这个函数比较简单,特别注意函数注释。

 

 

CPU_INT16U  OSVersion (OS_ERR  *p_err)

{

#ifdef OS_SAFETY_CRITICAL

    if (p_err == (OS_ERR *)0) {

        OS_SAFETY_CRITICAL_EXCEPTION();

        return ((CPU_INT16U)0u);

    }

#endif

 

   *p_err = OS_ERR_NONE;

    return (OS_VERSION);

}


0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有