您好,欢迎访问三七文档
实时操作系统(RTOS)RTOS是一段嵌入在目标代码中的程序,系统复位后首先执行,相当于用户的主程序,用户的其它应用程序都建立在RTOS之上。不仅如此,RTOS还是一个标准的内核,将CPU时间、中断、I/O、定时器等资源都包装起来,留给用户一个标准的API,并根据各个任务的优先级,合理地在不同任务之间分配CPU时间。RTOS是针对不同处理器优化设计的高效率实时多任务内核,RTOS可以面对几十个系列的嵌入式处理器MPU、MCU、DSP、SOC等提供类同的API接口,这是RTOS基于设备独立的应用程序开发基础。优秀RTOS上跨处理器平台的程序移植只需要修改1-4的内容。在RTOS基础上可以编写出各种硬件驱动程序、专家库函数、行业库函数、产品库函数,和通用性的应用程序一起,可以作为产品销售,促进行业的知识产权交流,因此RTOS又是一个软件开发平台。RTOS的基本结构RTOS最关键的部分是实时多任务内核,它的基本功能包括任务管理、定时器管理、存储器管理、资源管理、事件管理、系统管理、消息管理、队列管理、旗语管理等,这些管理功能是通过内核服务函数形式交给用户调用的,也就是RTOS的API。ARM7启动顺序ARM7启动过程嵌入式系统资源有限,程序通常都固化在ROM总运行。ROM中程序执行前,需要对系统硬件和软件运行环境进行初始化,这些工作是用汇编语言编写的启动程序完成。启动程序是嵌入式程序的开头部分,应与应用程序一起固化在ROM中,应首先在系统上运行的启动程序应包含各模块中可能出现的所有段类,并合理安排他们的次序。BootLoade设计BootLoader概念在嵌入式系统中,通常没有像PC机BIOS那样的固件程序,因此整个系统的加载启动任务就完全由BootLoader来完成。对于我们的实验开发板,由于flash接的是微处理器Bank0的片选信号。映射的地址为0x00000000。而实验系统在上电或复位时从地址0x00000000处开始执行,所以在这个地址处安排系统的BootLoader程序。由于BootLoader与硬件结合非常紧密,所以对于不同结构的CPU其BootLoader程序都是不同的。BootLoader总体设计Stage1\stage2\根文件和映像文件关系如图BootLoader的stage1完成以下功能:(1)硬件设备初始化。(2)设置堆栈。(3)为加载BootLoader的stage2准备RAM空间(4)拷贝BootLoader的stage2到RAM空间中。(5)跳转到stage2的C入口点.BootLoader的stage2必须完成以下功能:(1)初始化本阶段要使用到的硬件设备。(2)将kernel映像和根文件系统映像从flash上读到RAM空间中。(3)为内核设置启动参数。(4)调用内核。uClinux根文件及系统映象文件对于uClinux根文件系统的制作则使用uClinux的dist包,在宿主机的Linux环境下通过makemenuconfig命令来完成对根文件系统的配置,编译,连接等一系列工作,生成所需要的根文件系统映象文件。注意:不同CPU,依赖于CPU体系结构的代码。设备初始化代码都放在stage1中,并且都用汇编语言来实现,以达到短小精悍的目的。而stage2则用C语言来实现,实现系统功能。BootLoader实现BootLoaderStage1功能术语解释映象文件(IMAGE):指一个可以执行的文件,ELF格式.段(section):描述映象文件的代码或数据块。RO:是Read-only的简写形式.一般存放的代码。RW:是Read-write的简写形式。一般是存放初始化的数据。ZI:是Zero-initialized的简写形式。一般是存放零初始化数据。输入段(inputsection):它包含代码、初始化数据或描述了在应用程序运行之前必须要初始化为0的一段内存。输出段(outputsection):它包含一系列具有相同R0,RW,ZI属性的输入段。域(Regions):在一个映象文件中,一个域包含了1-3个输出段。多个域组织在一起就构成了最终的映象文件1、硬件的初始化目的:为stage2的执行以及随后的kernel的执行准备好一些基本的硬件环境1).屏蔽所有的中断。为中断提供服务是操作系统的设备驱动程序的责任,因此在BootLoader的执行全过程中不必响应任何中断。中断屏蔽可以通过写ARM的CPSR寄存器来完成PI。2).设置CPU的速度和时钟频率。3)堆栈初始化。设置堆栈指针是为执行C语言代码作准备。把sp的值设置在RAM空间距最顶端1.5KB的地方(堆栈向上生长)。因为在不同的工作模式下所访问的堆栈指针寄存器(R13)不同,所以要初始化各种工作模式的堆栈。4).RAM初始化。包括正确地设置系统内存控制器的功能寄存器以及各内存库控制寄存器等共有13个需要初始设置的寄存器.2、为stage2准备RAM空间S3C44BOX开实验板来说,在Bank6的片选信号上我们接了8m的SDRAM,而Bank6映射的起始地址为OXOCOOOOOO,进而RAM的空间范围为OxOcOOOOOO-OxOc7fffff3、拷贝stage2到RAM设计了一个拷贝程序,负责将stage2的代码搬运到RAM中,让它在RAM中运行,以获得更快的速度。在上述一切都就绪后,就可以跳转到BootLoader的stage2去执行了。在ARM系统中,通过修改PC寄存器为合适的地址来实现。BootLoaderStage2的功能stage2的代码用C语言实现,以便于实现更复杂的功能和取得更好的代码可读性和可移植性。当stage1的工作完成,为stage2准备好运行环境后就可以跳转进main()函数了。直接把main()函数的起始地址作为整个。stage2执行映像的入口点是最直接的想法。但是这样做将无法处理main()返回的情况。为解决这个问题,可以写一段ARM的汇编程序,作为main()函数的外部包裹。1、硬件初始化1)初始化I/0端口及两个串口,以便对终端用户输出I/0信息及与GPRS模块通信2)设定系统主频2、内核映象文件及根文件系统的下载将uClinux的内核及根文件系统的映象文件下载到开发板上需要两个途径(1)利用网口,使用TFTP下载;(2)利用串口下载;(在PC上的串口工具都有发送文件的功能,传输内核和根文件系统映象文件的到SDRAM)3、加载内核映像和根文件系统映像对内存进行规划时包括两方面:(1)内核映像所占用的内存范围,基地址和映像的大小;(2)根文件系统所占用的内存范围,基地址和映像的大小。uClinux映象文件的执行方式:(1)一种方式是内核映象文件直接在FLASH中运行。(2)另一种方式是先将其解压到SDRAM中,再在SDRAM中运行。对于内核映像,因为嵌入式Linux的内核一般都不操过1MB,所以我们将其拷贝到SDRAM地址OxOc300000处。这样当开始启动uClinux时,压缩的uClinux内核将自动解压到0X0c008000处开始运行。当然也可以修改为其它的地址范围,但这样做就需要对uClinux源代码包的、kefile文件进行相应的修改,操作起来非常麻烦,所以我们不对它进行改动。对根文件系统映像,我们将其拷贝到。x0c000000+0x00100000开始的地方。像ARM这样的嵌入式微处理器都是在统一的内存地址空间中寻址Flash等固态存储设备的,所以从Flash上读取数据与从RAM单元中读取数据的操作并没有什么不同。4、调用内核BootLoader调用Linux内核的方法是直接跳转到内核的第一条指令处,对S3C44BOX来说也即直接跳转到0x0c300000地址处.当调转后uClinux就开始启动。我们的BootLoader使用mrun命令,设置启动参数,将内核映象从flash拷贝到地址0x0c300000处,并开始运行,将控制权交给操作系统,进而启动操作系统。由于mrun命令使用的函数调用及宏定义比较多,这里就不给出源代码了。完成了上述任务以后,BootLoader设计完成ARM系统引导启动程序一般流程如下:(1)设置入口指针(2)设置中断向量ARM7要求中断向量必须设置从0地址开始,连续8*4字节的空间,分别是复位、未定义指令错误、软件中断、预取指令中断、数据存取错误、IRQ、FIQ和一个保留的中断向量(如果ROM位于0地址,向量表包含一系列指令跳转到中断服务程序,否则向量必须被动态初始化。可以在启动程序中添加一段代码,使其在运行时将向量表拷贝到0地址开始的存储空间)对于各未用的中断,用一个只包含返回指令的哑函数,以防止错误引起系统的混乱。(3)初始化堆栈和寄存器取决于使用了哪些中断,一般系统需要处理哪些错误类型。一般来说管理者堆栈必须设置,如果使用了IRQ中断,则IRQ堆栈必须设置。如果系统使用了DRAM或者其他的外设,则需要设置相关的寄存器,以确定其刷新频率,数据总线宽度等信息(4)初始化存储器系统有些芯片可通过寄存器编程初始化存储器系统,而对于复杂系统通常集成了MMU来管理内存(5)如果有必要改变处理器模式、状态如果系统应用程序是运行在用户模式下,可在此处将系统改为用户模式并初始化用户的堆栈指针。(6)初始化C语言所需要的存储器空间为正确运行应用程序,在初始化期间应将系统需要读写的数据和变量从ROM拷贝到RAM里;一些要求快速响应的程序,如中断处理程序,也需要在RAM中运行;如果使用FLASH,对FALSH的檫除和写入也一定要在RAM里运行。ARM公司软件开发工具包中链接器提供了分布装载的功能,可实现这一目的。(7)呼叫C语言ARM有两种指令集:16位的Thumb指令集和32位的指令集。使用16位的存储器可以降低成本,在这种情况下,Thumb指令集的整体执行速度要比ARM32位指令集体,而且提高了代码密度,所以一般用Thumb编译器将C语言程序编译成16位代码。处理器在一开始总是处于ARM状态,可使用BX指令转换到Thumb状态呼唤C语言程序,要注意的是用C语言编写的嵌入式程序时,要避免使用不能被固化到ROM的库函数。技术难点分析----MMU的使用MMU是存储器管理单元的缩写,是用来管理虚拟内存系统的器件。MMU通常是CPU的一部分,本身有少量的存储空间存放从虚拟地址到物理地址的匹配表。此表称作TLB(转换旁置缓冲区)。所有数据请求都送往MMU,由MMU决定数据只在RAM中还是在大容量的存储器设备内。如果数据不在存储空间内,MMU将产生页面错误中断MMU的两个主要功能是:将虚拟地址转换为物理地址控制存储器存取允许。MMU关掉时,虚地址直接输出到物理地址总线。使用MMU解决了以下几个问题:a.使用DRAM作为大容量存储器时,如果DRAM行列是非平方的,会导致该DRAM的物理地址不连续,这将给程序的编写调试造成极大的不方便,而适当的配置MMU可将其转换成虚拟地址连续的空间b.ARM内核的中断向量表放在0地址,对于ROM在0地址的情况,无法调用中断服务程序,所以在调试阶段有必要将可读写的存储器空间映射到0地址。c.系统的某些地址是不允许被访问的,否则会产生不可预料的后果,为避免这类错误,可以通过MMU匹配表的设置将这些地址设为用户不可以存取类型;d.启动程序中生成的匹配表中包含地址映射,存储页面大小(1M、64K或者4K)以及是否允许存取等信息。ARM系统初始化1、Bootloader引导程序Bootloader是由汇编语言编写的芯片引导程序。它固化在目标板的ROM中,用于启动存放在RAM中或者ROM中的嵌入式软件的程序。如果CPU支持,在bootloader开发过程中也可以将它放在RAM中运行。在嵌入式ucLinux的开发中,首先要根据硬件目标板的特性开发出bootloader程序,以完成下面的任务:1.1初始化处理器使用bootloader初始化处理器中的一些配置寄存器。比如:如果需要使用ARM72
本文标题:ARM速成教材
链接地址:https://www.777doc.com/doc-23721 .html