新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > μC/OS-II的内核结构

μC/OS-II的内核结构

作者: 时间:2016-10-08 来源:网络 收藏

尽的解释。

OSSched()的所有代码都属临界段代码。在寻找进入就绪态的优先级最高的任务过程

中,为防止中断服务子程序把一个或几个任务的就绪位置位,中断是被关掉的。为缩短切

换时间,OSSched()全部代码都可以用汇编语言写。为增加可读性,可移植性和将汇编语言

代码最少化,OSSched()是用C写的。

3.6 给调度器上锁和开锁(LockingandUnLockingtheScheduler)

给调度器上锁函数OSSchedlock()(程序清单L3.9)用于禁止任务调度,直到任务完

成后调用给调度器开锁函数OSSchedUnlock()为止,(程序清单L3.10)。调用

OSSchedlock()的任务保持对CPU的控制权,尽管有个优先级更高的任务进入了就绪态。然

而,此时中断是可以被识别的,中断服务也能得到(假设中断是开着的)。OSSchedlock()

和OSSchedUnlock()必须成对使用。变量OSLockNesting跟踪OSSchedLock()函数被调用的

次数,以允许嵌套的函数包含临界段代码,这段代码其它任务不得干预。μC/OS-Ⅱ允许嵌

套深度达255层。当OSLockNesting等于零时,调度重新得到允许。函数OSSchedLock()和

OSSchedUnlock()的使用要非常谨慎,因为它们影响μC/OS-Ⅱ对任务的正常管理。

当OSLockNesting减到零的时候,OSSchedUnlock()调用OSSched[L3.10(2)]。

OSSchedUnlock()是被某任务调用的,在调度器上锁的期间,可能有什么事件发生了并使一

个更高优先级的任务进入就绪态。

调用OSSchedLock()以后,用户的应用程序不得使用任何能将现行任务挂起的系统调用。也就是说,用户程序不得调用OSMboxPend()、OSQPend()、OSSemPend()、OSTaskSuspend

(OS_PR1O_SELF)、OSTimeDly()或OSTimeDlyHMSM(),直到OSLockNesting回零为止。因为调度器上了锁,用户就锁住了系统,任何其它任务都不能运行。

当低优先级的任务要发消息给多任务的邮箱、消息队列、信号量时(见第6章任务间通讯和同步),用户不希望高优先级的任务在邮箱、队列和信号量没有得到消息之前就取得了CPU的控制权,此时,用户可以使用禁止调度器函数。

程序清单 L3.9 给调度器上锁

voidOSSchedLock(void)

{

if(OSRunning==TRUE){

OS_ENTER_CRITICAL();

OSLockNesting++;

OS_EXIT_CRITICAL();

}

}

程序清单L3.10给调度器开锁.

voidOSSchedUnlock(void)

{

if(OSRunning==TRUE){

OS_ENTER_CRITICAL();

if(OSLockNesting>0){

OSLockNesting--;

if((OSLockNesting|OSIntNesting)==0){(1)

OS_EXIT_CRITICAL();

OSSched();(2)

}else{

OS_EXIT_CRITICAL();

}

}else{

OS_EXIT_CRITICAL();

}

}

}

3.7 空闲任务(IdleTask)

μC/OS-Ⅱ总是建立一个空闲任务,这个任务在没有其它任务进入就绪态时投入运行。这个空闲任务[OSTaskIdle()]永远设为最低优先级,即OS_LOWEST_PRI0。空闲任务OSTaskIdle()什么也不做,只是在不停地给一个32位的名叫OSIdleCtr的计数器加1,统计任务(见3.08节,统计任务)使用这个计数器以确定现行应用软件实际消耗的CPU时间。程序清单L3.11是空闲任务的代码。在计数器加1前后,中断是先关掉再开启的,因为8位以及大多数16位微处理器的32位加1需要多条指令,要防止高优先级的任务或中断服务子程序从中打入。空闲任务不可能被应用软件删除。

程序清单L3.11μC/OS-Ⅱ的空闲任务.

voidOSTaskIdle(void*pdata)

{

pdata=pdata;

for(;;){

OS_ENTER_CRITICAL();

OSIdleCtr++;

OS_EXIT_CRITICAL();

}

}

3.8 统计任务

μC/OS-Ⅱ有一个提供运行时间统计的任务。这个任务叫做OSTaskStat(),如果用户将系统定义常数OS_TASK_STAT_EN(见文件OS_CFG.H)设为1,这个任务就会建立。一旦得到了允许,OSTaskStat()每秒钟运行一次(见文件OS_CORE.C),计算当前的CPU利用率。换句话说,OSTaskStat()告诉用户应用程序使用了多少CPU时间,用百分比表示,这个值放在一个有符号8位整数OSCPUsage中,精读度是1个百分点。

如果用户应用程序打算使用统计任务,用户必须在初始化时建立一个唯一的任务,在这个任务中调用OSStatInit()(见文件OS_CORE.C)。换句话说,在调用系统启动函数OSStart()之前,用户初始代码必须先建立一个任务,在这个任务中调用系统统计初始化函数OSStatInit(),然后再建立应用程序中的其它任务。程序清单L3.12是统计任务的示意性代码。

程序清单L3.12初始化统计任务.

voidmain(void)

{

OSInit();/* 初始化uC/OS-II(1)*/

/* 安装uC/OS-II的任务切换向量 */

/* 创建用户起始任务(为了方便讨论,这里以TaskStart()作为起始任务)(2)*/

OSStart();/* 开始多任务调度 (3)*/

}

voidTaskStart(void*pdata)

{

/* 安装并启动uC/OS-II的时钟节拍 (4)*/

OSStatInit();/* 初始化统计任务 (5)*/

/* 创建用户应用程序任务 */

for(;;){

/* 这里是TaskStart()的代码!*/

}

}

因为用户的应用程序必须先建立一个起始任务[TaskStart()],当主程序main()调用系统启动函数OSStcnt()的时候,μC/OS-Ⅱ只有3个要管理的任务:TaskStart()、OSTaskIdle()和OSTaskStat()。请注意,任务TaskStart()的名称是无所谓的,叫什么名字都可以。因为μC/OS-Ⅱ已经将空闲任务的优先级设为最低,即OS_LOWEST_PR10,统计任务的优先级设为次低,OS_LOWEST_PR10-1。启动任务TaskStart()总是优先级最高的任务。

图F3.4解释初始化统计任务时的流程。用户必须首先调用的是μC/OS-Ⅱ中的系统初始化函数OSInit(),该函数初始化μC/OS-Ⅱ[图F3.4(2)]。有的处理器(例如Motorola的MC68HC11),不需要“设置”中断向量,中断向量已经在ROM中有了。用户必须调用OSTaskCreat()或者OSTaskCreatExt()以建立TaskStart()[图F3.4(3)]。进入多任务的条件准备好了以后,调用系统启动函数OSStart()。这个函数将使 TaskStart()开始执行,因为TaskStart()是优先级最高的任务[图F3.4(4)]]。



关键词:

评论


相关推荐

技术专区

关闭