本文介绍的移植过程基于华恒科技提供的软件包(用于HHBF531-StartKIT-R1开发板)。我
们的硬件平台是:
CPU:BF533
FLASH:S29AL004D-512KB
SDRAM:HY57V281620-16MB
下面我们分成以下几个步骤进行介绍:
一, 建立交叉编译开发环境:
1, 安装(虚拟)linux系统:
移植uclinux要在linux系统环境下交叉编译,所以需要一个linux系统。可以安装一个
完整的linux操作系统,也可以在windows系统下利用虚拟软件运行linux系统。本人不习惯
使用linux操作系统,所以在windows环境下安装了一个虚拟linux——colinux。本人下载
的colinux安装包是colinux_installer_v0.95.zip ,安装包内包含blackfin交叉编译工具
链,利用此工具包安装的虚拟linux系统内已经带有blackfin交叉编译工具链,下载地址为
:http://blackfin.uclinux.org/gf/project/bfin-colinux/frs/。
安装colinux的方法很简单,和一般的windows软件安装相同,全部采用默认值即可。唯一
要注意的是,要保证安装盘(比如说c盘)有足够的空间(大约需要3.5GB)。
安装成功后,点击你桌面上的blackfin-colinux图标就可以运行colinux了。Colinux默认
已经建立两个用户:root和uclinux,密码均为bf533。查看linux根目录下有没有/opt/uC
linux/bfin-elf、/opt/uClinux/bfin-linux-uclibc、/opt/uClinux/bfin-uclinux三个目
录,有的话blackfin交叉工具链已经安装成功,但不一定适用于本文的源码编译;因为某
些变量定义不一致可能导致华恒提供的源码编译错误,所以要使用华恒提供的软件包附带
的交叉编译工具链。
更多资料参见:http://blackfin.uclinux.org/。
2, 安装blackfin交叉编译工具链:
解压华恒软件包HHBF531-R1-v1.0.0-070327.tgz:
#tar jxvf HHBF531-R1-v1.0.0-070327.tgz
生成HHBF531-R1文件夹,内包含交叉编译工具链、uboot源码包、uclinux源码包、jtag工
具和源码镜像。
进入交叉编译工具链目录:
#cd HHBF531-R1/toolchains
交叉编译工具链是一个tgz压缩包gcc-bfin-3.4.tgz,包含的用于交叉编译的可执行文件,
直接解压到相应目录即可以使用,无需安装。
#tar jxvf gcc-bfin-3.4.tgz /usr/local/
设置编译工具目录:
#PATH=”/usr/local/gcc-bfin-3.4-uclinux/bin:$PATH”
这样,交叉编译环境就建立好了。开始华恒提供的源码吧,看看你的环境是否建立正确!
如果出现错误,仔细检查以上过程。
二, 移植u-boot:
uclinux启动离不开引导程序,这个引导程序叫作bootloader。Bootloader是在操作系统运
行之前执行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的
映射表,从而建立适当的系统软硬件环境,为最终调用操作系统内核做好准备。
U-Boot是一种通用的Bootloader,可以方便地移植到各种硬件平台上。
华恒提供的u-boot在HHBF531-R1/u-boot目录下,支持blackfin系列DSP和常用开发板。
我们这里把U-Boot的移植分成两个部分。第一部分是为我们的新开发板在目录/board/下建
立一个新目录,并拷贝最类似的开发板源码到该目录,做一些配置修改,对我们的新开发
板进行配置并编译通过;第二部分是针对我们的新开发板的特点修改相关源码文件的内容
,使其能在我们的新开发板上运行。
1, 第一部分:
我们的新开发板基于BF533,与U-Boot中的hhbf开发板最类似,我们以hhbf开发板为模板修
改得到我们新开发板的移植代码。
进入u-boot目录:
#cd HHBF531-R1/u-boot
注意要让uclinux用户用于读写操作的权限,否则下面操作时报“Permition denied.”错
误。简单点,我们直接用root用户登陆。
进入开发板目录,建立对应于我们开发板的文件目录,这里命名为naribf533。
#cd board
#cp –R hhbf naribf533
#cd naribf533
#mv hhbf.c naribf533.c(修改文件名)
删除不需要的文件:
#mv –r hhbf*
#mv psd4256.h
这样我们新开发板的文件目录和文件都有了(现在还不能在我们开发板上运行)。然后修
改naribf533目录下的Makefile和u-boot.lds,把其中的hhbf全部修改为naribf533,后面
编译过程中如果报找不到hhbf的错误也把相应的hhbf改为naribf533。
再加入一个头文件:
#cd include/configs
#cp hhbf.h naribf533.h
这个头文件中有很多内容要修改,我们将在第二部分中予以修改。
修改顶层目录下的Makefile,找到以下内容:
hhbf533_config : unconfig
@ > include/config.h
@echo “#define CONFIG_HHBF 1” >> include/config.h
@echo “#define CONFIG_BF533 1” >> include/config.h
@./mkconfig –a $(@:_config=) blackfin bf533 hhbf533 #hhtech
模仿上述语句,在下面增加以下内容:
naribf533_config : unconfig
@ > include/config.h
@echo “#define CONFIG_HHBF 1” >> include/config.h
@echo “#define CONFIG_BF533 1” >> include/config.h
@./mkconfig –a $(@:_config=) blackfin bf533 naribf533
切记在“@./mkconfig –a $(@:_config=) blackfin bf533 naribf533”前面的是Tab来的
,万万不能用空格代替,因为它是靠这个来识别命令的!
最后编译u-boot,
#make distclean
#make naribf533_config(就是在Makefile里添加的config)
#make
看看有没有错,有错的话按着提示来改,如果没错的话应该就能生成u-boot.bin这个文件
。现在还不能使用,因为这只是hhbf的一个仿制品而已。
编译正确生成u-boot.bin文件,这一部分就算完成了。下面我们尝试修改相应的源代码。
2, 第二部分:
该部分主要是修改开发板配置文件以及flash驱动。
我们先来修改开发板配置文件,让u-boot能运行起来。修改的主要内容包括:串口设置、
时钟设置、flash设置和SDRAM设置。我们的开发板上目前还没有网络功能,先不设置该内
容。
将以下设置替换原开发板配置文件相应部分即可。
串口设置,将波特率设置为115200。
#define CONFIG_BAUDRATE 115200
时钟设置,根据开发板晶振频率和系统需要的工作频率设置,我们开发板的晶振为27MHz,
内核时钟为输入时钟的22倍频,系统时钟为内核时钟的5分频,所以如下设置。
#ifdef CONFIG_BF533
#define CONFIG_CLKIN_HZ 27000000
#endif//CONFIG_BF533
#ifdef CONFIG_BF561
#define CONFIG_CLKIN_HZ 33000000
#endif//CONFIG_BF561
/* CONFIG_CLKIN_HALF controls what is passed to PLL 0=CLKIN */
/* 1=CLKIN/2 */
#define CONFIG_CLKIN_HALF 0
/* CONFIG_PLL_BYPASS controls if the PLL is used 0=don't bypass */
/* 1=bypass PLL */
#define CONFIG_PLL_BYPASS 0
/* CONFIG_VCO_MULT controls what the multiplier of the PLL is. */
/* Values can range from 1-64 */
#ifdef CONFIG_BF533
#define CONFIG_VCO_MULT 12
#endif//CONFIG_BF533
#ifdef CONFIG_BF561
#define CONFIG_VCO_MULT 10
#endif//CONFIG_BF561
/* CONFIG_CCLK_DIV controls what the core clock divider is */
/* Values can be 1, 2, 4, or 8 ONLY */
#define CONFIG_CCLK_DIV 1
/* CONFIG_SPI_BAUD controls the SPI peripheral clock divider */
/* Values can range from 2-65535 */
/* SCK Frequency = SCLK / (2 * CONFIG_SPI_BAUD) */
#define CONFIG_SPI_BAUD 2
/* CONFIG_SCLK_DIV controls what the peripheral clock divider is */
/* Values can range from 1-15 */
#define CONFIG_SCLK_DIV 4
flash设置,根据你的开发板flash容量和起始地址定制,我们的开发板flash容量为512KB
,起始地址为0x20000000。
#ifdef CONFIG_BF533
#define CFG_MAX_FLASH_BANKS 1 //flash只有一段
#define CFG_MAX_FLASH_SECT 11 //flash一共有11个sector
#endif//CONFIG_BF533
#ifdef CONFIG_BF533
#define CFG_ENV_ADDR 0x20020000
#define CFG_ENV_SECT_SIZE 0x10000
#endif//CONFIG_BF533
#ifdef CONFIG_BF533
#define FLASH_SIZE 0x80000
#define CFG_FLASH_SIZE 0x80000 //容量为512KB
#endif//CONFIG_BF533
SDRAM设置,根据你的开发板SDRAM容量和起始地址定制,我们的开发板SDRAM容量为16MB,
列地址宽度为9,起始地址为0x00000000。
#define CFG_LARGE_IMAGE_LEN 0x1000000 /* Large Image Length */
#ifdef CONFIG_BF533
#define CONFIG_MEM_SIZE 16 /* 128, 64, 32, 16 */
#endif//CONFIG_BF533
#define CONFIG_MEM_ADD_WDTH 9 /* 8, 9, 10, 11 */
#define CFG_MEMTEST_START 0x00100000 /* memtest works on */
#define CFG_MEMTEST_END 0x00f00000 /* 1..15 MB in DRAM */
#define CFG_SDRAM_BASE 0x00000000
#ifdef CONFIG_BF533
#define CFG_MAX_RAM_SIZE 0x01000000
#endif//CONFIG_BF533
如上设置后,重新编译u-boot,发现出现错误#error "CFG_MONITOR_BASE != TEXT_BASE"
,原因是TEXT_BASE设置值与配置文件不一致,主要是由于我们修改了SDRAM的容量。到b
oard/naribf533目录下修改config.mk文件,将TEXT_BASE的地址修改为0x0fc0000。接下来
编译应该没有任何错误了。
编译生成的u-boot.bin下载到开发板即可以运行了,应该能看到串口返回的u-boot成功运
行的信息。这样第一步修改就完成了。
在上面看到的u-boot运行信息里,你会发现有很多关于华恒的信息,可能你很不愿意显示
这些内容。这是因为你还没有修改flash驱动,里面显示的还是华恒提供的flash驱动显示
的内容。而且此时还不能下载uclinux镜像,因为华恒提供的flash驱动不一定适合你的开
发板,不能对你的开发板flash进行写操作。所以,我们接下来修改flash驱动。
flash驱动对应的文件是board/naribf533/flash.c,它主要包括以下几个函数:
unsigned long flash_init (void ),Flash初始化;
void flash_print_info (flash_info_t *info),打印Flash信息;
int flash_erase (flash_info_t *info, int s_first, int s_last),Flash擦除
;
volatile static int write_dword (flash_info_t *info, ulong dest, ulong d
ata),Flash写入;
int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt),
从内存复制数据。
Flash驱动修改要根据你使用的flash特性进行,参考flash的文档。主要修改内容包括:f
lash操作命令、flash扇区分配和一些打印信息。
另外,还有SDRAM的配置。除了再(board).h文件中的配置以外,如果你使用的SDRAM的刷新
频率不同于hhbf531学习板上使用的,还必须到include/asm-blackfin/mem_init.h文件中
去修改SDRAM_Tref和SDRAM_NRA两个参数。
3, 测试U-boot:
如果以上修改内容都做到了,编译得到的u-boot应该没有什么问题了,但测试还是必要的
。
u-boot能正确打印启动信息,不代表u-boot完全正确了,比如说flash不能正确擦写、SDR
AM不能正确操作等问题都可能存在。这里分一下几项内容测试u-boot。
1)测试u-boot所有命令:
在u-boot的monitor下,键入help,会显示u-boot支持的所有命令。依次测试各命令,检查
是否正确。
2)测试flash驱动:
通过u-boot的loadb和go命令,下载一个可执行程序到某个未使用的地址空间,检查是否正
确运行,以测试flash能否正确读写。
3)测试SDRAM:
SDRAM的测试往往被人忽略,其实该部分是很重要的,一旦错误可能给后面的内核移植带来
很多问题,本人就遇到这样的问题。
测试SDRAM主要包括空间的连续性和是否有空间重叠现象。
连续性测试可以通过md命令,从低地址到高地址依次打印内存信息,检查打印的地址是否
连续。
内存空间是否重叠可以通过对每MB空间写入特定数,检查各MB空间的数据是否重复,重复
则可能因为空间重叠。
除以上测试内容外,可能还有其他小问题,视情况另做测试。
通过以上测试后,你的u-boot基本就没有问题了,可以放心地利用它下载运行linux了。
U-Boot在基于ADSP BF533的嵌入式Linux系统上的移植
1 引言
Boot Loader(内核引导程序)是在操作系统内核运行之前运行的一段自举程序,用于初始化硬件设备、改变处理器运行模式、重组中断向量和建立内存空间映射图,从而将系统的软硬件带到一个合适的状态或者用户定制的特定状态,以便为最终加载操作系统内核准备好正确的环境[1]。
嵌入式Linux系统常用的Boot Loader有arm-boot、redboot、U-Boot等。U-Boot (全称Universal Boot Loader)是当前比较流行的遵循GPL条件的开放源码项目。U-Boot具有源码公开的特点,开发人员可根据自身需要进行裁减;支持多种处理器和嵌入式操作系统内核;具有多种设备驱动源码:支持种引导方式;具有功能强大且成熟、稳定等诸多优点,故在嵌入式系统开发过程中广泛采用。U-Boot严重依赖于底层硬件,不同的CPU或嵌入式板极设备需要不同的U-Boot,因此,在嵌入式系统中建立通用的U-Boot是非常困难的,故U-Boot需针对开发板量身定做。
2 开发平台
2.1 BF533简介
Blackfin系列DSP是ADI公司与Intel联合开发推出的第一款高性能、低功耗第四代定点DSP产品,融合了Analog Devices/Intel公司的微信号结构(MSA)。它将一个32位RISC型指令集和双16位乘法累加(MAC)信号处理功能与通用型微控制器所具有的易用性组合在一起。这种组合使Blackfin处理器能够在信号处理和控制处理应用中发挥最佳的性能。且Blackfin处理器通过将工业标准接口与高性能的信号处理内核相结合在一起,用户可以快速设计出节省成本的解决方案,而且无需昂贵的外部组件。
本开发系统采用BF533,BF533是主频高达600 MHz、峰值处理能力为1.2 GMI/s的高性能Blackfin处理器。BF533内核包含2个16位MAC、2个40位ALU、4个8位视频ALU以及1个40位移位器。另外,BF533还包括1个UART口、1个SPI口、2个串行口(SPORT)、4个通用定时器(其中3个具有PWM功能)、1个实时时钟、看门狗定时器以及1个并行外设接口。外部存储器控制器可与SDRAM、SRAM、Flash和ROM实现无缝连接[2]。
2.2 系统硬件平台简介
本系统的开发板硬件系统如图1所示。
目标板以Blackfin嵌入式处理器为核心,数据地址线复用到SDRAM、Flash、USB、Ethernet,并通过FPGA实现逻辑控制。此外,将UART端口转换为RS232端口引出。其中SDRAM的地址为0x00000000~0x02000000,Flash的地址为0x20000000~0x20300000。
宿主机采用Window和Suse10.0双操作系统,采用串行接口和以太网连接宿主机和目标板,程序先在宿主机上编译,然后下载至目标板上运行,目标板的终端被重定向到串行接口,由宿主机输出。
2.3 开发环境的建立
2.3.1 在宿主机上设置终端
大部分嵌入式系统在宿主机大多都采用kermit或minaicom实现与目标板的通信,本系统采用inicom。minicom是Linux下一个类似于Windows超级终端的友好串口通信程序。在终端输入bash#minicom-s进入minicom设置画面,设置串口波特率、有效数据位、停止位以及奇偶校验位分别为57 600、8 bit、1位停止位以及无奇偶校验位等。
2.3.2安装交叉编译器
交叉编译是在一个架构下编译另外一个架构的目标文件。要从http://blackfin.uclinux.org网站上下载Blackfin ToolChain,然后安装并修改环境变量PATH,使其包含ToolChain的安装目录。
3 U-Boot启动两阶段
U-Boot代码一般分为stage1和stage2两大部分。stage1依赖于cpu体系结构如设备初始化代码,常用汇编语言编写以达到短小精悍,提高系统运行效率的目的。它主要包括cpu/bf533目录下的start.s。stage2一般采用C语言编写实现复杂功能,这样代码则具有更好的可读性和可移植性,主要包括lib blackfin/board.c文件和common/main.c文件中main_loop函数。
stagel从cpu入口函数cpu/bf533/start.s开始,通常包含以下步骤:
(1)基本硬件的初始化,为随后执行kernel准备好基本的硬件环境。包括:屏蔽所有中断,引导装载程序的执行过程中不必执行任何中断,中断屏蔽可通过写cpu的中断屏蔽寄存器或状态寄存器实现;设置cpu的速度和时钟频率,初始化pll;RAM初始化,初始化内存控制器的各个寄存器;初始化UART,向串口打印U-Boot的字符信息;关闭cpu内部指令,数据cache。
(2) 为加载U-Boot的stage2准备RAM空间,通常将stage2置于整个RAM空间的最顶层1 MB空间。
(3)拷贝U-Boot的stage2到RAM。判断是否是Flash运行,如果是就将stage2的代码拷贝到TEXT BASE处。将stage2安排到RAM空间的最顶层1 MB是较推荐的方法。
(4)设置堆栈指针sp为C语言代码执行做好准备。
(5)跳转到stage2的C语言代码入口点。
stage2主要包括lib-blackfin/board.c中board_init_f、board_init_r函数以及common/main.C中main_loop函数。通常包含以下步骤:
(1)初始化此阶段需用的硬件设备,由board_init_f和board_init_r函数实现。
(2)内存映射检测。
(3)加载内核并为内核设置启动参数。
(4)调用内核。
4 U-BOOt的移植
4.1 U-Boot方法与要点
移植U-Boot简便的方法是从U-Boot支持的开发板中选择一个与其目标板接近的开发板进行修改。需修改的是与硬件相关的部分,涉及到两个层面:针对CPU的移植,由于U-Boot_1.1.3支持BF533,故只需做第二层面的移植:针对目标板硬件的移植。在移植前,需仔细阅读U-Boot/readme文件,该文件对目录结构和如何移植作了简要介绍。从移植U-Boot的最小要求、U-Boot能够正常启动的角度出发,选择BF533的STAMP板为模板,相关源代码在/board/stamp目录下,结合U-Boot的启动流程,主要修改文件如下:
(1)与目标板相关的代码部分:在board下创建mybf533目录,无需从头开始,参考与目标板相似的STAMP板在mybf533目录下创建mybf533.c、mybf533.h、flash.c、config.mk、Makefie等文件。需要修改/board/mybf533/config.mk:
TFEXT_BASE用于设置程序编译链接的起始地址即将U-Boot的stage2拷贝到SDRAM的TEXT_BASE处,即SDRAM最顶层一段存储区。修改board/mybf533/Makefile:
(2)与CPU相关的代码部分:U-Boot_1.1.3/epu文件中含有BF533的目录,其中包含start.s、cpu.c、cpu.h、interrupt.c、init_sdram.s等。故不需要建立与cpu相关的文件目录。
(3)与头文件相关的代码:在include/configs创建mybf533.h,参考include/configs/stamp.h,如下:
Flash的修改与具体型号和容量有关,修改过程中参考Flash擦除数据命令、特定寄存器的写入地址以及扇区的大小和位置。
与SDRAM相关设置:
注意:最后一行要用Tab键开头表示命令。其中blackfin表示CPU的种类.bf533是cpu bf533对应的代码目录,mybf533是目标板对应的目录。这样可使用make mybf533_config配置自身的开发板。
其他修改视情况而定。如根据SDRAM大小修改cplb表,根据需要修改堆栈大小。如drivers/cfi_flash.c中flash_init()函数,cpu/bf533/ints.c中init_IRQ()函数等。
修改完毕后就可以采用如以下命令编译U-Boot:bash$>make clean,bash$>make mrproper,bash$>make mybf533_config,bash$>make。
编译完后U-Boot_1.1.3生成U-Boot的二进制文件U-Boot.bin(U-Boot.bin只能用于更新)。执行bash$>bfin-uclinux-objcopy-I binary-Oihex U-Boot.bin,生成可在Windows下首次烧写到Flash的十六进制文件U-Boot.hex。
4.2 U-Boot的烧写
第一次下载U-Boot到目标板或者当U-Boot不能正常启动时。必须通过JTAG或者ADI ICE将U-Boot下载到目标板。在此可将ADI公司的仿真器与Visual DSP++环境相连,通过Visual DSP++,在TOOLS-->Flash Programmer下执行Flash驱动程序M25P64.dxe,选择"Erase all"-->Load Flie烧写U-Boot.hex文件到Flash中。
移植成功后,打开终端minicom复位开发板,若串口能输出正确的启动信息.则表明移植基本成功。启动后,如果在设定的时间内,串口没有接收到按键。U-Boot将自动加载操作系统内核和文件系统。若设定时间内串口接收到按键,则U-Boot停止自动加载,进入命令行,可看到U-Boot的提示符"mybf533>",查看Flash信息,调试或手动加载内核。
生成新的U-Boot.bin文件后。可通过Ethernet或者串口更新U-Boot。因为网络的传输速度远比串口快,故一般选择网络传输。将新生成的U-Boot.bin拷贝到宿主机根目录下的tftpboot目录(前提是已经创建tftp sever),在目标板出现U-Boot提示符后。按任意键进入下载模式:
mybf533>tftp 0x1000000 U-Boot.bin
0x1000000为SDRAM默认的下载地址空间,用于U-Boot的升级、调试。当需要升级或者修改U-Boot,可将新的U-Boot从SDRAM烧写到。Flash,覆盖原来的U-Boot,以减少烧写Flash的次数。在烧写以前最好测试一下所下载的U-Boot能否正常运行:
如果不正确,应重复执行Erase all和Copy命令,直到正确为止。至此,U-Boot移植的步骤已基本完成。
5 结束语
U-Boot是一个功能强大的Boot loader。前期移植工作是嵌入式系统开发的首要环节。但其移植不可避免的存在一些难以预料的问题。嵌入式开发人员应该在了解U-Boot的工作机理、移植条件后,根据目标板和具体情况灵活裁减U-Boot以提高操作系统移植的稳定性,缩短移植周期,降低产品成本。
本文结合U-Boot的运行机理以及U-Boot移植的基本要求,研究了U-Boot在基于BF533的嵌入式系统上的移植。本文的移植是在不改变U-Boot框架前提下,对嵌入式目标板和CPU相关代码进行修改,实现了成功移植且移植后的U-Boot能够在目标板上稳定运行,为后续开发奠定了良好的基础。
基于Blackfin嵌入式系统的U-boot分析与调试
引言
Boot loader代码是CPU芯片复位后进入操作系统之前执行的一段代码,主要用于完成硬件启动到操作系统启动的过渡,从而为操作系统提供基本的运行环境。Boot loader代码与CPU的内核结构、具体型号、应用系统配置及操作系统有关,其功能类似于PC机的BIOS程序。
Blackfin DSP是美国模拟器件公司与Intel联合开发的第4代DSP产品,是专为通信和互联网应用而设计的通用DSP芯片,适合处理互联网中的大量图像、声音、文本和数据流,以及汽车电子中的可视系统、宽带无线系统、消费类多媒体电子、数字摄像机、多通道VoIP、安全和监督、机顶盒和视频电话会议等。 本文对基于Blackfin 561微处理器构建的嵌入式开发板EZKIT561的U-boot第一和第二阶段的具体工作流程进行了分析,画出了各阶段的流程图,同时在U-boot第一阶段代码中加入LED指示程序来跟踪第一阶段的执行情况;而在U-boot第二阶段,则在代码的相应位置添加了向串口的打印信息,以跟踪U-boot在此阶段的执行情况。
1 Blackfin DSP简介
ADI公司推出的Blackfin处理器是专为嵌人式音频、视频、通信计算要求和功耗约束条件而设计的新型16~32位嵌入式处理器。Blackfin处理器由ADI和Intel联合开发,主要基于微信号架构(MSA)。它将一个32位RISC型指令集和双16位乘法累加(MAC)信号处理功能与通用型微控制器所具有的易用性组合在一起。这种处理特征使得Blackfin处理器在信号处理和控制处理应用中均能发挥上佳作用,因而在许多场合可免除增设单独异类处理器。
2 Boot loader及U-boot简介
2.1 Boot loader简介
Boot loader是用于初始化目标板硬件,可给嵌入式操作系统提供板上硬件资源信息,并进行装载、引导嵌人式操作系统运行的固件。最终,Boot Loader会把操作系统内核映像加载到RAM中,并将系统控制权传递给它。
大多数Boot Loader都包含两种不同的操作模式: "启动加载"模式和"下载模式"。
启动加载(Boot loading)模式也称"自主"(Autonomous)模式。即Boot Loader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行。这种模式是Boot Loader的正常工作模式,因此在嵌入式产品发布的时侯,Boot Loader显然必须工作在这种模式下。
在下载(Downloading)模式下,目标机上的Boot Loader将通过串口连接或网络连接等手段从主机(Host)下载内核映像和根文件系统映像等。从主机下载的文件通常先被Boot Loader保存到目标机的RAM,然后再被Boot Loader写到目标机的FLASH等固态存储设备中。Boot Loader的这种模式通常在第一次安装内核与根文件系统时使用;此外,以后的系统更新也会使用Boot Loader的这种模式。工作于这种模式下的Boot Loader通常都会向它的终端用户提供一个简单的命令行接口。
2.2 U-boot简介
U-Boot(全称U niversal Boot Loader)是遵循GPL条款的开放源码项目。其源码目录和编译形式与Linux内核相似。事实上,不少U-Boot源码就是相应的Linux内核源程序的简化,尤其是一些设备的驱动程序,这一点从U-Boot源码的注释中就能体现。目前支持的目标操作系统有OpenBSD,NetBSD,FreeBSD,4.4BSD,Linux,SVR4,Esix,Solaris,Irix,VxWorks,LynxOS,pSOS,QNX,RTEMS,ARTOS;这是U-Boot中Universal的一层含义,另外一层含义是U-Boot除了支持PowerPC系列处理器外,还能支持Black-fin、MIPS、x86、ARM、NIOS、XScale等诸多处理器。上述两个特点正是U-Boot项目的开发目标,即支持尽可能多的嵌入式处理器和嵌人式操作系统。U-Boot的主要目录结构如表1所列。
3 基于Blackfin DSP的U-boot运行分析
大多数Boot loader都分为stagel和stage2两大部分,U-boot也是如此。
3.1 U-boot的stagel阶段
依赖于CPU体系结构的代码(比如设备初始化代码等),通常都放在stage1中,该代码可用blackfin DSP汇编语言来实现,以达到短小精悍的目的。实际操作可在位于U-boot 1.1.3\cpu\bf533中的Start.S和Startl.S文件中实现,而且是从Start.S开始运行,此阶段的程序流程图如图1所示。
stage1的步骤以执行的先后主要包括硬件设备初始化、为加载Boot Loader的stage2准备RAM空间、拷贝Boot Loader的stage2到RAM空间、设置堆栈、跳转到stag2的C入口等。
3.2 U-boot的stage2阶段
通常stage2可用C语言来实现更复杂的功能,该代码具有更好的可读性和可移植性。Stage2实现的主要功能包括初始化本阶段要使用到的硬件设备,检测系统内存映射(memory map),将ker-nel映像和根文件系统映像从flash上读到RAM空间中,为内核设置启动参数,以及调用内核等。
而基于ADSP-BF561 EZKIT-Lite评估板的U-boot在该阶段的启动时,首先在第一阶段结束后,调用\U-boot 1.1.3\1ib_blackfin\board.c文件中的board_init_f()函数并执行。
然后再调用board.c文件中的board_init_r()函数并按先后顺序执行,其流程图如图2所示。
之后,再在board_init_r函数的最后调用\U-boot 1.1.3\common\main.c中的main_loop()函数。在执行过程中,系统会首先对自动启动内核进行倒计时,倒计时的时间由环境变量bootdelay的设定值决定。由于先前已经对串口进行了初始化,所以会在windows超级终端打印"ezkit:>",这样,mainloop()函数的执行将产生两条分支:一是等待u-boot的自启动命令执行,即执行bootcmd环境变量所设定的自动运行的命令(比如setenvbootcmd bootm 0x2000 0000),引导flash特定地址中的嵌入式操作系统;二是在u-boot的自启动命令执行前按下任意键,以进入u-boot的命令行。在此状态下可以查看和修改环境变量、下载更新U-boot和内核镜像文件、对flash进行擦写操作或通过命令启动操作系统(如bootm 0x2000 0000);
4 基于评估板的U-boot启动跟踪调试
4.1 第一阶段跟踪调试
由于U-boot的启动过程分为两个阶段,第一阶段在串口初始化之前无法获得字符串提示信息。这样,第一阶段的运行过程似乎就没办法掌握.但是,EZKIT561开发板提供16个用户可编程的LED,所以就可以通过这16个LED来了解u-boot在第一阶段的具体执行过程,即在U-boot第一阶段的几个不同的代码处添加LED指示程序。
ADSP-BF561有48个双向通用可编程I/O引脚。这些可编程引脚具有实现SPI接口的特殊功能。每一个可编程引脚均能通过操作一系列的标志控制寄存器、标志状态寄存器和标志中断寄存器来进行独立控制。由于一共有48个通用可编程I/O引脚,所以可将以上寄存器分成三组,每组可对16个通用可编程I/O引脚进行操作。
通过参考EZKIT56 1原理图可知,LED 5~20与PF 32~47 pins相连,可以跟踪堆栈配置。设计时可使用以下寄存器进行控制。
(1)FIO2_DIR寄存器
这是一个16位寄存器,若将其中的某一位设置为1,那么相应的PF引脚就可作为输出;反之,则为输入。其相关设置代码如下:
(2)FIO2_FLAG_D
这也是一个16位寄存器,对其写操作时,可指定相应的PF引脚状态;而当进行读操作时,则返回相应的PF引脚的值。它的每一位都控制着一个LED灯。其相关设置代码如下:
w [p0]=r0;
ssync;
添加的跟踪堆栈配置程序的流程图如图3所示。修改代码后即可在U-boot文件夹路径下依次输入以下命令:make clean、make mrproper、make ezkit561 config和make,然后再利用bfin-u.clinux-objcopy将生成的U-boot.bin转换为U-boot.hex,最后通过VDSP++开发环境中TOOL下的flashprogrammer将u-boot.hex烧写到flash中,同时进行复位操作以观察LED的变化。
本设计希望在堆栈配置前使LED 13、LED 14亮,其它LED灭,持续时间为1 s;而在堆栈分配之后使LED 11、LED 12亮,其它LED灭,持续时间为1 s。其实际的观察结果是,在复位之后,LED 13、LED 14持续亮1 s,接着LED 11、LED 12持续亮1秒,可见其完全达到了预期目标。
4.2 第二阶段跟踪调试
第二阶段是在进人C函数之后,就进行串口的初始化。之后,便可通过向串口打印信息来实时跟踪所启动的执行流程,以了解程序目前执行的具体部分或运行到哪一个阶段出现了问题。
下面以打印串口初始化完成信息为例。首先在U-boot第二阶段找到串口初始化的代码,即U-boot/lib-blackfin/board.c文件的serial.init()函数,然后在此函数之后添加printf("serial initializationis ok!\n")以实现打印。其程序代码如下:
修改代码后的编译和下载步骤如前所示,调试时使用的串行通信软件是windows自带的"超级终端"程序,所选择的"每秒位数" (即波特率)为57600,传输文件使用的通信协议为Kermit协议。配置好超级终端后,按下开发板上的复位键.终端便可显示出系统启动过程的相关信息。系统复位后,第一行显示的是"serial initializa-tion is ok!"。这便是自行添加的打印语句,其主要功能是提示串口初始化已完成。
由于第二阶段可以通过串口打印信息,且在相关的每一阶段均可添加相关的printf句来实现打印提示信息,所以跟踪及调试都比较容易。
5 结束语
通过分析基于Blackfin 561微处理器构建的嵌入式开发板EZKIT561的U-boot代码,以期对Boot Loader的启动过程有一个比较深入的理解,文章还通过一些调试方法对其运行阶段进行跟踪,以便对将来在开发板上的ucLinux移植和进一步的视频编解码工作进行准备。