BOOTLOADER程序设计.ppt_第1页
BOOTLOADER程序设计.ppt_第2页
BOOTLOADER程序设计.ppt_第3页
BOOTLOADER程序设计.ppt_第4页
BOOTLOADER程序设计.ppt_第5页
已阅读5页,还剩41页未读 继续免费阅读

下载本文档

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

文档简介

bootloader程序设计,本章主要讲解bootloader(启动代码)的运行机制,代码功能与实现方法。通过本章的学习可以进一步理解arm微处理器的启动方式,对于后续学习嵌入式操作系统有很大的帮助。,内容提要,1 为什么要写启动代码 2 两种启动方式以及其中的区别 3 启动代码的功能与实现 4 启动代码编写,1.为什么要编写启动代码,启动代码是系统上电或复位以后运行的第一段代码,他的作用是在用户程序运行之前对系统硬件及软件环境进行必要的初始化并在最后使程序跳到用户程序. 在此之前系统的所有硬件都是不好用的,初始化代码直接对arm处理器内核及硬件控制器进行编程,所执行的操作与具体的目标系统紧密相关。,2.两种启动方式以及其中的区别,根据代码存放位置,以及地址启动位置的区别,arm支持两种方式的启动: nor flash和 nand flash,表1 两种flash对比表,2.1 nor flash启动代码运行方式,从nor flash启动时,与ngcs0相连的nor flash就被映射到了ngcs0片选的空间,其地址被映射为0x00000000; 因为nor flash支持系统运行,所以不必考虑程序的搬移,只需保证系统上电后或者复位时代码从0开始即可。,2.2 nand flash启动代码运行方式,从nand flash启动时,芯片内部自带一块容量为4k的bootsram会被映射到ngcs0片选的空间,起始地址被映射为0x00000000,因此,编写的启动代码要保证在0开始的地址处。 系统上电后,bootsram没有任何代码,arm芯片通过硬件机制将nand flash前4k的内容拷贝到其中,然后在bootsram中运行这4k的代码(0地址处),此种情况下要保证启动代码放在nand flash的0地址处,启动代码要小于4k(只要ram初始化,搬移程序小于4k即可)。,所有程序编译链接后代码量小于4k时,程序不用考虑从nand flash搬移到sdram的问题,因为所有程序在启动时已全部在bootsram中,运行即可。 所有程序编译链接后代码量大于4k时,启动代码不只要有初始化内容,还要有一段搬移代码,将全部程序从nand flash搬移到sdram,也就是系统启动时需要两次搬运,第一次将前4k搬移到bootsram,第二次将所有代码搬移到sdram中,其中第一次无需人工干预,硬件机制自动实现,第二次需要程序员编写代码实现。,3.启动代码的功能与实现,启动代码的主要功能 1.建立异常向量表 2.初始化系统堆栈 3.初始化硬件 4.应用程序执行环境初始化 5.跳转至主函数,3.1 异常向量表的建立,异常向量表位于启动代码的起始部分,是用户程序与启动代码之间以及启动代码的各个部分之间联系的纽带。 它由一个个跳转函数组成,当系统发生异常时,arm处理器会通过硬件机制强行将pc指针指向异常向量表中对应的异常跳转函数存储地址,之后跳到相应的异常中断服务程序中执行。,中断向量表的程序通常如下表示: area init ,code, readonly entry b resethandler /复位异常 b undefhandler /未定义异常 b swihandler /软中断异常 b preaborthandler / 取指终止异常 b dataaborthandler /数据中止异常 b /保留 b irqhandler / 中断异常 b fiqhandler / 快速中断异常 其中关键字entry是指定编译器保留这段代码,链接的时候要确保这段代码被链接在整个程序的入口地址,当arm启动时,pc指针会自动寻找该关键字从该关键字处执行。,3.1.1正常上电或者复位的运行,arm要求异常向量表必须存储在0地址,当开发板上电或者复位时,pc会指向0地指出,进而跳到复位异常处理函数resethandler,这个函数负责完成系统的初始化,即初始化堆栈、初始化硬件、初始化应用程序执行环境、跳至主函数。,3.1.2未定义异常处理函数,当arm处理器不认识当前指令时,就会将该指令发送至协处理器,如果协处理器也不认识就会产生未定义异常。 未定义异常后,cpu会将函数的返回地址及此时的cpsr保存到未定义异常专用的r14和spsr中,然后在修改cpsr使系统进入未定义异常模式运行,pc被强制指向0x00000004,然后程序就跳至未定义异常的处理函数,上述过程由硬件实现不需人工干预。,3.1.3 软中断异常处理函数,软件中断异常是由用户定义的中断指令,用于用户模式下的程序调用特权模式下的操作指令,例如修改cpsr值,从而进入其他特权模式等。 处理器相应swi异常的流程: 1.保存cpsr,r14 2.修改cpsr进入管理模式,进制irq中断 3.强制pc转向0x00000008,并跳入软中断异常处理函数。,swi中断举例,3.1.4取指终止异常处理函数,当处理器预取的指令地址不存在或者地址不允许当前指令访问,产生该异常。 处理的方式 1. 异常地址之前的指令正常执行,到该指令发生异常。 2. 处理返回地址(pc-4)以及保存cpsr 3.切换模式到取指异常模式 4.强制pc转向0x0000000c,并跳入处理函数 通常只要不涉及mmu,一般处理函数为死循环。,3.1.5数据中止异常处理函数,产生条件:数据访问指令的目标地址不存在或者该地址不允许此指令访问。 处理方式同取指终止异常,3.1.6 irq中断异常处理函数,arm内核为了处理外部设备向cpu发出的服务请求,尤其是一些紧急事件而特别作出的设计,来中断时进中断处理中断函数,结束后返回继续执行主程序。 条件:外部中断请求引脚拉低,irq中断使能(i位清零) 处理方式 1. 保存cpsr和返回地址到专用的r14以及spsr 2.修改cpsr禁止新的irq产生,切换模式到irq模式 3.强制pc转向0x00000018,并跳入处理函数,注意事项: 编写irq中断处理程序是,要注意中断的重入性,即在有些irq中断处理函数中,允许新的irq产生,但这种情况会刷新掉一些以前的寄存器值,例如lr,所以在允许新中断产生之前要把一些寄存器保护一下,避免产生混乱。,irq中断举例,例: 一个外部无重入中断irq_eint1 void _irq irqhandle(void) void (*p)(void); /定义一个函数指针 int irq_no; /中断号 uint32 intpnd; /中断挂起号 intpnd=rintpnd;/从中断挂起寄存器读取中断号 /将中断挂起号转换为中断号 for(irq_no=0;irq_no1; if(intpnd=0) break; ,/利用函数指针取得中断服务程序的地址 p=(void(*)(void)vicvectaddirq_no; p(); 在汇编语言中实现启动代码中,需要在一场向量表之前引入这个函数,所以要加入代码: import irqhandle _irq这个关键字可实现进入中断处理函数时一些关键寄存器的自动保护和处理完毕后的自动返回,具体请见汇编和c的混合调用,因此接下来就是要编写中断处理函数了。,void irq_eint0(void) /中断处理函数 void irq_eint1(void) /中断处理函数 编写完之后中断处理函数需要用两个语句来使其与irq异常处理函数建立联系 vicvectadd0=(unit32)irq_eint0 vicvectadd1=(unit32)irq_eint1 注意:arm有32个外部中断源,8-32占用一个irq源,因此要加语句进行判断,而且处理程序的最后要把中断标志位清除,以免系统不断的响应,3.1.7 fiq异常中断处理函数,系统对实时性比较敏感,如数据大页面的传输或通道处理时就需要非常短的中断响应时间,而fiq就是响应这种类型的中断。 硬件结构对fiq的支持 1.fiq具有8个专用寄存器,系统从其他模式切换到fiq模式不用寄存器进栈,节约了时间 3.fiq异常入口位于异常向量表最后。 处理方式 1. 保存cpsr和返回地址到专用的r14以及spsr 2.修改cpsr禁止新的irq、fiq产生,切换模式到fiq模式 3.强制pc转向0x0000001c,并跳入处理函数,fiq异常处理函数,handlerfiq stmfd sp!,r0-r3,lr /保存返回值 bl fiq_exception /fiq中断处理 ldmfd sp!,r0-r3,lr /寄存器出栈 subs pc,lr,#4 /返回 void fiq_exception (void) 代码 汇编语言实现的启动该代码需要在handlerfiq前引入这个函数 import fiq_exception,3.2 系统堆栈的初始化,系统堆栈的初始化主要是给处理器的各个模式分配堆栈空间。堆栈是为中断或程序跳转服务的,当发生中断或程序跳转的时候,需要将当前处理器的状态以及一些参数保留在堆栈中,当处理完了之后再将堆栈内的数据恢复,以保证原来程序的正确运行。,系统初始化的准备工作,/工作模式位的设定 usermode equ 0x10 /用户模式 fiqmode equ 0x11 /fiq模式 irqmode equ 0x12 /irq模式 svcmode equ 0x13 /管理模式 abortmode equ 0x17 /中止模式 undefmode equ 0x1b /未定义模式 modemask equ 0x1f /掩码 noint equ 0xc0 /禁止两种中断,;/系统堆栈空间设定 userstack equ (_stack_baseaddress-0x3800) ;/0x33ff4800 svcstack equ (_stack_baseaddress-0x2800) ;/0x33ff5800 undefstack equ (_stack_baseaddress-0x2400) ;/0x33ff5c00 abortstack equ (_stack_baseaddress-0x2000) ;/0x33ff6000 irqstack equ (_stack_baseaddress-0x1000) ;/0x33ff7000 fiqstack equ (_stack_baseaddress-0x0) ;/0x33ff8000 /根据_stack_baseaddress设置堆栈在内存中的存放位置,在此设定为0x33ff8000,各种堆栈分配的大小按照需要设置,同时要考虑到用到哪些中断。,堆栈初始化的顺序,堆栈初始化的顺序决定系统最后运行在哪种处理器模式,最后初始化哪种模式的堆栈,系统就运行在哪种模式。 一般系统最后要运行在特权模式,因为如果运行在用户模式无法操作cpsr,将对接下来的程序产生影响。最后初始化系统模式的堆栈。,注意: 启动代码中如果是通过bl指令跳转到堆栈初始化函数的话,需要注意一点:堆栈初始化后如果系统运行在非管理模式,则堆栈初始化函数最后不应该通过mov pc,lr返回。因为系统上电或复位后系统运行在管理模式,而各种特权处理器模式下都有自己对应的lr,上面的这条指令放入的是最后初始化的模式的lr,而不是管理模式的lr,所以无法实现正确返回,正确的方法是在刚进入堆栈初始化函数时将lr保存在一个通用寄存器,函数返回时将这个寄存器的值放入pc即可,如果最后初始化的是管理模式则可通过mov pc,lr返回。,3.3 初始化硬件,目的:初始化硬件的目的是为主程序的运行创造一个合适的硬件环境,这一部分是和具体的应用系统密切相关的。 初始化的内容: 1.关闭看门狗 2.屏蔽所有中断 3.初始化时钟和pll 4.初始化存储系统,3.3.1 关闭看门狗,看门狗是为了防止程序跑飞,但是系统上电或者复位以后,默认看门狗是打开的,这样如果不喂狗会给程序带来麻烦,造成复位的循环,因此在初始化程序中必须把它关掉。 代码 ldr r0,=wtcon ;/将看门狗控制寄存器最低位清零 ldr r1,=0x0 str r1,r0,3.3.2屏蔽中断,中断服务程序一般在用户程序中实现,启动代码中无需处理终端,另外为了避免在启动过程中触发中断,所以一般采用屏蔽中断方法避免麻烦的产生。 代码 ldr r0,=intmsk ;/屏蔽所有中断 ldr r1,=0xffffffff str r1,r0 ldr r0,=intsubmsk ;/屏蔽所有子中断 ldr r1,=0x7ff str r1,r0,3.3.3初始化pll和时钟,时钟是处理器运行的脉搏,在进入主函数之前应该对其进行设置。pll,锁相环,起作用是将外部晶振的输入频率倍频到一个较高的频率。 s3c2410有两个锁相环:mpll和upll。mpll用于cpu以及其他外设,通过mpll产生三个时钟频率:fclk、hclk、pclk。fclk就是时钟,hclk用于驱动ahb总线设备如(sdram),pclk用于驱动apb总线设备(如uart)。upll用于usb模块。,设置pll以及时钟的代码,;/设置pll重置延时,因为pll改变时,刚开始会给系统带来一段时间的不稳定,此时不使用pll作为fclk的输出而使用外部时钟,等locktime结束之后pll稳定了再使用。 ldr r0,=locktime ldr r1,=0xffffff str r1,r0 ;/设置mpll的输出频率,办法是通过设置 mpllcon,具体算法看芯片手册 ldr r0,=mpllcon ldr r1,=(m_mdiv12)+(m_pdiv4)+m_sdiv) ;/fin=12mhz,fout=50mhz str r1,r0,3.3.4 初始化存储系统,s3c2410的存储地址空间为0-0x3fffffff,共1g,这些地址空间被分为8个bank,每个bank有128m字节的存储空间。 8个bank的读写位宽可以通过编程来设定,具体要看挂载的存储器的类型,bank0可以配置为16位或者32位,其他bank可以配置为8、16、32位 前六个bank可以挂载rom、sram等类型存储设备,后两个可以挂载rom、sram、sdram等类型存储设备。 bank0-bank6起始地址固定,ban7的起始地址可以调整。,存储系统的初始化代码, 将存储器配置值得数据表的地址放入寄存器r0; 将总线数据宽度和等待控制寄存器的地址放入寄存器r1,因为寄存器的地址是在s3c2410的头文件中定义好的,不会改变,所以用ldr指令。 至给一些列的寄存器赋值,一共13个值。,3.3.5应用程序执行环境的初始化,文件类型的转化 源文件(.c或.s)经过arm编译器的编译生成elf(executable and linkable format )格式的目标文件(后缀名.o),目标文件经过链接器以后生成elf格式的映像文件(后缀名为.axf),此映像文件还有一些调试信息,经过第三方软件再将其转换为适合rom运行的.bin文件,烧进flash中运行。 可执行文件的分区 1.加载域,映像文件在存储器中存放的地址 2.运行域,映像文件运行时候的地址 每个域右1-3个输出段组成,每个输入段由1-3个输入段组成。,输入段的组成 每个输入段包含程序代码、已经初始化的数据、未经初始化的存储区、被初始化为0的存储区。

温馨提示

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

评论

0/150

提交评论