嵌入式系统软件设计.ppt_第1页
嵌入式系统软件设计.ppt_第2页
嵌入式系统软件设计.ppt_第3页
嵌入式系统软件设计.ppt_第4页
嵌入式系统软件设计.ppt_第5页
已阅读5页,还剩36页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

2019/5/17,1,第五章 嵌入式系统软件设计,嵌入式系统作为一个完整的、独立的、能够单独运行的系统。与传统的通用计算机系统相比,它有许多独有的特点。这些特点也产生了它与通用计算机系统的区别。这些区别不仅表现在整个系统软件的结构上,也体现在软件的开发方法上。,2019/5/17,2,5.1嵌入式软件结构及组成,用户应用软件高层,用户应用软件底层,GUI 协议 设备驱动 文件系统,操作系统层,板级支持包,初始化引导代码,2019/5/17,3,5.2初始化引导代码实例,初始化引导代码也称为引导加载程序,即BootLoader。它是系统上电后运行的第一段程序代码。通过这段代码,可以初始化存储器空间的映射,从而将系统的软硬件环境设置到一个合适的状态,以便为最终调用操作系统内核准备好环境。,2019/5/17,4,PC的启动过程:在系统上电后由BIOS(一段固件程序)进行POST(上电自检),在分配资源过后,将硬盘MBR(主引导记录)中的OS Boot Loader如LILO,或者GRUB)载入内存,然后将控制权交给OS Boot Loader,将操作系统内核映象加载到内存中,接着就跳转到内核的入口处去执行,即启动操作系统。,2019/5/17,5,而在嵌入式系统中,通常并没有像BIOS 那样的固件程序(注,有的嵌入式 CPU 也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由 Boot Loader 来完成。一般在上电或者复位后,嵌入式系统都会从一个固定的地址处开始执行。这个固定地址一般由CPU生产厂商决定 (通常为0x0000_0000),在这个地址处安排的通常就是系统的Boot -Loader程序。,2019/5/17,6,与普通PC的启动相比较,在嵌入式系统中所说的BootLoader的功能与普通PC中的BIOS以及OS BootLoader类似。与Bootloader不同的是BIOS在装载OS系统的同时,还传递一些参数设置(中断端口定义、显存大小等),而Bootloader一般只简单地装载系统。,2019/5/17,7,BootLoader的启动一般分为两个阶段。阶段一主要完成的是与CPU体系结构有关的初始化,如设备的初始化。它一般用汇编语言来实现。阶段二主要完成的是一些常规的初始化,通常用C语言实现。,2019/5/17,8,我们按照U-Boot的启动流程介绍了各个阶段主要完成的工作以及相应的一些示意代码和程序框架。 对ARM9核处理器,U-boot启动流程主要体现在三个文件上,即 cpu/*/start.s lib_arm/board.c common/main.c。,2019/5/17,9,start.s文件,在start.s文件中通过如下语句来指定这个入口: .globl _start _start: 因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本文件u-boot.lds 来完成。u-boot.lds文件用来设置U-boot中各个目标文件的连接地址。 注:链接脚本文件的功能是将输入文件的各节映射到输出文件中;换句话说,它将所有输入对象文件都链接到单一的可执行文件中,将该可执行文件的各节装入到指定地址处。,2019/5/17,10,设置异常向量,异常中断向量表是u-boot与操作系统内核发生联系的关键地方之一。即使操作系统内核已经得到处理器的运行控制权,一旦发生中断,处理器还是会自动跳转到从0x0地址开始的异常中断向量表中的某个位置(依据中断类型)处读取指令运行。 ARM9要求异常中断向量表必须设置在从0地址开始,连续84字节的空间,分别是复位、未定义指令错误、软件中断、预取指令错误、数据存取错误、一个保留的中断向量以及IRQ和FIQ。,2019/5/17,11,b reset ldr pc,_undefined_instruction;将标号_undefined_instruction的地址加载到pc中。在该例中,_undefined_instruction处又放的是 ;undefined_instruction的地址,这样经过一次中间转换, ;当未定义指令错误到来时,实际上是将 ;undefined_instruction处的地址加载到pc中,即运行的是 ;undefined_instruction处的指令。 ldr pc,_software_interrupt ldr pc,_prefetch_abort ldr pc,_data_abort ldr pc,_not_used ldr pc,_irq ldr pc,_fiq,2019/5/17,12,_undefined_instruction:.word undefined_instruction;在存储器中预留一个字的空间大小,并将标号undefined_instruction放到该空间中,并用标号undefined_instruction表示这个预留的空间 _software_interrupt: .word software_interrupt _prefetch_abort: .word prefetch_abort _data_abort: .word data_abort _not_used: .word not_used _irq: .word irq _fiq: .word fiq .align 5;为了指令对齐 undefined_instruction: bl do_undefined_instruction,2019/5/17,13,设置CPU模式,;设置CPU模式为SVC32模式,禁止IRQ和FIQ中断 ,参考3.4.2节 ;CPSR位 31 30 29 28 7 6 5 4 3 2 1 0 ; 1 1 0 1 0 0 1 1 mrs r0,cpsr ;将cpsr加载到r0中 bic r0,r0,#0x1f ;将cpsr的低5位清0 orr r0,r0,#0xd3 ;将cpsr的低8位设置为11010011 msr cpsr,r0 ;将r0加载到cpsr中,2019/5/17,14,设置若干寄存器,设置看门狗计时器(关闭),设置中断屏蔽寄存器(屏蔽所有中断,因为为中断提供服务通常是操作系统设备驱动程序的责任,在BootLoader执行过程中可以不必响应任何中断,更重要的是此时系统还没有为中断执行准备必要的堆栈等条件),设置时钟除法控制寄存器(设置FCLK:HCLK:PCLK)。,2019/5/17,15,# define pWTCON 0x53000000 # define INTMSK 0x4A000008 /* 中断控制基址寄存器*/ # define INTSUBMSK 0x4A00001C # define CLKDIVN 0x4C000014 /* 时钟除法寄存器 */ /*关闭看门狗计时器*/ ldr r0,=pWTCON /*参考3.4.4节ldr伪指令介绍*/ /*该指令将pWTCON的值加载到r0中,这里编译器会把该条指令编 /*译为两条指令,但对于程序员而言,这是透明的,即在程序员看来, /*r0中保存的是pWTCON的值*/ mov r1,#0x0 /*将r0赋值为0*/ str r1,r0 /*将r1的值0保存到r0所表示的存储器单元,即0x53000000处*/,2019/5/17,16,/* 在默认情况下,通过设置INTMSK来屏蔽所有的IRQ中断 */ mov r1,#0xffffffff ldr r0,=INTMSK str r1,r0 ldr r1,=0x3ff ldr r0,=INTSUBMSK str r1,r0 /* 默认情况下,FCLK为120MHz,这里设置FCLK:HCLK:PCLK = 1:2:4 */ ldr r0,=CLKDIVN mov r1,#3 str r1,r0,2019/5/17,17,CPU、协处理器和RAM初始化,CPU、协处理器和RAM初始化,2019/5/17,18,程序复制以及栈的初始化,U-Boot代码等0x00FF FFFF0x00FE 0000 堆(malloc调用)0x00FC 00000x00FB FFAC Board信息栈(向下增长)0x00FB FF20 应用程序空间0x0000 00000x0000 2000 异常向量 将ROM中的程序复制到RAM中,进行栈的初始化,为第二阶段准备RAM空间。注意U-Boot没有用MMU单元,而是使用实地址。 U-Boot被初始安装在第一个Bank的前128K的地址空间。在经过引导,DRAM初始化后,代码将它自己搬移到DRAM的高地址空间。在U-Boot代码后,将保留大小为CFG_MALLOC_LEN的空间用于被malloc()调用。之后,初始化堆栈(向下增长),然后是一个包含Board信息的结构。最后,异常向量被放到DRAM的低8K空间。典型的有16M空间的配置如图5-2。,2019/5/17,19,16M空间的典型配置,2019/5/17,20,具体程序参见p158,2019/5/17,21,跳转到RAM中运行,具体代码如下: ldr pc,_start_armboot _start_armboot: .word start_armboot /*标号_start_armboot 表示一个字大小的空间,而在该空*/ /*间中存放的正是start_armboot的地址*/ 其中的start_armboot在下面即将介绍的board.c中定义。,2019/5/17,22,1.定义的数据结构,该文件主要定义了下面的数据结构. typedef int (init_fnc_t) (void); init_fnc_t *init_sequence = cpu_init, /* basic cpu dependent setup */ board_init, /* basic board dependent setup */ interrupt_init, /* set up exceptions */ env_init, /* initialize environment */ init_baudrate, /* initialze baudrate settings */ serial_init, /* serial communications setup */ console_init_f, /* stage 1 init of console */ display_banner, /* say that we are here */ #ifdefined(CONFIG_DISPLAY_CPUINFO) print_cpuinfo, /* display cpu info (and speed) */ #endif #ifdefined(CONFIG_DISPLAY_BOARDINFO) checkboard, /* display board info */ #endif dram_init, /* configure available RAM banks */ display_dram_config, NULL, ;,2019/5/17,23,函数start_armboot (void)中,通过循环来实现对各个部件的初始化。包括cpu_init(CPU相关的设置),board_init(板子相关的设置),interrupt_init(中断设置),env_init(环境变量设置),init_baudrate(串口的波特率设置) ,serial_init(串口初始化),console_init_f (控制台设置),display_banner(显示标题),dram_init(可用内存配置)。,2019/5/17,24,void start_armboot (void) init_fnc_t *init_fnc_ptr; for (init_fnc_ptr = init_sequence; *init_fnc_ptr; +init_fnc_ptr) if (*init_fnc_ptr)() != 0) hang (); ,2019/5/17,25,2.初始化Flash设备,#ifndef CFG_NO_FLASH size = flash_init (); /* 配置可用的FLASH Banks */ display_flash_config (size); #endif /* CFG_NO_FLASH */,2019/5/17,26,3.初始化系统内存分配函数 mem_malloc_init (_armboot_start - CFG_MALLOC_LEN); 4.初始化NAND设备 #if (CONFIG_COMMANDS /* 在帧缓冲被设置后,必须对显示设备进行初始化 */ #endif /* CONFIG_VFD */,2019/5/17,27,7.进入死循环main_loop() 该函数的具体实现在main.c中。之所以要用死循环,是因为当main_loop返回时,不论是正常还是非正常的情况,能够重新进入函数执行。而不会出现main_loop退出后系统不工作的情况。 for ( ; ; ) /* 当任何情况出现时,能够重新进入main_loop() */ main_loop (); ,2019/5/17,28,main.c文件,该文件位于U-boot/common/main.c,在启动过程会出现“Hit any key to stop autoboot”提示,若回车则进入命令提示状态,否则U-boot便会从某个位置(由bootcmd参数设置)启动预装的操作系统内核。,2019/5/17,29,5.3 嵌入式系统软件构件技术,基于构件的开发(Component-Based Development,简称CBD)是一种软件开发新模式,它是在一定构件模型的支持下,复用构件库中的一个或多个软件构件,通过组合手段高效率、高质量地构造应用软件系统的过程。由于以分布式对象为基础的构件实现技术日趋成熟,CBD已经成为现今软件复用实践的研究热点,被认为是最具潜力的软件工程发展方向之一。在嵌入式系统中,对于各个功能部件的复用也越来越被受到重视。,2019/5/17,30,1.构件 因为不同的需求以及不同的关注点,构件并没有统一的定义、例如,Szyperski97在Component Software-Beyond OO Programming中提到“软件构件是一个仅带特定契约接口和显式语境依赖的结构单元”。一般可以认为“构件是一个系统中实际存在的可更换部分,它实现特定的功能,符合一套接口标准并实现一组接口。构件代表系统中的一部分物理实体,包括软件代码(源代码、二进制代码或可执行代码)或其等价物(如脚本或命令文件)。”,2019/5/17,31,5.4 LCD显示构件,2019/5/17,32,LCD的显示要求设计专门的驱动电路与显示控制电路。驱动电路包括提供LCD的驱动电源,液晶分子的偏置电压,以及LCD的驱动逻辑。显示控制电路可由专门的硬件电路组成,也可以采用集成电路模块,还可以使用处理器外围LCD控制模块 . 在图中,嵌入式处理器往往只是一个核,如ARM9DTMI;LCD控制器则多是ARM的合作伙伴在以ARM核为基础生产芯片时所增加的外围部分,如S3C2410X的LCD控制器。其中的LCD驱动器,则是由许多其它公司生产的,专门用于LCD的驱动逻辑,如LCD显示驱动器SD0432。,2019/5/17,33,接口函数,为了便于描述,在此小节中,首先定义若干接口函数。针对具体某一款的LCD显示器的实现将在下一节中进行具体阐述。 正如大家所知,目前的LCD产品可支持黑白、灰度以及彩色3种显示模式。当定义接口函数的时候,有两种方案:可以为每一种LCD定义接口函数,也可以定义一种通用的函数,用于3种LCD的显示。 第一种方案的优点是它具有很强的针对性,对于不同的LCD使用不同的LCD组件代码。但它的缺点也是非常明显的,那就是移植性很差。一种LCD的组件代码要移植到另一种LCD上时,需要改动大量的程序代码。 第二种方案与第一种方案完全相反,它的优点就是移植性好。因为它对外提供的接口都是相同的,只是它封装了内部不同的函数实现。正如鱼与熊掌不可兼得,因为它失去了对某一LCD的针对性,所以在实现某些功能时会显得不足 .,2019/5/17,34,1.LCD初始化 使用之前任何设备都要初始化。LCD的初始化工作主要完成对LCD驱动器的初始化,如初始化S3C2410X的LCD控制器。在具体编程实现中,实际上就是设置控制器的相关寄存器。 函数原型:void lcd_init(v

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论