1k likes | 1.35k Vues
《 嵌入式系统原理与应用 》. 2008 年秋季. 第 5 章 嵌入式系统开发过程及软件设计. 第 5 章 嵌入式系统开发过程及软件设计. 本章主要介绍以下内容: 嵌入式软件开发特点 嵌入式软件开发流程 常用的调试方法 操作系统和开发工具 板级支持包 BootLoader 介绍 嵌入式软件开发过程. 5.1 嵌入式软件开发的特点. 需要交叉开发环境 。交叉开发环境是指实现编译、链接和调试应用程序代码的环境。与运行应用程序的环境不同,它分散在有通信连接的宿主机与目标机环境之中。
E N D
《嵌入式系统原理与应用》 2008年秋季 第5章 嵌入式系统开发过程及软件设计
第5章 嵌入式系统开发过程及软件设计 • 本章主要介绍以下内容: • 嵌入式软件开发特点 • 嵌入式软件开发流程 • 常用的调试方法 • 操作系统和开发工具 • 板级支持包 • BootLoader介绍 • 嵌入式软件开发过程
5.1 嵌入式软件开发的特点 • 需要交叉开发环境。交叉开发环境是指实现编译、链接和调试应用程序代码的环境。与运行应用程序的环境不同,它分散在有通信连接的宿主机与目标机环境之中。 • 宿主机(Host):是一台通用计算机,一般是PC机。它通过串口与目标机通信。宿主机的软硬件资源比较丰富,包括功能强大的操作系统及相应的集成开发工具。 • 目标机(Target):在嵌入式软件开发期间使用,目标机可以是嵌入式应用软件的实际运行环境,也可以是能替代实际环境的仿真系统。目标机体积小,集成度高。目标机硬件资源有限,软件可以裁减,也可以配置。
嵌入式软件开发的特点 • 引入任务设计方法。嵌入式应用系统以任务为基本的执行单元。嵌入式系统的设计通常采用DARTS(Design and Analysis of Real-Time Systems)设计方法进行任务的设计。DARTS给出了任务划分的方法和定义任务间接口的机制。 • 需要固化程序。通用软件的开发在测试完成以后就可以直接投入运行。其目标环境一般是PC机,在总体结构上与开发环境差别不大。而嵌入式应用程序开发环境是PC机,但运行的目标环境却千差万别,可以是PDA,也可以是仪器设备。而且应用程序在目标环境下必需存储在非易失性存储器中,保证在关机后下次的使用。
嵌入式软件开发的特点 • 软件开发难度大。嵌入式应用软件对稳定性、可靠性、抗干扰、实时性等性能要求比通用软件的要求更为严格。
5.2 嵌入式软件的开发流程 1.需求分析阶段 对问题的识别和分析:功能需求、性能需求、环境需求、可靠性需求、安全需求、用户界面需求、资源需求、软件成本、开发进度。 制定规格说明文档:规格说明书、初级用户手册。 需求评审:正确性、无歧义性、安全性、一致性、可修改性、可验证性等。
5.2 嵌入式软件的开发流程 2.设计阶段 包括:系统设计、任务设计和任务的详细设计。 3.生成代码阶段 包括:代码编程、交叉编译和链接、交叉调试和测试等。 注:嵌入式集成开发环境都支持交叉编译、链接,如WindRiver公司的Tornado及GNU套件,微软公司的EVC++嵌入式开发环境,RAM公司提供的ADS、SDT等。
嵌入式软件的开发流程 4.固化阶段 嵌入式应用软件调试完成以后,编译器要对源代码重新编译一次,以产生固化到目标环境的可执行代码,再烧写到目标环境的Flash中。可执行代码烧写到目标环境以后,还要进行运行测试,以保证程序正确无误。固化测试完成后,整个嵌入式应用软件的开发就基本完成了。
宿主机 目标机 ARM硬件平台 嵌入式软件的开发流程
5.3常用调试方法 • 软件仿真(源程序模拟器方式) 在PC机上,通过软件手段模拟执行为某种嵌入式处理器编写的源程序。 • 驻留监控程序(监控器方式) 监控程序是一段运行于目标机上的可执行程序,主要负责监控目标机上被调试程序的运行情况。它与宿主机端的调试器一起完成对应用程序的调试。被调试程序下载到目标机,就可以进行调试。监控程序一般可完成设置断点、单步执行、查看寄存器或内存空间的值等各项功能。 • 不需要专门的调试硬件 • 需要占用目标板上的一部分资源 • 不能对程序进行完全仿真,主要用于调试在目标机操作系统上运行的应用程序,不适于调试目标操作系统。
常用调试方法 • JTAG仿真器(ICD,In-Circuit Debugger,在线调试器) 通过JTAG口与 目标机的CPU进行通信。 • 完全非插入式调试,不使用片上资源,无需目标存储器,不占用目标系统的任何端口 • 仿真效果更加接近于目标硬件 • 在线仿真器(ICE,In-Circuit Emulator) ICE是一种完全仿造调试目标CPU设计的仪器。该仿真器可以真正运行所有的CPU动作。使用ICE同使用一般的目标硬件一样,只是在ICE上完成调试之后,需要把调试好的程序重新下载到目标系统上而已。
处理器的选择 • 处理性能 • 技术指标 • 功耗 • 操作系统和软件支持工具的选择 • 是否内置调试工具
5.4 操作系统和软件支持工具的选择 • 如果用户希望使用Windows CE、Linux等操作系统,就需要选择ARM720T以上带有MMU(Memory Management Unit)功能的ARM芯片。 • ARM720T、ARM920T、ARM922T、ARM946T、Strong-ARM都带有MMU功能。而ARM7TDMI则没有MMU,不支持Windows CE和Linux,但目前有uCLinux以及uC/OS-II等不需要MMU支持的操作系统可运行于ARM7TDMI硬件平台之上。
操作系统和软件支持工具的选择 • 如果决定采用Linux、Windows CE、vxWorks等操作系统时,在选择处理器时应该尽量选择该操作系统已经支持的处理器,这样可以大大加快开发进度,降低难度。 • 选择不同的操作系统,其软件开发过程和调试手段各不相同,选择方案是否能够提供各个开发阶段(包括bootloader开发、操作系统移植、驱动开发和应用开发)所需的软件支持工具也是一个必须考虑的因素。
硬件驱动程序的调试 • 如果硬件平台是自行设计的,必须首先对硬件进行调试,硬件调试成功是进行操作系统移植和应用程序开发的一个基本前提。 • 这个过程通常是通过编写一些简单的测试程序直接驱动硬件以验证硬件是否正确,这些程序可以基于操作系统进行编程,也可以不使用操作系统,而且后一种方法来得更加简单,调试也更方便和快捷。
操作系统的选择和移植 • μC/OS-II • Linux/uClinux • Windows CE • vxWorks
μC/OS-II • 免费公开源代码、结构小巧、具有可剥夺实时内核的实时操作系统。 • 其内核提供任务调度与管理、时间管理、任务间同步与通信、内存管理和中断服务等功能。它可以基于ROM运行(ROMable)、可裁减,具有高度移植性。 • μC/OS-II实时嵌入式内核在工业控制、数据采集等领域应用广泛。但μC/OS-II内核不支持文件系统、网络协议等功能,而且没有提供统一的硬件驱动程序接口和开发工具链,在复杂应用中需要考虑内核以外功能的实现难易程度。
μC/OS-II • 在μC/OS-II开发中,内核、驱动程序和应用程序都是集中编译,μC/OS-II编译以后的二进制代码中既包含内核代码,也包含驱动程序和应用程序的代码。 • μC/OS-II没有提供统一的开发工具链,μC/OS-II程序的编译应该采用支持所选处理器的编译器。对于ARM处理器,可以在Windows环境中使用ADS 1.2、ADT IDE中编译μC/OS-II,也可以在Linux环境中使用GNU GCC编译μC/OS-II。
Linux/uClinux • Linux/uClinux是对于有MMU和没有MMU的处理器的Linux解决方案。 • Linux/uClinux提供强大的文件系统、网络功能、GUI等软件模组支持,而且这些功能都是可以裁减的,同时它还提供了标准的驱动程序接口和软件开发接口,便于用户编程和程序维护。 • Linux/uClinux自身具备一整套工具链(GNU GCC),包括编译和调试工具,用户可以自行建立嵌入式系统的开发环境和交叉运行环境。
Linux/uClinux • 对于ARM处理器,Linux/uClinux内核、驱动程序以及应用程序的编译都在Linux环境中使用GNU GCC完成。对于内核和驱动程序的调试通常借助于运行于Linux/uClinux之前的bootloader来完成,只有在很少的情况下需要借助在线仿真器完成。对于应用程序的调试则可以完全抛弃在线仿真器,使用GDB完成。
Windows CE • Windows CE是Windows界面在嵌入式处理器中的实现,它提供了友好的人机交互界面和强大的二次开发功能。Windows CE包括四大基本模块,它们提供了操作系统的关键特性,分别是:内核(Kernel)模块、对象存储(Object Store)模块、GWES(用户、应用程序和操作系统之间的图形用户界面)模块和通信(Communication)模块。
Windows CE • Windows CE拥有完善的软件支持开发工具,Windows CE的核心移植和驱动开发使用专门的操作系统定制工具:Windows CE Platform Builder(简称PB)。而应用程序的开发则有嵌入式开发工具包Embedded Visual Tools,包括Embedded Visual C++(简称EVC)和Embedded Visual Basic(简称EVB)等。同时Embedded Visual Tools下还可以进行部分驱动程序的开发。同时在Windows CE中还提供了用于Windows CE开发的bootloader:EBOOT。
vxWorks • VxWorks是专门为实时嵌入式系统设计开发的操作系统内核,为程序员提供了高效的实时多任务调度、中断管理,实时的系统资源以及实时的任务间通信。 • 在各种CPU平台上提供了统一的编程接口和一致的运行特性,尽可能的屏蔽了不同CPU之间的底层差异。应用程序员可以将尽可能多的精力放在应用程序本身,而不必再去关心系统资源的管理。基于VxWorks操作系统的应用程序可以在不同CPU平台上轻松移植。
vxWorks • VxWorks包括了进程管理、存储管理、设备管理、文件系统管理、网络协议及系统应用等几个部分。VxWorks只占用了很小的存储空间,并可高度裁减,保证了系统能以较高的效率运行。 • TornadoII是为开发VxWorks应用系统提供的集成开发环境,TornadoII中包含的工程管理软件,可以将用户自己的代码与VxWorks的核心有效的组合起来,可以按用户的需要裁剪配置VxWorks内核。
ARM主流开发工具 • Windows操作系统 • ARM ADS/SDT + 调试器 • GNU + Cygwin + 调试器 • ARM SDT + 简易电缆 • Linux操作系统 • GNU + GDB
5.5 板级支持包 • BSP(Board Support Package 板级支持包)是介于底层硬件和操作系统之间的软件层次,它完成系统上电后最初的硬件和软件初始化,并对底层硬件进行封装,使得操作系统不再面对具体的操作。
板级支持包的特点 • 硬件相关性:因为嵌入式实时系统的硬件环境具有应用相关性,所以,作为高层软件与硬件之间的接口,BSP必须为操作系统提供操作和控制具体硬件的方法。 • 操作系统相关性:不同的操作系统具有各自的软件层次结构,因此,不同的操作系统具有特定的硬件接口形式。
BSP板级支持包 • 功能 • 为应用程序提供统一的硬件操作接口 • 特征 • 高度硬件相关 • 高度依赖于具体硬件平台 • 各种操作系统各异
和BootLoader存在一定的重叠 板级支持包的功能 • 嵌入式系统初始化 • 片级初始化 • 板级初始化 • 系统级初始化 • 硬件相关的设备驱动程序
系统级初始化 • 这是一个以软件初始化为主的过程,主要进行操作系统初始化。BSP将控制转交给操作系统,由操作系统进行余下的初始化操作。包括加载和初始化与硬件无关的设备驱动程序,建立系统内存区,加载并初始化其他系统软件模块,比如网络系统、文件系统等;最后,操作系统创建应用程序环境并将控制转交给应用程序的入口。
硬件相关的驱动程序 • 与初始化过程相反,硬件相关的设备驱动程序的初始化和使用通常是一个从高层到底层的过程。 • 尽管BSP中包含硬件相关的设备驱动程序,但是这些设备驱动程序通常不直接由BSP使用,而是在系统初始化过程中由BSP把它们与操作系统中通用的设备驱动程序关联起来,并在随后的应用中由通用的设备驱动程序调用,实现对硬件设备的操作。
BootLoader的基本概念 • BootLoader是系统加电后运行的第一段软件代码。 • 嵌入式系统中,整个系统的加载启动任务完全由 BootLoader来完成。比如在一个基于ARM920T core的嵌入式系统中,系统在上电或复位时都从地址0x00000000开始执行,而在这个地址处安排的通常就是系统的BootLoader程序。
BootLoader的基本概念 • 简单地说,BootLoader就是在操作系统内核或用户应用程序运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核或用户应用程序准备好正确的环境。 • 通常,BootLoader 是依赖于硬件而实现的,特别是在嵌入式领域,为嵌入式系统建立一个通用的 BootLoader 是很困难的。
BootLoader的主要任务与典型结构框架 • 从操作系统的角度看,BootLoader的总目标就是正确地调用内核来执行。 • 大多数BootLoader都分为stage1和stage2两大部分。 • 依赖于CPU体系结构的代码,比如设备初始化代码等,通常都放在stage1中,而且通常都用汇编语言来实现,以达到短小精悍的目的,也就是前面说的启动代码。 • 而stage2 则通常用C语言来实现,这样可以实现复杂的功能,而且代码会具有更好的可读性和可移植性。
BootLoader的主要任务与典型结构框架 • BootLoader的stage1通常包括以下步骤 • 为加载 BootLoader 的 stage2 准备 RAM 空间 • 拷贝 BootLoader 的 stage2 到 RAM 空间中 • 设置好堆栈 • 跳转到 stage2 的 C 入口点 • BootLoader的stage2通常包括以下步骤 • 初始化本阶段要使用到的硬件设备 • 调用应用程序或启动内核
Stage 1初始化流程图 • stage 1的功能: RAM初始化,设置各个部件的时钟和片选,将BootLoader拷贝到RAM中,设置堆栈,调用Stage 2。 • 注意:在本阶段,特别是在堆栈设置之前,进行函数调用(也有些汇编子程序不需要使用堆栈)或者使用堆栈保存数据将产生不可预知的结果;
Stage 2流程图 • stage 2的功能: 初始化串口,显示菜单,通过控制台获取用户输入,并执行相应的命令操作。
Bootloader 启动过程 开 始 初始化与中断有关的寄存器 建立异常向量表 初始化串口 初始化时钟 初始化协处理器 建立堆栈 引导操作系统 初始化flash ROM, SDRAM 结 束 执行重映射,建立新的异常向量表
BootLoder作用 • Bootloader的作用: • 嵌入式系统的资源有限,应用程序通常都是固化在ROM中运行。ROM中的程序执行前,需要对系统硬件和软件运行环境进行初始化。这些工作是用汇编语言和C语言编写的Bootloader代码完成的。在ARM处理器的嵌入式系统中,Bootloader代码的作用主要有以下几点: • 建立中断向量表 • 初始化CPU各种模式的堆栈和寄存器 • 初始化flash ROM,SDRAM等各种片内外设 • 实现地址重映射 • 初始化目标板; • 引导操作系统
建立中断向量表 建立中断向量表: LDR PC,ResetAddr //reset LDR PC,UndefinedAddr //undefined LDR PC,SWI_Addr //software interrupt LDR PC,PrefetchAddr //prefetch LDR PC,DataAbortAddr //data abort LDR PC,[PC,#-0xff0] //irq LDR PC,FIQ_Addr //fiq
初始化堆栈 初始化堆栈: MOV R0,LR 因芯片模式切换,故将程序返回地址保存至R0,同时在初始化堆栈完成后使用R0返回. MSR CPSR_c,#0xd3 ;设置管理模式堆栈 LDR SP,StackSvc MSR CPSR_c,#0xd2 ;设置中断模式堆栈 LDR SP,StackIrq MSR CPSR_c,#0xd1 ;设置快速中断模式堆栈 LDR SP,StackFiq
初始化堆栈 初始化堆栈:初始化堆栈 MSR PSR_c,#0xd7 ;设置中止模式堆栈 LDR SP,StackAbt MSR CPSR_c,#0xdb ;设置未定义模式堆栈 LDR SP,StackUnd MSR CPSR_c,#0xdf ;设置系统模式堆栈 LDR SP,StackUsr MOV PC,R0
初始化外设: 初始化外设主要是指初始化cpu内部的控制寄存器,比如:lcd 控制器,网络控制器等等,主要是靠汇编语言来完成 实例代码: LDR R1,=0x3ff5000 ;外设寄存器1地址 LDR R0,=0x0 STR R0,[R1] ;赋初值 LDR R0,=0x3ff5008 ;外设寄存器2地址 LDR R1,[R0] ;取出寄存器的值 AND R1,R1,#0x08 CMP R1,#0x08 ;测试bit3
地址重映射 地址重映射: 地址重映射是实现RAM和ROM的物理地址对调,在嵌入式系统里面: 0x0地址ROM的开始地址,RAM开始地址是非0x0的地址,在bootloader汇编代码中需要将RAM的地址和ROM的地址对调,这样一个过程,我们叫做地址重映射 地址重映射的代码举列: LDR r0, =0x3FF0000 + 0x3010 LDR r1, =0x00003002 LDR r2, =0x12040060 LDR r3, =rROMCON1 LDR r4, =rROMCON2 LDR r5, =rROMCON3 LDR r6, =rROMCON4 LDR r7, =rROMCON5
地址重映射的代码举列: LDR r8, =0x10000380 LDR r9, =rSDRAMCON1 LDR r10,=rSDRAMCON2 LDR r11,=rSDRAMCON3 LDR r12,=rSREFEXTCON STMIA r0, {r1-r12} 问题:地址重映射的作用是什么? 地址重映射
初始化目标板 初始化目标板: 初始化目标板主要是指初始化cpu的时钟,设置存储器加速,打开中断和目标板特性相关初始化配置 注意: 每个目标板的硬件配置都不完全样,初始化目标板程序都不会完全一样.
引导操作系统: 引导操作系统是一个很复杂的过程,我们在这里讲的是在如何在bootloader里面将linux kernel加载到RAM中并且跳转到RAM中开始启动Linux,以下是导操作代码举列: //将ROM中的linux kernel搬移到RAM中 om2ram_copy_loop ldr r3, [r0], #4 str r3, [r2], #4 subs r1, r1, #4 bne rom2ram_copy_loop //跳转到RAM中的Linux开始地址 LDR R0,=kernel address MOV PC,R0
AT91RM9200 Bootloader开发实例 ; bootload.s INCLUDE AT91RM9200.inc ;------------------------------------------------------------------------------ ;定义AREA ;------------------------------------------------------------------------------ AREA reset, CODE, READONLY ;------------------------------------------------------------------------------ ;定义程序开始点 ;------------------------------------------------------------------------------ EXPORT __ENTRY __ENTRY