嵌入系统第二讲ucosii内核结构_第1页
嵌入系统第二讲ucosii内核结构_第2页
嵌入系统第二讲ucosii内核结构_第3页
嵌入系统第二讲ucosii内核结构_第4页
嵌入系统第二讲ucosii内核结构_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第二讲 uCOSII内核结构uCOSII在F28377D上的应用 首先是移植uCOSII与CPU相关的代码,这部分是用户根据使用的CPU编写的,分别是OS_CPU.H、OC_CPU_A.ASM和OC_CPU_C.C三个文件。这三个文件确定所使用的CPU的相关代码和硬件配置,包括:临界段代码、使用的定时器,进出中断(每一个任务的切换相当于完成一次中断)的堆栈设置,任务切换函数等。这层是从硬件到软件的第一次扩展。 接下来就是uCOSII与CPU无关的代码,包括:OS_CORE.C、OS_FLAG.C、OS_MBOX.C、OC_MEM.C、OS_MUTEX.C、OS_Q.C、OS_SEM.C、OS_

2、TASK.C、OS_TIME.C、uCOS_II.C、uCOS_II.H以及与应用程序有关的配置文件OS_CFG.H、INCLUDES.H。这些是对硬件到软件的第二次扩展,再上一层就是用户开发的应用软件代码了。文件结构及与硬件的关系聚焦您的关注 | FOCUS ON YOUR FOCUS 临界段代码是那些不能有中断嵌入的代码,在处理这些代码的时候,需要两个宏在处理临界段时关中断,处理完毕后再开中断。这两个宏分别是OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。F28377D移植时,在OS_CPU.H中定义这两个宏:#define OS_CRITICAL_METHO

3、D 1#if OS_CRITICAL_METHOD=1#define OS_ENTER_CRITICAL() asm( setc INTM) /进入临界宏代码#define OS_EXIT_CRITICAL() asm( clrc INTM)/出临界宏代码#endif 可以在OS_CPU.H中可以看到有三种处理方法,其它两种就不作介绍了,F28377D采用第一种方法:用CPU指令“setc INTM”关中断,用CPU指令“clrc INTM”开中断临界段聚焦您的关注 | FOCUS ON YOUR FOCUS 任务通常是一个无限循环。它所具有的特征如下:void Task1 (void *pd

4、ata) while(1) /*这里添加用户代码*/ /*这里添加uCOSII的功能函数,如OSFlagPend()、OSTimeDly()等*/ /*这里可以再次添加用户代码*/ 任务聚焦您的关注 | FOCUS ON YOUR FOCUS在任何时候,任务的状态一定是在以下5种状态之一,如果没有任务在运行,uCOSII会执行空闲任务即OSTaskIdle()睡眠状态:指任务驻留在程序空间(ROM或RAM)还未交由uCOSII来管理。交出是通过OSTaskCreate()或OSTaskCreateExt()的两者之一来实现的。就绪状态:任务一旦创建就进入了就绪态准备运行。任务的建立可以是在多任

5、务运行开始前,也可以动态地由一个运行着的任务建立。一个任务可以通过调用OSTaskDel()返回到睡眠态或让另一个任务进入睡眠态。运行状态:调用OSStart()可以启动多任务。任何时刻只能有一个任务处于运行态。就绪的任务只有当所有优先级高于这个任务的任务都转为等待状态或者是被删除才能进入运行态。等待状态:正在运行的任务可以通过调用OSTimeDly()或OSTimeDlyHMSM()将自身延迟一段时间。这个任务将进入等待状态直到函数中定义的延迟时间到。同时,这两个函数会产即强制执行任务切换,让下一个优先级最高并处于就绪态的任务运行。等待时间过去后,OSTimeTick()会使延迟了的任务进入

6、就绪态。正在运行的任务也可能在等待某一事件的发生,如使用了OSFlagPend()、OSSemPend()、OSMutexPend()、OSMboxPend()或OSQPend()。如果事件未发生,调用这些函数的任务就进入了等待状态直到等待的事件发生。中断服务状态:正在运行的任务如果被中断,就会进入中断服务态。响应中断时,正在执行的任务会被挂起。中断服务子程序可能会发送事件发生而使其它任务进入就绪态,并在中断服务子程序返回前判断被中断任务和中断进入就绪状态任务的优先级,从而决定哪个任务运行。任务状态聚焦您的关注 | FOCUS ON YOUR FOCUS 一旦任务建立,一个任务控制块OS_TC

7、B就被赋值。任务控制块是一个数据结构,在uCOS_II.h中声明。当任务的CPU使用权被剥夺时,uCOSII用它来保存该任务的状态。当任务重新得到CPU使用权时,任务控制块能确保任务从当时被中断的那一时丝毫不差地继续执行。 任务控制块通过任务控制块初始化函数OS_TCBInit()进行初始化。这个函数在OS_CORE.C中。任务控制模块聚焦您的关注 | FOCUS ON YOUR FOCUS 每个任务都赋予了不同的优先级,从0级到最低优先线OS_LOWEST_PRI(),当UCOSII初始化时,最低优先级总是被赋给空闲任务。(见OS_CFG.H)。 每个就绪的任务都放在就绪表中,就绪表有2个变

8、量OSRdyGrp和OSRdyTbl。在OSRdyGrp中,任务按优先级每8个任务分为一组。OSRdyGrp中的每一位表示8组任务中每一组是否有进入就绪的任务。任务进入就绪态时,就绪表OSRdyTbl中的相应元素的相应位就置为1,而OSRdyTbl所属的OSRdyGrp相应位也就置1。例如,当OSRdyTbl4中的任何一位是1时,OSRdyGrp的第4位就置1。 为确定下一次该哪个优先级的任务运行,UCOSII中的调度器总是将最低优先级的任务在就绪表中相应字节的相应位置1。 这两个变量在ucos_ii.h中声明。任务优先级的低3位用于确定任务在OSRdyTbl中的所在位。接下来的3位用于确定是

9、在OSRdyTbl数组的第几个元素。 然后配合OSUnMapTbl(在os_core.c中)这样就可以找出进入就绪态的优先级最高的任务。例如OSRdyGrp的值为0 x68,则查OSUnMapTblOSRdyGrp的值为3,然后查OSUnMapTblOSRdyTbc3,假设此时OSRdyTbl3的值是0 xE4,则为2,于是任务优先级就等于(3*8+2)=26。利用这个优先级的值,但任务控制块优先级表OSTCBPrioTbl即得到指向相应任务的任务控制块OS_TCB。就绪表聚焦您的关注 | FOCUS ON YOUR FOCUSUCOSII总是运行进入就绪态任务中优先级最高的任务。确定哪个任务

10、优先级最高,该哪个任务运行是由调度器完成即函数OSSched()。这个函数可以在os_core()中找到。SOSched()主要完成以下2步:将被挂起任务的CPU寄存器推入堆栈,然后将较高优先级任务的寄存器值从栈中恢复到寄存器中。为了完成任务切换,将运行OS_TASK_SW()宏,这是人为的模仿一次中断,在F28377D中即运行一个软件中断,例如将它定义成:#define OS_TASK_SW() asm(“ TRAP #30”)即执行一次用户11中断。然后将中断矢量链接到OSCtxSw()(这个函数是用户需要根据CPU来编写的),OSCtxSw()将OS_TCBHighRdy指向即将被挂起的

11、任务,并让当前任务控制块OSTCBCur指向即将被挂起的任务。任务调度聚焦您的关注 | FOCUS ON YOUR FOCUS如前所述,调用OS_TASK_SW()后需完成任务切换,步骤如下:第一步:OSTCBCur指向即将被挂起的任务(低优先级的任务)第二步:CPU的堆栈指针(SP寄存器)指向即将被挂起任务的栈顶第三步:OSTCBHighRdy指向任务切换后运行的任务的任务控制块OS_TCB第四步:OS_TCB中的OSTCBStkPtr指向即将运行的任务的栈顶第五步:即将运行的任务的堆栈中存有准备装回到CPU寄存器中的一些值,这些值是在上一次任务切换时保存下来的。在执行OSCtxSW()时应

12、该完成:1. 进入中断2. 保存通用寄存器3. 堆栈指针寄存器被保存在当前任务的OS_TCB中。4. 将OSTCBHighRdy复制到OSTCBCur中5. 从OS_TCB中找出将要重新开始运行的任务的堆栈指针,装入CPU的SP寄存器中。6. 按相反的方向从堆栈中弹出通用寄存器7. 中断返回任务级的任务切换聚焦您的关注 | FOCUS ON YOUR FOCUS 任务开始时需要调用OSSchedlock()函数用于禁止任务调度,任务完成后调用解锁函数OSSchedUnlock()。变量OSLockNesting为OSSchedLock()函数调用的次数进行计数,以允许嵌套的函数包含临界段代码,

13、这段代码其他任务不得干预。UCOSII允行嵌套深度达255层。当OSLockNesting=0时,便重新允许调度。以上函数和变量可以在os_core.c中找到。调度器上锁与解锁聚焦您的关注 | FOCUS ON YOUR FOCUS UCOSII总会有一个空闲任务,这个任务在没有其它任务进入就绪状态时投入运行。这个空闲任务OSTaskIdle()永远都是最低优先级而且不能被应用软件删除。 UCOSII有一个统计运行时间的任务OSTaskStat()。要使用这个函数需将系统配置常数OS_TASK_STAT_EN置1(OS_CFG.H中)。一旦允许,OSTaskStat()每秒运行1次来计算CPU

14、的利用率,即告诉用户应用程序使用了多少CPU时间,并用百分比表示。这个值存放在OSCPUsage的有符号8位整数中,精度是1%。如果应用程序打算使用统计任务,就必须在初始化时建立的第一个也是唯一的任务中主mf有t统计任务初始化函数OSStatInit()。即在调用系统启动函数OSStart()之前,用户初始代码中必须先建立一个任务,在这个任务中调用系统统计初始化函数,然后再建立应用程序中的其他任务。空闲与统计任务聚焦您的关注 | FOCUS ON YOUR FOCUS USOSII中,中断服务子程序要用汇编语言来写。也可以将服务子程序在C中以函数方式编写,然后在汇编中以调用子程序的方式来调用。

15、 有两个函数用于中断的进出控制,一个是OSIntEnter()和OSIntExit()。中断服务子程序的示意性代码如下:保存全部CPU寄存器;调用OSIntEnter()或OSIntNesting直接加1;if (OSIntNesting =1) OSTCBCur-OSTCBStkPtr = SP;清中断源;重新开中断;执行用户代码做中断服务;调用OSIintExit();恢复所有CPU寄存器;执行中断返回指令; 有些微处理器中断发生时,CPU寄存器是自动入栈的,且若要允许中断嵌套,在中断服务子程序中须重新开中断,这可以视作一个优点。如果中断服务子程序执行得非常快,无须通知任务已经进入了中断服

16、务,只要不在中断服务期间开中断,也无须调用OSIntEnter()或OSIntNesting加1。UCOSII中的中断聚焦您的关注 | FOCUS ON YOUR FOCUS UCOSII需要提供周期性信号源,用于实现时间延时和确认超时。必须在多任务系统启动以后,也就是在调用OSStart()之后,再开启时钟节拍器。换句话说,调用OSStart()之后应做的第一件事是初始化定时器中断。通常容易犯的错误是,将允许时钟节拍器中断放在系统初始化函数OSInit()之后,在启动多任务系统启动函OSStart()之前。 UCOSII中的时钟节拍服务是通过在中断服务子程序中调用OSTimeTick()实现的。OSTimeTick()跟踪所有任务的定时器以及超时时限。时钟节拍中断服务子程序OSTickISR()是用户编写的汇编代码,在F28377D中

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论