- 基于ARM的嵌入式Bootloader实现自动升级
- 发布时间:2012-4-20 22:39:23 来源:深圳市科特鑫电子有限公司—专业的电子芯片IC资源网
-
作为一种32位的高性能、低成本、低功耗的嵌入式RISC(Reduced Instruction Set Computer)微处理器,ARM(Advanced RISC Machines)微处理器目前已经成为应用最广泛的嵌入式微处理器。和基于简单RTOS甚至没有使用任何操作系统的嵌入式程序设计相比,基于ARM- uClinux嵌入式系统的开发采用了成熟、高效、可靠、模块化、易于配置的操作系统,使程序具有良好的可移植性,博得众多嵌入式开发者的青睐[1]。嵌入式系统由硬件和软件两部分组成,软件部分主要包括Bootloader、内核和文件系统。但由于Bootloader与处理器的体系结构和具体嵌入式板级设备的配置密切相关,至今没有一个完全通用的Bootloader可以直接应用于各种嵌入式系统中,因此Bootloader成为运行嵌入式 Linux系统设计的一个关键问题。www.51kaifa.com 通常在嵌入式系统中,首先通过专用烧录器将Bootloader烧写到目标板的Flash中,然后在Bootloader中,将内核映像文件和文件系统映像文件通过串口和网络下载并烧写到Flash中。若需对内核或文件系统升级,则按上述方法重新烧写新的Kernel,Romfs直接覆盖原来的 Kernel,Romfs。这种方法中,一方面必须将目标板和主机通过串口线或网线相连,需到现场去升级,比较麻烦;另一方面,通过串口或网络烧写映像文件,速度很慢。本文分析Bootloader的结构和主要任务,并针对实际项目开发中用到的Sigma Designs 公司的EM8624L芯片(ARM7TDMI处理器+uClinux)扩充Bootloader功能,实现了通过CF存储卡或硬盘对内核或文件系统映像文件的自动升级。对需要经常为Kernel,Romfs升级的嵌入式系统来说,克服了传统升级方法的局限,简化了升级方法,提高了升级速度。www.51kaifa.com 1 ARM-uClinux嵌入式系统硬件平台 EM8624L是Sigma Designs公司的一款采用ARM7TDMI内核的高性能的嵌入式芯片,主要用于多媒体播放,尤其支持高清片源播放的场合。该芯片的特点:主频为 166MHz和200MHz(可选),没有内存单元(MMU),16KB的数据cache和16KB的指令cache,8KB的SRAM和2KB的 ISP、2KB的DSP,外围总线接口支持SDRAM、静态存储器、Flash并且有以太网(Ethemet10/100)、USB2.0接口,2个 UART接口等等,其总体设计硬件结构如图1
2 Bootloader分析 Bootloader是在操作系统内核运行之前运行的一段程序。通过此程序,可以初始化硬件设备、建立内存空间的映射图,以便为最终调用操作系统内核准备好正确的环境。 2.1 Bootloader结构及工作流程 大多数Bootloader都包含两种不同的操作模式[2]: 1)启动加载(Boot loading)模式。即Bootloader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程并没有用户的介入。 2)下载(Down loading)模式:在这种模式下,目标机的Bootloader将通过串口或网络连接等通信手段从主机下载内核映像和根文件系统映像等,然后保存到目标机上的Flash类固态存储设备中。 Bootloader的这种模式通常在系统初次安装和更新时被使用。www.51kaifa.com 基于ARM的芯片多数为复杂的片上系统(SoC),这类复杂系统里的多数硬件模块都是可配置的,因此大多数Bootloader都分为stage0 和stage1两大部分。依赖于CPU体系结构的代码,通常都放在stage0中,在这一部分,我们直接对处理器内核和硬件控制器进行编程,因此常常都用汇编语言来实现。而stage1则通常用C/C++语言来实现,这样可以实现更复杂的功能,而且代码具有更好的可读性和可移植性。 因此,Bootloader中stage0的主要任务如下:屏蔽所有中断,初始化相关GPIO(General Purpose IO),初始化SDRAM,拷贝Bootloader和Kernel到SDRAM中,关闭数据Cache,跳转到Stage1执行等。本实验在 Bootloader中实现进入stage0的代码如下: //@EM8624L has internal memory at REG_BASE_CPUwww.51kaifa.com ldr r1,=(REG_BASE_CPU + STAGE0_CRYPTO_STACK_SIZE) mov sp , r1 //@call crypto stage 0 entry function ldr r1 , =(STAGE0_CRYPTO_IMAGE_START) @new pc mov lr , pc mov pc , r1 uart_putc #’x’ , r10 , r11 Stage1的主要任务如下:初始化计时器,初始化网络,初始化Flash,装载内核映像和文件系统映像,初始化命令控制台等。进入stage1的汇编代码如下: adr r0 , load_addr //@get stage1 entry point ldr r9 , [r0 , #0x0c] 3 本实验基本原理
本实验对 Bootloader的功能进行了扩充,加入自动升级的功能。即:用户需要对目标板的内核或文件系统进行升级,只需要将新的映像文件拷贝到CF存储卡或移动硬盘中,然后将CF卡或移动硬盘插入目标板相应的插槽,每次重启目标板时,先启动Bootloader,初始化硬件环境后,在应用程序运行前,判断是否存在要升级的文件,如果存在则先把Flash指定的位置的内容擦除掉,然后再把要升级的内核或文件系统的映像文件写进相应的位置,写完后立即删除CF存储卡或移动硬盘上的升级文件,即完成升级。如图2 项目开发板上有一块8M Byte的Flash和二块32M Bit的DDR SDRAM。Flash的起始地址映射到0x00000000,其布局如下[7]:
如图所示,在虚拟地址位置0x00030000(实际物理地址为0x46030000)擦除和重写内核与文件系统映像文件。要对CF卡或移动硬盘进行文件存取,必须将CF卡或移动硬盘格式化成某种文件系统。本实验所编写的Bootloader主要支持3种文件系统:FAT16,FAT32,EXT2。系统启动时,Bootloader首先检测CF卡或移动硬盘的文件系统类型,然后按照相应的文件系统格式查询CF 卡或移动硬盘的所有文件。若发现有更新的映像文件,则读CF卡的操作,CF卡的驱动见文献[3],将映像文件读到SDRAM中,再从SDRAM烧写到嵌入式开发版的Flash中,实现升级。 生成内核和文件系统步骤如下: 1)进入linux的armutils_2.5.127.0目录下执行make linux-config,裁剪uClinux的配置; 2)make linux 生成kernel-2.4.22-dtv-EM8624L-romfs.bin ,这是uClinux的内核; 3)make rootfs 生成rootfs-dtv-EM8624L-romfs.ext2,这是root文件系统; 4)make romfs 生成romfs-dtv-EM8624L-romfs.bin.gz,这是rom文件系统。 Bootloader在系统初次安装或传统升级时烧写内核和文件系统时用Sigma Designs 公司提供的tera term软件烧写,步骤为: 1) cd ../armutils_2.5.80.0/bin 2) uuencode romfs-config-envision8624L-romfs-rom.bin.gz x > romfs-config-envision8624L-romfs-rom.bin.gz.uuencode //生成uuencode编码的文件(为ascii码,用于在windows环境下烧入flash); 3) 运行tera term出现boot > 4)运行config serial fast,然后选菜单setupàserial port,设置baud rate为115200(串口波特率); 5)在Boot>download serial romfs gz ,准备接受文件; 6)选菜单file-->send file,选中romfs-config-envision8620L-romfs-rom.bin.gz.uuencode,确定后,你会看到tera term下载文件; 7). Boot> flash romfs,把文件烧到flash中; 在本实验中,升级时将生成的内核和文件系统映像文件直接以二进制形式烧进去,不需要用uuencode转,即:把romfs-dtv-EM8624L-romfs.bin放在CF卡或移动硬盘相应的文件中进行升级即可。实现的伪代码为: #define FLASH_SIZE 0X8000000 #define LOADER_FLASHBASE 0X46030000 //romfs存放的起始物理地址 if (fp = fopen(UPDATEFILE , ”rb”)) == NULL)return;www.51kaifa.com else { Flash_erase_region(LOADER_FLASHBASE , romfs_len); //删除0x46030000开始的romfs_len长度的flash区域; Flash_write_data(LOADER_FLASHBASE ,UPDATEFILE, romfs_len); //把要升级的romfs烧写0x46030000开始的romfs_len长度的flash区域中; } remove(UPDATEFILE); //升级完后删除CF卡或移动硬盘的升级文件,以免下次启动又要开始升级; system("reboot"); //重启新系统 上述函数调用放在Bootloader的stage1中执行。
|
|
|
|