DIY编程器网
标题:
基于μC/OS-Ⅱ在ARM7上移植方法的探讨与实现
[打印本页]
作者:
liyf
时间:
2012-1-16 18:42
标题:
基于μC/OS-Ⅱ在ARM7上移植方法的探讨与实现
随着嵌入式技术的快速发展,实时多任务操作系统作为一种软件平台已逐步成为国际嵌入式系统的主流,目前世界上已经有一大批成熟的实时嵌入式操作系统。
通常,对嵌入式软件的基本要求是体积小、指令速度快、具有较好的裁减性和可移植性,目前,实时操作系统很多,如vxworks,windows ce,psos,qnx,lynxos等,这些操作系统都具有高可靠性、强实时性等特点,但他们都是商业操作系统,价格昂贵,人们往往很难接受,μc/os-ⅱ操作系统的出现是对这些商业操作系统的一个很大的冲击。
1 μc/os-ⅱ操作系统简介
μc/os-ⅱ是源码公开的实时操作系统,是一个自由操作系统。程序开发人员可以改写源代码,使之符合自己的要求,裁减掉不需要的部分,使操作系统变得小巧、灵活、并且能满足用户特定操作系统的需要。为了提高系统的实时能力,μc/os-ⅱ可以将一个复杂的应用划分为多个相互独立的任务,并根据任务的重要性来分配优先级。任务的调度完全由μc/os-ⅱ的实时内核完成,主要包括任务的状态管理、选择最高优先级的任务、执行任务和撤销任务等,μc/os-ⅱ内核还负责cpu时间分配,cpu时间总是优先分配给中断事件,其次是任务队列中当前优先级最高的任务,不同任务间的通信可以通过μc/os-ⅱ提供的信号量、邮箱、信息队列等机制完成,他的绝大部分代码是用c语言编写的,可移植性强,因此1997年以后,在国际上逐渐被广泛采用。
2 其软硬件体系及可移植性分析
μc/os-ⅱ核心代码很小,程序开发人员要把他移植到自己的目标板中只需做少量的工作。图1是基于μc/os-ⅱ的嵌入式系统的软硬件体系结构。
(3)os_stk_growth
μc/os-ⅱ使用结构常量os_stk_growth指定堆栈的生长方式,其代码为:
#define os_stk_growth 1
3.2.2 os_cpu_c.c
包含了与移植有关的c函数,包括堆栈的初始化和一些钩子函数的实现,但是最重要的是ostaskstkinit()函数,该函数是在用户建立任务时系统内部自己调用的,用来对用户任务的堆栈初始化。在arm7体系结构下,任务堆栈空间由高至低递减,依次保存着pc,lr,r12,…,r1,r0,cpsr的初始化堆栈结构,当用户初始化了堆栈,ostaskstkinit()就返回新的堆栈指针stk所指的定地址。ostaskcreate()和ostaskcreateext()会获得该地址并将他保存到任务控制块tcb中,其他的几个钩子函数必须声明,但可以不包含任务代码,这些钩子函数在本移植中全为空函数。
3.2.3 os_cpu_a.s
μc/os-ⅱ移植的绝大部分工作都集中在os_cpu_a.s文件的移植上,在这个文件里,最困难的工作又集中体现在osintctxsw和ostickisr这两个函数的实现上。这是因为这两个函数的实现是和移植者的移植思路以及相关硬件定时器、中断寄存器的设置有关,在实际的移植工作中,这两个地方也是比较容易出错的地方,这部分需要对处理器的寄存器进行操作,所以必须用汇编语言编写,包括4个子函数:osstarthighrdy()、osctxsw()、osintctxsw()、ostickisr()。
osstarthighrdy()该函数首先调用钩子函数ostaskswhook(),然后将osrunning标志位设置为真,表示任务开始执行,从而保证任务切换操作的正确执行,紧接着从具有最高优先级的任务控制块中取得任务的堆栈指针,初始化堆栈指针寄存器sp,然后恢复其他的寄存器,开始执行最高优先级的任务。
osctxsw()该函数在任务级任务切换函数中调用,首先保存处理器寄存器,将当前sp存入任务tcb中,载入就绪最高优先级任务的sp,从新任务的任务堆栈中恢复处理器所有寄存器的值,然后执行中断返回指令。
osintctxsw()该函数是在isr中执行任务切换功能,其原理基本上与任务级的切换相同,区别只是isr已经保存了cpu的寄存器,因此不要再进行类似的操作,只需对堆栈指针作相应的调整即可。
ostickisr()该函数是系统时钟节拍中断服务函数,首先要保存处理器寄存器,接着调用osintenter()函数,以保证中断嵌套层数不超过255层,如果满足了该条件,则把堆栈指针保存到当前任务的任务控制块tcb中,然后给产生中断的设备清中断,重新允许中断,接下来调用ostimetick()来维持μc/os-ⅱ内部的定时以及调用osintexit()函数决定是否因为这个中断服务程序的执行,使得更高优先级的任务就绪。
4 μc/os-ⅱ的测试
做完移植工作以后,就要测试移植是否正确,这其实是移植过程的最后一步,应该首先不加任何用代码来测试移植好的μc/os-ⅱ,即应该首先测试内核自身的运行状况,这样做的目的是如果有些部分未能正常工作,那就是移植本身的问题,而不是应用代码产生的问题,主要分为以下几个步骤来进行移植的测试:
首先,必须了解处理器所使用的编译器系统,这个步骤取决于使用的编译器,在这期间是无代码的测试,其次,要验证ostaskstkinit()和osstarthighrdy()函数,在os_cfg.h文件中设置os_task_stat_en为0,只让一个空闲任务os_taskidle()运行,检查是否出错,然后需要验证任务级切换osctxsw()函数,在测试任务tasktest()中加入ostimedly()函数,ostimedly()函数接着调用os_sched(),os_sched()调用汇编语言编写的函数osctxsw()函数,如果是正确配置了swi,cpu就会开始执行osctxsw(),最后,需要验证osintctxsw()和ostickisr()函数。
当上述的这些测试步骤都成功后,可以尝试运行一些具体的任务,按照由简到繁的过程不断使测试变得复杂,来进一步验证内核的稳定性和系统性能。
这里建立了一个简单的led灯闪烁控制任务,其代码如下:
加载后,led灯闪烁控制正常,则测试成功,内核正常运转,若测试出现问题,就要认真找出问题所在,不可忽略硬件的问题,还有编译器等,当然也可以采用其他的测试,如串口的测试等。
5 结语
以上所述为μc/os-ⅱ在arm7上移植的通用方法,但针对不同的处理器还需要作适当的修改,rtos是当今嵌入式应用的热点,应用rtos,可以提高产品的可靠性,降低研发周期,其中μc/os-ⅱ具有很好的实时性和很小的代码量,占用空间少,执行效率高,移植方法相对简单,因此掌握μc/os-ⅱ的移植方法是相当重要的。
欢迎光临 DIY编程器网 (http://diybcq.com/)
Powered by Discuz! X3.2