潘亚文,李宏华,蒋紫韵,吴春法
(闽南科技学院 光电信息学院,福建 泉州 362332)
嵌入式系统开发包括裸机程序开发、系统移植和应用程序开发。启动是指系统上电后CPU从运行的第一条指令开始到运行裸机程序或应用程序为止的过程。其中裸机程序开发和系统移植会涉及到启动过程,目前的启动文献绝大多数都是介绍基于系统移植U-boot的启动运行[1-3],实际上还有很多裸机程序的启动运行,这两者的启动有很大区别。实际应用中许多嵌入式系统开发都是裸机程序开发,因此理清这一启动过程,有助于整个嵌入式系统的开发。
裸机程序开发[4]从本质来说就是三个问题:一是怎样生成裸机.bin可执行程序;二是怎样将裸机.bin可执行程序烧到SoC中并启动运行;三是裸机程序的启动过程。第一个问题涉及到嵌入式开发环境,目前有集成开发环境和交叉编译开发环境两种[5-7]。第二个问题总体来说包括三类烧写方法:第一类是直接通过集成软件将.bin文件烧写到存储介质并运行[8];第二类是通过第三方软件将.bin文件直接烧写到存储介质中运行[9];第三类是通过U-boot烧写.bin文件并运行。对于第三个问题裸机程序的启动过程与第二个问题息息相关,烧写方法不同,启动过程也有所不同,下文将详细论述。
在单片机应用中,裸机程序的开发只需要在Keil集成开发环境中就可以完成,简单容易上手。而嵌入式系统开发相对复杂,针对目前嵌入式系统裸机程序的开发可以分为两种开发环境:一种是集成开发环境,另一种是自己搭建的免费交叉编译开发环境。
由于目前嵌入式系统芯片80%以上都是ARM内核,所以在此主要介绍针对ARM内核芯片的集成开发环境。一个嵌入式可执行程序的开发分为源程序编辑,汇编、编译、链接生成.bin二进制文件,调试、运行等开发步骤。所谓集成就是把上述几个步骤同时集成到一个开发环境之中。目前世界上针对不同的芯片集成开发环境有很多种,ARM公司针对ARM系列芯片面向全球开发者提供ADS和Keil MDK两大主流集成开发环境。ADS2020最新版支持Cotex-M、Cotex-A、Cotex-R系列最新芯片,Keil MDK完美支持Cortex-M、Cortex-R4、ARM7和ARM9等系列芯片。集成开发环境使用简单方便,功能齐全,开发效率高,但因它是收费软件,阻拦了大部分中小公司对其的使用。许多高校及个人仍然使用一些低版本的集成开发环境,以利于学习。
因为集成开发环境需要收费,所以ARM+Linux免费交叉编译开发环境成为越来越多的中小企业和众多爱好者的选择。目前ARM+Linux免费交叉编译开发环境是一种主流,对于进入嵌入式系统世界的开发人员这也是需要掌握的必备技能。X86架构是通用计算机芯片的架构,ARM是嵌入式系统的芯片架构,在通用计算机系统里编译出可以在ARM架构下运行的程序就是交叉编译,其结构如图1所示。ARM+Linux交叉开发环境需要开发者自己在Linux操作系统下搭建编译环境,选择合适的ARM编译工具链,因此,开发者需要掌握Linux下的各种开发流程。这种开发方式源程序编辑一般在主机Windows下编辑,可执行的.bin文件在Linux下生成,而运行又在目标机嵌入式系统里执行,因此,这种方式比较复杂。
图1 交叉编译开发环境
以A8处理器为例,其交叉编译环境的搭建过程如下:
(1)在PC端安装虚拟机VMware软件。
(2)在VMware里安装发行版Linux操作系统。
(3)从官方网站http://www.crosstool-ng.org下载已制作好的适合Cotex-A8的交叉编译工具链,如arm-cotex_a8-linux-gnueabi.tar.bz2。
(4)解压下载好的工具链。
$ cd /opt
$ tar xjf arm-cotex_a8-linux-gnueabi.tar.bz2
(5)在环境变量PATH里添加工具链的bin目录。
$ export PATH=$PATH:/opt/tools/arm-cotex_a8-linuxgnueabi.tar.bz2
(6)在/etc/environment文件里添加bin目录使当前用户不失效工具链命令。
这里启动是指嵌入式系统启动运行生成的.bin文件,由于S3C2240芯片是以一款ARM9为内核入门级的经典芯片,资料丰富,所以以S3C2440芯片为例说明从NAND FLASH和NOR FLASH启动裸机程序的过程。
2.1.1 NAND FLASH启动
以S3C2440芯片为例说明从NAND FLASH启动。NAND FLASH存储介质的特点是容量大、体积小、速度慢、价格低廉,但不能作为运行内存,常作为存储介质[10]。但是对于S3C2440芯片,如果从NAND FLASH启动,芯片会自动把NAND FLASH前4 KB的内容复制到S3C2440内部的SRAM(steppingstone)中,SRAM也只有4 KB,同时把内部的SRAM映射到内存nGCS0片选空间0x00000000,系统从SRAM的0x00000000开始运行。因此如果裸机程序的.bin文件小于4 KB,可以将程序烧写到NAND FLASH中直接启动,这是一种启动裸机程序的方式,但是源程序一开始需要做必要的芯片级初始化工作。
另一种NAND FLASH的启动方式是将U-boot放在NAND FLASH中,前4 KB的内容非常宝贵,做最基本的初始化包括初始化SDRAM的工作。然后通过U-boot将裸机程序的.bin文件下载到SDRAM中,然后跳到SDRAM中运行.bin裸机程序。这也是一种常见而简单的运行.bin裸机程序的方法。
2.1.2 NOR FLASH启动
同样以S3C2440芯片为例说明NOR FLASH启动。NOR FLASH的特点是容量很小、体积大、速度快、价格贵,主要是CPU能直接对其总线式读操作,因此常作为启动介质[11]。如果S3C2440选择NOR FLASH启动,NOR FLASH被映射到0x00000000,CPU直接从NOR FLASH开始运行。因此裸机程序的.bin文件可以直接烧写到NOR FLASH中运行。需要注意的是源程序一开始需要通过汇编程序做必要的芯片级初始化工作。
Cotex-A8处理器是一款高端处理器,主频最高可达1 GHz,目前应用在上网本、机顶盒、数字电视、家庭网络、打印机、智能家居等领域。其启动方式也很多,下面介绍以Cotex-A8为内核三星公司的S5PV210芯片启动运行程序的过程。
S5PV210系统上电后先从具有类似NOR FLASH功能的内部IROM中读取预先设置的代码BL0并执行。这一段IROM代码是三星出厂前设置的,由于不知道将来怎样外接SDRAM,因此这一段IROM是不能初始化外接SDRAM的,这一段IROM代码只能做一些基本的芯片级初始化工作。同时这一段代码会通过OM0~OM5引脚电平判断选择启动模式,S5PV210支持的几种启动模式见表1所列,然后从相应的外部存储介质去读取启动代码到内部IRAM中执行。基于上述过程,第一种方法可以把裸机程序.bin文件放入表1的存储介质中就可以启动运行;第二也可以直接把裸机程序下载到内部IRAM中运行,经验证通过USB方式把.bin文件下载到内部SRAM的0xd0000010处可以运行裸机程序;第三可以通过U-boot下载运行裸机程序的.bin文件,这需要先启动U-boot,然后下载裸机程序的.bin文件并运行。
表1 S5PV210的启动模式
下面开始介绍三个开发板,三种不同的启动流程,以理解嵌入式裸机程序的启动及运行。
这里的集成开发环境是武汉创维特公司开发的ADT集成开发环境,开发板SOC是S3C2440,实验中是将裸机程序下载到NOR FLASH中运行。由于在集成开发环境中编辑源程序及烧写程序到NOR FLASH中并执行的过程简单,这里不在祥述。需要注意的是这样的裸机源程序由一段汇编代码和C代码组成,汇编代码做基本的初始化工作并最终跳到C代码中执行,C代码是完成裸机程序功能的代码段。汇编代码段的功能:关看门狗;关总中断;关SUB子中断;配置时钟寄存器以减少PLL锁相时间;配置MPLL设置时钟频率;设置内存控制寄存器;初始化栈;设置IRQ中断处理程序;初始化存储器中的数据;跳转到C代码main函数中运行。
这里的交叉编译环境选择ARM+Linux,默认在Windows下通过虚拟机已搭建好,U-boot也已经烧录到NAND FLASH中。开发板搭载内核为Cortex-A53系列高性能八核三星处理器S5P6818,其最高主频高达1.4 GHz。由于是通过U-boot将裸机程序烧写到SDRAM中运行,U-boot一开始做了许多初始化工作,所以源程序编辑不需要汇编代码,只需要C代码就可以。其启动及运行过程如下:
(1)编辑需要运行的裸机C代码;
(2)将C代码移动到VMWare下的Linux操作系统下;
(3)利用交叉编译工具链编译C代码得到.bin文件;
(4)将.bin文件移动到Windows系统下;
(5)配置超级终端,使开发板与主机连接;
(6)启动开发板,进入U-boot模式;
(7)配置开发板IP和主机IP使相互之间可以ping通;
(8)将裸机.bin文件上传到TFTPD32软件里;
(9)U-boot下烧 写.bin文件到SDRAM,例如 tftp 0x40000000 pwm.bin;
(10)跳到SDRAM下执行裸机代码.bin,例如 go 0x40000000。
经过上述步骤,裸机程序就可以通过U-boot在SDRAM中启动运行。
这里的交叉编译环境是ARM+Linux,默认在Windows下通过虚拟机已搭建好。开发板搭载内核为Cortex-A8 系列高性能三星处理器S5PV210。由于IROM中的启动代码BL0做了芯片级初始化工作,所以这里的源程序不需要汇编代码来初始化。S5PV210裸机程序启动流程如图2所示,其运行过程如下:
(1)编辑需要运行的裸机C代码;
(2)将C代码移动到VMWare下的Linux操作系统下;
(3)利用交叉编译工具链编译C代码得到.bin文件;
(4)将.bin文件移动到SD卡里;
(5)选择相应的OM管脚电平开机即可启动目标板运行裸机程序。
图2 S5PV210裸机程序启动流程
将.bin文件移到SD卡后,开机目标板,首先运行S5PV210内部IROM中的程序BL0,并根据OM管脚选择,将SD卡的.bin文件读到S5PV210内部的IRAM中运行,裸机程序得以运行。
综上所述,启动运行裸机程序的方法有很多,但不论哪种方法都需要理清开机运行从第一行代码,直到整个裸机程序结束的过程才能很好地进行嵌入式开发。需要注意的是有的启动方法源程序是由基本初始化的汇编代码和C代码组成,有的启动方法只需要C代码。只需要C代码的启动方法中,C代码运行之前一定是在其他地方提前做好了初始化工作,比如通过U-boot下载运行裸机程序,U-boot事先做了初始化,其中S5PV210通过SD卡启动,S5PV210在内置的IROM里BL0做了基本的初始化。