ARM Boot Loader简介(二)

来源:百度文库 编辑:神马文学网 时间:2024/04/27 15:41:06
1.3初始化存储设备
初始化存储器系统主要是对系统存储器控制器的初始化,如果系统具有存储器管理单元,也必须对其进行初始化。
ARM微处理器架构的理论寻址能力为4GB,但是对于一个特定的系统来说,所配备的实际物理存储器远没有那么多。出于对芯片的面积、成本、使用灵活性等方面的考虑,这么大容量的存储器如果设计在芯片内部是不能被接受的。因此,基于ARM微处理器的系统一般都需要外扩大容量的存储器,这些存储器是由专门的存储器控制器控制的。
因为存储器控制器并非标准ARM微处理器架构的一部分,所以不同的ARM微处理器,设计也会各不相同,初始化代码自然也会有一些差异,但一般包含如下两个方面:
1.       存储器类型和时序的配置
ARM微处理器一般都设计有多种类型的存储器接口,需要根据具体的系统设计加以正确配置,且对于同在一种类型的存储器,也会因为访问速度的差异进行不同的时序设置。
存储器接口时序优化是非常重要的,这会影响到整个系统的性能。因为一般系统运行的速度瓶颈都存在于存储器访问,所以存储器访问时序应尽可能的快;而同时又要考虑到由此带来的稳定性问题,应根据不同的情况来配置。一般一个特定的系统,需要进行多次测试,才能确定最佳的时序配置。
2.       存储器的地址分配与地址重映射
ARM微处理器架构的理论寻址能力为4GB,但是对于一个特定的系统来说,所配备的实际物理存储器远没有那么多。因此,存储器的地址分配也就是将物理存储器定位在4GB地址空间的哪个具体位置。
ARM微处理器通常采用两种方式来完成地址分配:一种方式采用固定的存储器地址分配,即物理存储器的起始地址是固定的;另一种方式采用存储器重映射的手段,使物理存储器的起始地址可以在有效的地址空间内任意改变,即物理存储器的地址是不固定的。
基于固定存储器地址分配的ARM微处理器系统,当系统的硬件设计完成以后,物理存储器地址也就确定了,在软件设计的程序流程中考虑就简单一些。而对于具有存储器地址重映射功能的系统,这个过程就复杂的多。
一种典型的存储器地址重映射过程描述如下:当系统上电或复位以后,PC指针指向0x0,程序从0x0地址开始执行,因此,为了能正确读取代码,要求此时Flash(或其它类型的ROM)的起始地址为0x0。但Flash(或其它类型的ROM)的访问速度大大低于RAM,每次产生异常后,都要从Flash(或其它类型的ROM)的异常向量表调转到相应的处理程序,会影响异常的响应速度,因此,系统便提供一种灵活的地址重映射方法,在系统完成必要地初始化以后,将RAM安排到0x0地址处,而将原来位于0x0处的Flash(或其它类型的ROM)安排到其他的地方上去,加快异常的响应速度。
这个过程中最容易出错的地方是如何保证程序执行流程的连续性。因为PC指针最初在Flash里取指令执行,在进行地址重映射以后,Flash(或其它类型的ROM)被安排到其他地址上去了,而当前地址被安排为RAM,如果事先没有对RAM的内容进行正确地设置,在往下取指令执行就会出错,即程序的连续性被存储器地址重映射这种变化所打断。
常用的处理方法是:先将Flash(或其它类型的ROM)的内容全部复制到RAM中,然后再进行地址重映射。此时尽管Flash(或其它类型的ROM)和RAM的物理地址发生了变化,但由于RAM中的内容与原来的Flash(或其它类型的ROM)是一样的,PC指针就可以继续取得正确地指令执行,从而保证了程序流程的连续性。
1.4 初始化堆栈
因为ARM有7种执行状态,每一种状态的堆栈指针寄存器(SP)都是独立的(注意System和User模式使用同一个SP)。所以,对程序中需要用到的每一种模式都要给SP定义一个堆栈地址。方法是改变状态寄存器内的状态位,使处理器切换到不同的状态,然后给SP赋值。注意:不要切换到User模式进行User模式的堆栈设置,因为进入User模式后就不能再操作CPSR回到别的模式了,可能会对接下去的程序执行造成影响。
1.5 初始化用户执行环境
主要包括初始化临界I/O设备,初始化应用程序执行环境,改变处理器的运行模式和状态,使能中断4部分。
初始化临界I/O设备。临界I/O设备是指哪些使能中断之前必须进行初始化的设备。如果不对这些设备进行必要的初始化,它们可能会在使能中断后产生一些没有意义的中断请求,从而影响程序的运行。
初始化应用程序执行环境。程序代码通过编译、链接后生成可执行映像文件,一个ARM映像文件由RO,RW和ZI三个段组成,其中RO为代码段,RW是已初始化的全局变量,ZI是未初始化的全局变量。映像一开始总是存储在ROM/Flash里面的,其RO部分即可以在ROM/Flash里面执行,也可以转移到速度更快的RAM中执行;而RW和ZI这两部分是必须转移到可写的RAM里去。所谓应用程序执行环境的初始化,就是完成必要的从ROM到RAM的数据传输和内容清零。
改变处理器的运行模式和状态。ARM微处理器在复位或上电状态下的默认模式为系统管理模式,而在初始化代码中可能需要切换到其它模式进行必要的操作,如初始化各个模式下的堆栈指针寄存器。因此,在系统的初始化过程中处理器模式一般会经历如图2所示的变化。同时,ARM微处理器在复位后总是处于ARM状态,对于兼容Thumb指令的处理器如果应用程序的入口点对应Thumb指令,则必须将微处理器切换到Thumb状态。
使能中断。如果系统需要使用中断,初始化代码应该使能中断。中断使能可以通过清除CPRS中的中断禁止位来完成。
1.6 呼叫主应用程序
当所有的系统初始化工作完成之后,就需要把程序流程转入主应用程序。如果主应用程序是由C代码编写,可以通过以下两种方式进入C代码运行,最简单的情况如下:
IMPORT         C_Entry       ;定义一个外部标号,最好不使用main
B              C_Entry       ;跳转到该处执行
在ARM的ADS编译环境中,还另外提供了一种进入C代码的机制:
IMPORT         __main
B              __main
__main()是编译器提供的一个函数,负责完成库函数的初始化和对C代码运行环境的初始化,最后自动调转到main()函数执行,此时应用程序的主函数名必须是main()。
用户可以根据需要选择是否使用main()函数,如果想让系统自动完成初始化过程,可以使用main()函数;如果所有的初始化过程都由用户自己完成,则不使用main()。