首页 ucosii移植过程详解(移植原理)

ucosii移植过程详解(移植原理)

举报
开通vip

ucosii移植过程详解(移植原理)ucosii移植过程详解(移植原理) uCOS-II移值过程实例讲解 我将uCOS-II 移植到了EPONS 的C33209的平台上,接下来我就基于我移植好的代码讲解如何将uCOS-II从一种MCU移植到另一种MCU。 首先介绍uCOS-II的文件,如下表: ucos_ii.h os_cfg.h os_cpu.h os_core.c os_dbg_r.c os_flag.c os_mbox.c os_mem.c os_mutex.c os_q.c os_sem.c os_task.c ...

ucosii移植过程详解(移植原理)
ucosii移植过程详解(移植原理) uCOS-II移值过程实例讲解 我将uCOS-II 移植到了EPONS 的C33209的平台上,接下来我就基于我移植好的代码讲解如何将uCOS-II从一种MCU移植到另一种MCU。 首先介绍uCOS-II的文件,如下表: ucos_ii.h os_cfg.h os_cpu.h os_core.c os_dbg_r.c os_flag.c os_mbox.c os_mem.c os_mutex.c os_q.c os_sem.c os_task.c os_time.c ucos_ii.c os_cpu_c.c os_cpu_a.asm 其中我们和硬件平台相关的文件的文件名被加粗了,也就是说若要将uCOS-II移植到新的平台上只要关心以上四个文件就行了。当然你也可以根据需要再添加你自己的和平台相关的文件,事实上我也是这么做的。在我移植的例子中就添加了四个和平台相关的文件,文件如下表: crt0.c drv_rtc.c vector.c ext.s crt0.c是用来初始化系统的比如说MCU的一些特殊寄存器、设置外围的总线接口,等。drv_rtc.c是用来初始化系统中的一个RTC的,这个RTC可以为内核提供必要的基于时间片调度的时基。同时提供了对RTC开始和停止的操作函数。在我的例子中RTC会每秒产生32次中断。vector.c顾名思义,它是系统上电后为系统提供矢量入口表的文件,当然也包括中断向量表。ext.s是为uc/OS-II提供OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()函数的具体实现以及在用户程序的中断函数出入时要调用的状态保护和状态恢复函数OS_SAVEALL ()和OS_RESTOREALL ()。前面两个函数的功能是:OS_ENTER_CRITICAL()屏蔽中断;OS_EXIT_CRITICAL()恢复原来的中断使能状态。 1. os_cpu_a.asm的说明 要想顺利的移植首先要了解uCOS-II的一些基本概念。 uCOS-II实质上是一个嵌入式操作系统内核,她只负责管理各个任务,为每个任务分配CPU时间,并且负责任务之间的通讯。内核提供的基本服务是任务切换。这是个很重要的概念,可以说你只要掌握了任务切换的本质,可以说你就掌握了移植uCOS-II的技术。至于任务之间的通讯他们是建立在任务切换之上的 或者说和系统平台关系不大(当然这也和操作系统通讯机制的实现相关,至少 uCOS-II是这样的)。 接下来我们就有针对性的介绍什么是uCOS-II里的任务。一个任务通常是一 个无限循环,如下程序所示。 void Task1(void *data) { INT8U err; char *rxmsg; data = data; /* Prevent compiler warning */ while(1) //这是一个无限循环 { rxmsg = (char *)OSMboxPend(MAIL1, 0, &err); /* Wait for message from Task #2 */ OSTimeDlyHMSM(0, 0, 1, 0); /* Wait 1 second */ OSMboxPend(MAIL3, 0, &err); /* Wait for message from Task #3*/ OSMboxPost(MAIL2, (void *)1); /* Acknowledge reception of msg*/ } } 可以通过内核的专用函数来建立、删除、挂起、激活任务,在这里我们的重点在 如何移植,所以具体的使用方式和原理可以看JEAN J.LABROSSE 著、邵贝贝 译的《uCOS-II—源码共开的实时嵌入式系统》一 关于书的成语关于读书的排比句社区图书漂流公约怎么写关于读书的小报汉书pdf 。 (1). OSCtxSw()函数 在上面的例子里你也看到了任务和其他的C函数一样,有函数的返回类型,有 形式参数变量,只是任务是绝不会返回。事实上任务也就是一个函数,内核在调 度时是以这个函数为基础的,为了和其他函数区分,我们给了她另外一个名字——任务。也正因她是一个特殊的函数,而且和内核调度直接相关,所以不能随便 返回和被用户调用,而要用内核的专用函数来“建立”和“删除”。所谓的“建 立任务”其实是在内核处对该函数进行注册和相关数据结构的填充,比如该函数 的入口地址、为函数分配专门的堆栈空间(为什么要为函数分配专门的地址空间 呢,我们马上就会谈到)。“任务调度”就是根据情况(比如时间片被用完),来 调用另一个被称为任务的函数(我们暂时称之为函数TA),同时停止当前的一个 任务(其实也是一个函数,我们称之为TB)。问 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 出来了,若内核象普通函数那 样直接调用TA,那么当内核要重新调用TB时怎么知道刚才TB执行到哪里了 呢,若内核为TA和TB分配专用的两块空间,当内核要调用其他任务(其实就 是函数)的时候先将当前任务(函数)运行的地址和状态保存起来,然后当要返 回前再恢复,当然每个被称之为任务的函数都要有自己独立的保存运行地址和状 态的空间,以免混乱。那问题就很好解决了。这也就是为什么任务都有自己的堆栈空间的原因。 那么新的问题来了,内核是如何调度的呢,在这里我们只关心内核要进行任务调度时发生的情况,而不关心内核为什么及何时要调度任务。这是因为这和移植关系不大,各种内核对任务的调度算法是不同的,解决方案也不同。但这些只是些算法上的区别,和平台关系不大。我们只需要将精力集中在内核决定要调度时会发生的事情。在uc/OS-II中若内核决定要对任务实行调度时最终会调用这个关键的函数void OSCtxSw(void),该函数位于os_cpu_a.asm中。它其实是一个软件中断或陷阱。因此有必要在中断矢量表里分配一个软件 中断向量或陷阱给向量该函数。在我例子中的Vector.c文件中可以很清楚的看到我分配了一个软件中断向量给该函数。在os_cpu_a.asm文件中除了OSCtxSw()函数外你还看到了三个用汇编编写的函数,我会依次介绍。如下是OSCtxSw()函数的源代码。 OSCtxSw: pushn %r15 ; 将r1~r15寄存器压入当前任务堆栈,(r1~r15是C33中的CPU寄存器) ld.w %r0,%ahr ; 将状态寄存器的 内容 财务内部控制制度的内容财务内部控制制度的内容人员招聘与配置的内容项目成本控制的内容消防安全演练内容 转存入r0,r1寄存器 ld.w %r1,%alr ; pushn %r1 ; 将状态寄存器压入堆栈 ld.w %r4,%sp ; 将当前的SP指针内容保存入r4 xld.w %r5,[OSTCBCur] ; 将当前SP指针内容存入uc/OS-II的一个数据结构: ld.w [%r5],%r4 ; OSTCBCur->OSTCBStkPtr中 xcall OSTaskSwHook ; 调用用户接口函数,允许用户在任务切换时做一些工作 xld.w %r4,[OSTCBHighRdy] ; 得到要切换的任务的TCB块 xld.w %r5,OSTCBCur ; 将要切换到的任务TCB块放到当前TCB块 xld.w [%r5], %r4 ; xld.w %r5,OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy,保存要切换到的任务优先级 ld.b %r4,[%r5] xld.w %r5,OSPrioCur xld.b [%r5],%r4 xld.w %r5,[OSTCBHighRdy] ; SP = OSTCBHighRdy->OSTCBStkPtr,得到要切换到的 ld.w %r4,[%r5] ; 任务SP指针 ld.w %sp, %r4 popn %r1 ld.w %alr,%r1 ; 从要切换到的任务SP指针中恢复状态寄存器ld.w %ahr,%r0 popn %r15 ; 从要切换到的任务SP指针中恢复r1~r15寄存器 reti ; 从要切换到的任务SP指针中中断返回,这时自然就回到了要切换到的任务 该函数是用汇编写的,这就很直接的说明了一个问题——这个函数和uCOS-II的移植直接相关。OSCtxSw()人为的模仿了一次中断,大多数MCU提供软件中断或陷阱指令来实现这样的操作。必须提供中断向量给汇编语言函数OSCtxSw()。任务切换很简单,将被挂起任务的微处理器寄存器推入堆栈,然后将较高优先级的任务的寄存器值从堆栈中恢复到寄存器中。在uCOS-II中,就绪任务的堆栈结构总是看起来跟刚刚发生过中断一样,所有的微处理器的寄存器都保存在堆栈中。 (2). OSStartHighRdy()函数 在掌握了最关键的一个汇编函数后我们再来看看其他汇编函数。OSStartHighRdy(),顾名思义是操作系统开始工作时调用最高优先级任务的函数。它是在OSStart ()中被调用的,其实它的原理很简单,你只要理解了OSCtxSw()函数就能很轻易的理解它。我们先回顾一下刚才的话“就绪任务的堆栈结构总是看起来跟刚刚发生过中断一样”,那么在操作系统初始化结束,但还未进行调度时任务的堆栈结构又是什么样子的呢,uCOS-II是这样做的,她在初始化时将所有已建立任务的堆栈结构初始化,并把任务的首地址放在堆栈中。同时任务的堆栈指针指向栈顶。当系统启动开始执行第一个任务(当然是最高优先级的任务)时就调用OSStartHighRdy(),该函数会恢复要执行的任务的状态。在它返回时并没有使用普通的ret指令而是利用reti指令将初始化时由操作系统添入的任务的首地址和状态寄存器弹弹出,(单片机在进入中断时一般会自动将状态寄存器和PC指针同时入栈,所以在中断返回时要调用专用的reti指令,它会将状态寄存器和PC指针同时出栈。而正常的函数调用时状态寄存器是不会自动保存的,所以ret函数也不会同时恢复状态寄存器)这样第一个任务就启动了。 从中你应该可以看出OSCtxSw()和OSStartHighRdy()的相似之处了吧,OSCtxSw()是要将挂起任务的状态保存,然后恢复要运行的任务的状态。而OSStartHighRdy()只需要将要运行的任务的状态恢复就行了。所以这部分源代码也非常相似,你自己也一定看得懂。 (3). OSIntCtxSw()函数 接下来我们来看看OSIntCtxSw()函数,该函数是在中断中对任务进行切换时被OSIntExit()调用的。注意因为是在中断中被调用的,所以OSIntCtxSw()认为所有状态寄存器已经被保存。用户在中断中要进行任务调度时尤其要注意这点。还有,要强调OSIntCtxSw()是在OSIntExit()中被调用的,而OSIntExit()要和OSIntEnter()成对使用,即用户想在中断函数中调度任务的话一定要在进入中断时调用OSIntEnter()在离开中断前调用OSIntExit()。别忘了~还要在一进入中断时最先调用OS_SAVEALL()它会帮你把所有的寄存器都保存起来,在即将退出中断前调用OS_RESTOREALL()。OSIntCtxSw()的原理也和OSCtxSw()相似,只是少了保存状态寄存器这一环而已。值得一提的是OSIntCtxSw()是在OSIntExit()中被调用的,而在OSIntCtxSw()返回时就进入了新的任务,并不是从中断返回时再进入新的任务的,因此在OSIntCtxSw()里首先要调整堆栈指针的位置。 (4). OSTickISR()函数 接下来我们来看看最后一个函数OSTickISR(),这个函数其实就是一个时钟中断函数,就是它为系统提供所谓的时间片。既然作为一个中断函数你就必须给他分配中断向量。在我的Vector.c文件中你也能看到。它还会为一个称之为OSIntNesting的全局变量加一,为什么加一我们就不讨论了。反正你要移植的时候也别忘了给OSIntNesting变量加一就行了。 2. os_cpu_c.c的说明 和os_cpu_a.asm一样,os_cpu_c.c也是和移植密切相关的一个文件,只不过是用C语言写的。在该文件中最重要的是如下这个函数: OS_STK *OSTaskStkInit (INT32U *pd, void *pdata, INT32U *ptos, INT16U opt) { INT32U *stk; opt = opt; /* 'opt' is not used, prevent warning */ stk = (INT32U)ptos; /* Load stack pointer */ *stk-- = (INT32U)pd;//return address *stk-- = (INT32U)0x10;//psr, Interrupts enabled *stk-- = (INT32U)0;//r15 *stk-- = (INT32U)0;//r14 *stk-- = (INT32U)0;//r13 *stk-- = (INT32U)0;//r12 *stk-- = (INT32U)0;//r11 *stk-- = (INT32U)0;//r10 *stk-- = (INT32U)0;//r9 *stk-- = (INT32U)0;//r8 *stk-- = (INT32U)0;//r7 *stk-- = (INT32U)0;//r6 *stk-- = (INT32U)0;//r5 *stk-- = (INT32U)0;//r4 *stk-- = (INT32U)0;//r3 *stk-- = (INT32U)0;//r2 *stk-- = (INT32U)0;//r1 *stk-- = (INT32U)0;//r0 *stk-- = (INT32U)0;//alr *stk = (INT32U)0;//ahr return ((void *)stk); } 我们再次回顾一下“就绪任务的堆栈结构总是看起来跟刚刚发生过中断一样”这句话,那么在你要移植的系统初始化时要将任务堆栈变成什么样子呢,通
本文档为【ucosii移植过程详解(移植原理)】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_003124
暂无简介~
格式:doc
大小:25KB
软件:Word
页数:0
分类:生活休闲
上传时间:2017-10-16
浏览量:28