logo资料库

UCOS_III_配置与初始化.pdf

第1页 / 共21页
第2页 / 共21页
第3页 / 共21页
第4页 / 共21页
第5页 / 共21页
第6页 / 共21页
第7页 / 共21页
第8页 / 共21页
资料共21页,剩余部分请下载后查看
void OSInit (OS_ERR *p_err) { CPU_STK *p_stk; CPU_STK_SIZE size; #ifdef OS_SAFETY_CRITICAL /*这个定义我没找到,可能是留给以后的,或是留给我们自己写*/ if (p_err == (OS_ERR *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return; } #endif OSInitHook(); /* 这个函数是留给用户写的,编程的人可根据自己情况写,当然空的也行 */ OSIntNestingCtr = (OS_NESTING_CTR)0; /* 中断计数器,每来一个硬件中断这个就加 1, */ OSRunning = OS_STATE_OS_STOPPED; /* OSRunning 是说明是否要启动多任务切换功能,很明显初始化时是不启 动这个功能*/ OSSchedLockNestingCtr = (OS_NESTING_CTR)0; /* 这个是为了给任务上锁,开始为 0,如果在某个任务某个段不想让别的 任务打断就用上锁函数,这个参数会被加上,这样,别的任务就不能被切换, 因为负责任务调度的函数 会是否不为 0,不为 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
OSSafetyCriticalStartFlag = DEF_FALSE; /*这个为 1 的话,就不能建新的任务了*/ #endif #if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u /*这个 ucos3 一个优先级可以带任意多个任务,每次只运行该优先级的第一个任 务,用这个可以在每个固定时间将最前面的任务调到最后,总觉得这样会影响实 时性,下面细说*/ OSSchedRoundRobinEn = DEF_FALSE; OSSchedRoundRobinDfltTimeQuanta = OSCfg_TickRate_Hz / 10u; #endif if (OSCfg_ISRStkSize > (CPU_STK_SIZE)0) { p_stk = OSCfg_ISRStkBasePtr; /* Clear exception stack for stack checking. */ if (p_stk != (CPU_STK *)0) { /*关于 OSCfg_ISRStkBasePtr 我也不是很清楚,不用也行*/ size = OSCfg_ISRStkSize; /*在 os_cfg_app.c 中有定义 CPU_STK* const OSCfg_ISRStkBasePtr= (CPU_STK*)&OSCfg_ISRStk[0];*/ while (size > (CPU_STK_SIZE)0) { /*CPU_STK OSCfg_ISRSt[OS_CFG_ISR_STK_SIZE]这也是在 os_cfg_app.c 定义的*/ size--; /*#define OS_CFG_ISR_STK_SIZE 128u 在 os_cfg_app.h 中 定义*/ *p_stk = (CPU_STK)0; p_stk++; } } } #if OS_CFG_APP_HOOKS_EN > 0u 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 OS_PrioInit(); /* 初始化优先级 */ OS_RdyListInit(); /* 初始化就绪任务列表 */ 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); /* 初始化空任务,一般没有别的任务工作的话,就由它来占 CPU,空任务 的优先级要最低*/ 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_FLAG_EN > 0u /* ucos 的资源有 FLAG 控制,sem 控制,Mem 管理,Msg 消息管理,Mutx 互斥信 号管理,队列管理,软定时器管理*/ OS_FlagInit(p_err); if (*p_err != OS_ERR_NONE) { return; } #endif #if OS_CFG_MEM_EN > 0u /* Initialize the Memory Manager module */ OS_MemInit(p_err); if (*p_err != OS_ERR_NONE) { return; } #endif #if (OS_MSG_EN) > 0u /* Initialize the free list of OS_MSGs */ OS_MsgPoolInit(p_err); if (*p_err != OS_ERR_NONE) { return; } #endif #if OS_CFG_MUTEX_EN > 0u /* Initialize the Mutex Manager module */ OS_MutexInit(p_err); if (*p_err != OS_ERR_NONE) { return; } #endif #if OS_CFG_Q_EN > 0u OS_QInit(p_err);
/* Initialize the Message Queue Manager module */ if (*p_err != OS_ERR_NONE) { return; } #endif #if OS_CFG_SEM_EN > 0u /* Initialize the Semaphore Manager module */ OS_SemInit(p_err); if (*p_err != OS_ERR_NONE) { return; } #endif #if OS_CFG_TMR_EN > 0u /* Initialize the Timer Manager module */ OS_TmrInit(p_err); if (*p_err != OS_ERR_NONE) { return; } #endif #if OS_CFG_DBG_EN > 0u OS_Dbg_Init(); #endif OSCfg_Init(); } 使用这个操作系统首先要初始化这个系统的资源,OSInit 来初始化这些资源的。 OSIntNestingCtr 这个变量,在来中断时,这个就加 1,说明这时还在处理外部 中断 事情,这时候可能有任务进入就绪状态,但也不会被调用。OSSched 这个调度函 数会去看这个变量是否为 0,为 0 就可以调度,不然不能。这个是在自己编写移植函数时调用处理中断函数前调用 下 OSIntEnter,然后在调用 处理中断函数后调用 OSIntExit 就好了。 /******************************************************************** ***************************************************** void OSIntEnter (void) {
if (OSRunning != OS_STATE_OS_RUNNING) { /* Is OS running? */ return; /* No */ } if (OSIntNestingCtr >= (OS_NESTING_CTR)250u) { /* Have we nested past 250 levels? */ return; /* Yes */ } OSIntNestingCtr++; /* 这里就 把 OSIntNestingCtr+1 了 */ } ********************************************************************* *******************************************************/ /******************************************************************** ******************************************************** void OSIntExit (void) { CPU_SR_ALLOC(); if (OSRunning != OS_STATE_OS_RUNNING) { /* Has the OS started? */ return; /* No */ } CPU_INT_DIS(); if (OSIntNestingCtr == (OS_NESTING_CTR)0) { /* Prevent OSIntNestingCtr from wrapping */ CPU_INT_EN(); return; } OSIntNestingCtr--; /*看这,每退出一个中断处理就减 1,中断处理是会嵌套的*/ if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* ISRs still nested? */ CPU_INT_EN(); /* Yes */
return; } if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Scheduler still locked? */ CPU_INT_EN(); /* Yes */ return; } OSPrioHighRdy = OS_PrioGetHighest(); /* Find highest priority */ OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr; /* Get highest priority task ready-to-run */ if (OSTCBHighRdyPtr == OSTCBCurPtr) { /* Current task still the highest priority? */ CPU_INT_EN(); /* Yes */ return; } #if OS_CFG_TASK_PROFILE_EN > 0u OSTCBHighRdyPtr->CtxSwCtr++; /* Inc. # of context switches for this new task */ #endif OSTaskCtxSwCtr++; /* Keep track of the total number of ctx switches */ OSIntCtxSw(); /* Perform interrupt level ctx switch */ CPU_INT_EN(); } ********************************************************************* ********************************************************/ 我们也看到了,在这两个函数中都查看了 OSRunning,因为只有这个变量为 1 时, 这个系统才真正能启动多任务处理能力,我们这样看一下 int maint()/*这只是为了举例*/ { 。。。。。。 OSInit (&p_err); /*OSTaskCreate 这个函数以后会细说的,这里的每个参数这里就不说了*/ OSTaskCreate (OS_TCB task1, OS_ERR p_err;
OSTaskCreate (OS_TCB task2, CPU_CHAR "fisrt_tsk", OS_TASK_PTR task_func1, void *p_arg, OS_PRIO prio1, CPU_STK *p_stk_base, CPU_STK_SIZE stk_limit, CPU_STK_SIZE stk_size, OS_MSG_QTY q_size, OS_TICK time_quanta, void *p_ext, OS_OPT opt, OS_ERR *p_err); CPU_CHAR "second_tsk", OS_TASK_PTR task_func2, void *p_arg, OS_PRIO prio1, CPU_STK *p_stk_base, CPU_STK_SIZE stk_limit, CPU_STK_SIZE stk_size, OS_MSG_QTY q_size, OS_TICK time_quanta, void *p_ext, OS_OPT opt, OS_ERR *p_err); } 这里建了两个任务,而且其实 OSTaskCreate 这里是有调用 OSSched,但在这之 前会先看 OSRunning,因这在这里 这个两个任务建立时很明显,OSRunning 还为 0,这时是在 OSTaskCreate 运行不 到 OSSched 就会退出,所以不会有 任务动作,直到 OSStart (&p_err)这时 OSRunning 为 1,会在这个两任务中找一 个优先级最大的运行,然后以后再 建什么任务,就可以在 OSTaskCreate 调用到 OSSched,如果你这个新建的任务 优先级最高,那么就会直接调度到 这个新建的任务。如果没调用 OSStart,那么这个系系统也就不能真正启动。 OSSchedLockTimeBegin 这个是给任务上锁时读取,定时寄存器的 值, OSSchedLockTimeMax 当解锁时会计算下这次上锁的时间多长,如果比这 个值大,就把这次的上锁时间给这个变量 OSSchedLockTimeMaxCur 看代码,功能好像同上 OSStart (&p_err);
分享到:
收藏