论文部分内容阅读
摘 要:在UCOS移植前,必须先要建立一定的硬件环境让其运行。原始的UCOS实际上构成了具体内核中的外层或高层,而真正位于内核底层的则是CPU。而这两者之间就由“硬件抽象层”(HAL)来连接。本文在基于HMS30C7202硬件平台的基础上,详细讲述了UCOS在HMS30C7202移植中,硬件抽象层的实现步骤。
关键词:UCOS移植;硬件抽象层;中断二次跳转
引言
一般常用的嵌入式操作系统和通用操作系统一样,在内核完成了自身的初始化以后便会创建一个shell进程或者相应的窗口。之后,其他应用进程的创建和启动就是这个shell进程或者窗口的事情了。然而,像类似于UCOS这类比较小而是专用的嵌入式操作系统就不同了,内核和应用程序之间没有明确的界限,它们共享一个地址空间,在物理地址或者逻辑地址上都形成一个整体。整个系统的映像中就只有一个入口函数。
UCOS启动中,系统在完成最初的硬件初始化以后便转入由开发者提供的main(),在main()中再调用一个内核函数OSInit()来完成内核的初始化,然后在完成了与应用相关的初始化以后,就可以调用一个内核函数OSStart()启动内核的进程调度。从上面的过程可以看出,main0函数其实是一个回调函数,整个系统的入口其实是在HAL程序中。
HAL简介
一般HAL中包含着特定CPU的汇编语言编写的底层函数和数据结构,例如对CPU内部一些特殊寄存器的设置、开中断/关中断、中断向量的设置等等。
在不同类型的操作系统中,HAL存在的形式也有很大的不同。在一体化内核的Linux操作系统中,不存在独立的HAL。在Linux内核的源码中,目录arch/下面就是依赖于各种不同CPU的底层代码,那就是需要静态连接到内核中的HAL。所以,Linux所需要的就只是一个基本的引导装入程序。一旦内核开始运行,引导装入程序就完成了使命,Linux内核及其应用程序不会调用引导装入程序中的任何一段代码。然而在微内核的UCOS操作系统中,内核引导装入程序与HAL连接在一起,或者说在HAL的基础上构建内核引导装入程序。
在Hms30C7202上构建HAL
Hms30c7202是一款基于ARM720T内核的32位处理器。主要特征如下:更详细的芯片功能介绍请见参考文献。
·内核运行速率可达70MHz
·8KB综合指令/数据的cache
·内存管理单元MMU
·支持小端操作系统
·2KBSRAM可用于内部buffer。
如上所说,在ARM上运行UCOS的HAL要完成系统硬件的初始化和操作系统的引导两个工作。系统的初始化,主要包括下面几个步骤:
·标志整个代码的初始入口点
·设置异常中断向量表
·初始化存储系统
·初始化MMU
·将已经初始化的数据搬运到可写的数据区
·初始化各个模式下的数据栈
·初始化一些特殊外围接口
·安放好中断处理程序
·使能IRQ异常中断
以上的步骤中根据处理器中相应的寄存器,进行数据的读写即可。但是要注意MMU的初始化和中断结构的设计。在Hms30c7202中,对于MMU设置如下:
IMPORT LOPageTable
ldrr0,=LOPageTable
mcr
p15,0,r0,c2,c0,0
mvn
rO,#0
mcr
p15,0,r0,c3,c0,0
mov
rO,#CtrlMMU+CtrlCache+CtrlWBuff
mcr
p15,0,rO,c1,c0,0
首先我们将建立好的页表地址的基址存入寄存器C2(translationtablebase),然后通过寄存器C3设置好内存的访问权限,最后使能MMU单元,CACHE和BUFF。在LOPageTable开始的内存页表中,规划’了4G内存的分配情况。其实根据UCOS的自身特点可以不使用MMU或者将内存映射为1—1的甲板映射就可以。这里将4G的空间划分开来主要是为了更好的通用性,将来如果引导Linux,就也可以使用这段代码。
中断结构和中断处理程序的设计,应该是HAL中最为重要的一个环节。因为UCOS做为一个多任务操作系统,其本质就是在响应系统指定的时钟中断后进行任务切换。为了使中断处理程序的安装更为方便,因此采用了中断二次跳转的方法。首先在ARM处理器定义的中断向量处安放跳转指令,跳转到指定位置后,再进行位置的第二次映射。其中位置的映射是通过一个汇编定义的宏来实现的。其代码如下:
MACRO
$SourceHANDLER$Destination
$Source
subsp,sp,#4
stmfdsp!,{rO}
1drr0,=$Destination
ldr ro.[ro]
strl0,[sp,#4]
Idmfd sp!,{r0,pc}
MEND
这样就可以在程序的任意位置定义自己的中断处理函数,而不必担心因为使用B指令带来的跳转范围的限制问题。以[RQ中断为例:
HandlerlRQ
HANDLERHandlelRQ
IRQ中断发生时,PC指向地址0X18处,在此处放一条:B HandlerlRQ,程序跳转到Handler处,根据宏所定义的操作,PC指向HandlelRQ所代表的地址处。也就是说当IRQ中断发生时,其中断向量已经是HandleFlQ所代表的地址了,从这个地址再映射到UCOS IRQHANDLER就可以正确的实现IRQ中断的响应了。Hms30c7202中其他中断资源也都有自己固定的中断向量地址,也可以使用类似的方法进行处理。在需要用到的中断资源对应的中断向量处,安放相应中断处理函数的起始地址即可。
在UCOS中需要用到一个周期性的中断源来产生系统的时钟节拍。对于Hms 30c7202,可以选择使用WATCHDOGTimer、RTC或者是Timer来实现。这三者都可以实现周期中断,只是操作的难易程度不一样。如果系统要求高精度实时中断,使用Timer比较奸。如果系统要求比较低的话,用RTC实现则十分的简单。不管哪一种方法实现,其中断处理程序是相似的,给出伪代码如下:
XXX_IRQ_Handler
{
清除中断标志位
重新设置中断条件
OSTimeTick()
}
当周期中断发生时,Hms30c7202先进入IRQ中断,再来判别中断源。所以当进入UCOSIRQHANDLER后,在其中因该调用一个C函数来实现中断源的判别和相应处理函数的运行。
EXPORT UCOS IRQHandler
UCOS IRQHandler
stmfdsp!,{rO-r3,r12,1r}
blOSIntEnter
b1C IRQHandler
blOSIntExit
ldrr0,=OSIntCtxSwFlag
ldrrl,[rO]
cmprl,#1
beq_IntCtxSw
ldmfdsp!,{r0-r3,r12,1r}
subs pc,lr,#4
至此,整个HAL的框架已经建好,按照先前提出的步骤和上面讲到的中断处理的方法,编写好整个HAL程序和os cpu a.s和os_cpu_c.c中6个关键的移植函数。再跳转到main()程序入口,初始化UCOS操作系统,创建任务,启动系统时钟,启动系统即可运行自己定义的任务。
结语
对于UCOS来讲,在其运行以前HAL就已经把运行操作系统所必需的硬件环境建立好,并且隐藏了UCOS在调用系统硬件资源时实现的具体操作细节。从这点可以认为简单的HAL其实就是一个硬件资源初始化的程序。然而实际上完全可以基于HAL写一个普通的监控程序或者是引导/装入程序,甚至是一个内核。ARM公司为操作系统的开发提供了一个HAL,称为μHAL。μHAL是一组库程序。ARM公司向用户提供LlHAL的源代码和已经编译好的两个二进制文件,分别用于“半寄宿(semihost)“和独立运行(standalone)。具体内容请见参考文献当然也可以自己编写这些代码,本文就是这种情况。这样做工作量会变大,但是整个程序也许会更加的简练,执行的效率会更高。注:本文中所涉及到的图表、注解、公式等内容请以PDF格式阅读原文。
关键词:UCOS移植;硬件抽象层;中断二次跳转
引言
一般常用的嵌入式操作系统和通用操作系统一样,在内核完成了自身的初始化以后便会创建一个shell进程或者相应的窗口。之后,其他应用进程的创建和启动就是这个shell进程或者窗口的事情了。然而,像类似于UCOS这类比较小而是专用的嵌入式操作系统就不同了,内核和应用程序之间没有明确的界限,它们共享一个地址空间,在物理地址或者逻辑地址上都形成一个整体。整个系统的映像中就只有一个入口函数。
UCOS启动中,系统在完成最初的硬件初始化以后便转入由开发者提供的main(),在main()中再调用一个内核函数OSInit()来完成内核的初始化,然后在完成了与应用相关的初始化以后,就可以调用一个内核函数OSStart()启动内核的进程调度。从上面的过程可以看出,main0函数其实是一个回调函数,整个系统的入口其实是在HAL程序中。
HAL简介
一般HAL中包含着特定CPU的汇编语言编写的底层函数和数据结构,例如对CPU内部一些特殊寄存器的设置、开中断/关中断、中断向量的设置等等。
在不同类型的操作系统中,HAL存在的形式也有很大的不同。在一体化内核的Linux操作系统中,不存在独立的HAL。在Linux内核的源码中,目录arch/下面就是依赖于各种不同CPU的底层代码,那就是需要静态连接到内核中的HAL。所以,Linux所需要的就只是一个基本的引导装入程序。一旦内核开始运行,引导装入程序就完成了使命,Linux内核及其应用程序不会调用引导装入程序中的任何一段代码。然而在微内核的UCOS操作系统中,内核引导装入程序与HAL连接在一起,或者说在HAL的基础上构建内核引导装入程序。
在Hms30C7202上构建HAL
Hms30c7202是一款基于ARM720T内核的32位处理器。主要特征如下:更详细的芯片功能介绍请见参考文献。
·内核运行速率可达70MHz
·8KB综合指令/数据的cache
·内存管理单元MMU
·支持小端操作系统
·2KBSRAM可用于内部buffer。
如上所说,在ARM上运行UCOS的HAL要完成系统硬件的初始化和操作系统的引导两个工作。系统的初始化,主要包括下面几个步骤:
·标志整个代码的初始入口点
·设置异常中断向量表
·初始化存储系统
·初始化MMU
·将已经初始化的数据搬运到可写的数据区
·初始化各个模式下的数据栈
·初始化一些特殊外围接口
·安放好中断处理程序
·使能IRQ异常中断
以上的步骤中根据处理器中相应的寄存器,进行数据的读写即可。但是要注意MMU的初始化和中断结构的设计。在Hms30c7202中,对于MMU设置如下:
IMPORT LOPageTable
ldrr0,=LOPageTable
mcr
p15,0,r0,c2,c0,0
mvn
rO,#0
mcr
p15,0,r0,c3,c0,0
mov
rO,#CtrlMMU+CtrlCache+CtrlWBuff
mcr
p15,0,rO,c1,c0,0
首先我们将建立好的页表地址的基址存入寄存器C2(translationtablebase),然后通过寄存器C3设置好内存的访问权限,最后使能MMU单元,CACHE和BUFF。在LOPageTable开始的内存页表中,规划’了4G内存的分配情况。其实根据UCOS的自身特点可以不使用MMU或者将内存映射为1—1的甲板映射就可以。这里将4G的空间划分开来主要是为了更好的通用性,将来如果引导Linux,就也可以使用这段代码。
中断结构和中断处理程序的设计,应该是HAL中最为重要的一个环节。因为UCOS做为一个多任务操作系统,其本质就是在响应系统指定的时钟中断后进行任务切换。为了使中断处理程序的安装更为方便,因此采用了中断二次跳转的方法。首先在ARM处理器定义的中断向量处安放跳转指令,跳转到指定位置后,再进行位置的第二次映射。其中位置的映射是通过一个汇编定义的宏来实现的。其代码如下:
MACRO
$SourceHANDLER$Destination
$Source
subsp,sp,#4
stmfdsp!,{rO}
1drr0,=$Destination
ldr ro.[ro]
strl0,[sp,#4]
Idmfd sp!,{r0,pc}
MEND
这样就可以在程序的任意位置定义自己的中断处理函数,而不必担心因为使用B指令带来的跳转范围的限制问题。以[RQ中断为例:
HandlerlRQ
HANDLERHandlelRQ
IRQ中断发生时,PC指向地址0X18处,在此处放一条:B HandlerlRQ,程序跳转到Handler处,根据宏所定义的操作,PC指向HandlelRQ所代表的地址处。也就是说当IRQ中断发生时,其中断向量已经是HandleFlQ所代表的地址了,从这个地址再映射到UCOS IRQHANDLER就可以正确的实现IRQ中断的响应了。Hms30c7202中其他中断资源也都有自己固定的中断向量地址,也可以使用类似的方法进行处理。在需要用到的中断资源对应的中断向量处,安放相应中断处理函数的起始地址即可。
在UCOS中需要用到一个周期性的中断源来产生系统的时钟节拍。对于Hms 30c7202,可以选择使用WATCHDOGTimer、RTC或者是Timer来实现。这三者都可以实现周期中断,只是操作的难易程度不一样。如果系统要求高精度实时中断,使用Timer比较奸。如果系统要求比较低的话,用RTC实现则十分的简单。不管哪一种方法实现,其中断处理程序是相似的,给出伪代码如下:
XXX_IRQ_Handler
{
清除中断标志位
重新设置中断条件
OSTimeTick()
}
当周期中断发生时,Hms30c7202先进入IRQ中断,再来判别中断源。所以当进入UCOSIRQHANDLER后,在其中因该调用一个C函数来实现中断源的判别和相应处理函数的运行。
EXPORT UCOS IRQHandler
UCOS IRQHandler
stmfdsp!,{rO-r3,r12,1r}
blOSIntEnter
b1C IRQHandler
blOSIntExit
ldrr0,=OSIntCtxSwFlag
ldrrl,[rO]
cmprl,#1
beq_IntCtxSw
ldmfdsp!,{r0-r3,r12,1r}
subs pc,lr,#4
至此,整个HAL的框架已经建好,按照先前提出的步骤和上面讲到的中断处理的方法,编写好整个HAL程序和os cpu a.s和os_cpu_c.c中6个关键的移植函数。再跳转到main()程序入口,初始化UCOS操作系统,创建任务,启动系统时钟,启动系统即可运行自己定义的任务。
结语
对于UCOS来讲,在其运行以前HAL就已经把运行操作系统所必需的硬件环境建立好,并且隐藏了UCOS在调用系统硬件资源时实现的具体操作细节。从这点可以认为简单的HAL其实就是一个硬件资源初始化的程序。然而实际上完全可以基于HAL写一个普通的监控程序或者是引导/装入程序,甚至是一个内核。ARM公司为操作系统的开发提供了一个HAL,称为μHAL。μHAL是一组库程序。ARM公司向用户提供LlHAL的源代码和已经编译好的两个二进制文件,分别用于“半寄宿(semihost)“和独立运行(standalone)。具体内容请见参考文献当然也可以自己编写这些代码,本文就是这种情况。这样做工作量会变大,但是整个程序也许会更加的简练,执行的效率会更高。注:本文中所涉及到的图表、注解、公式等内容请以PDF格式阅读原文。