摘要:本文介绍基于NIOS的开发过程,以及详细介绍向该开发板移植uClinux操作系统和引导代码U-boot Bootloader的过程以及移植前的准备工作。 关键词:NIOS Bootloader U-boot uClinux 嵌入式系统
1.引言: NIOS 主要是利用了Altera公司的最新的SOPC——NIOS软核处理器技术,通过将包括16或32位高性能处理器在内的多种应用模块嵌入到一个通用的FPGA/CPLD内,实现了一个完全可重置的嵌入式系统。以RISC为基础的NIOS是可配置、可伸缩的软核处理器,具有16位指令集和16/32位数据通路,可以与Altera APEX PLD系列组合使用。例如,NIOS与APEX 20KE结构组合时,其传送速度为5MIPS,占用约1000个逻辑单元,相当于APEX EP20K 200F容量的12%。其开发套件,包括具有必要的外围内核的NIOS处理器、C/C++编译器、Cygnus的源级调试程序、Quartus编译软件、验证工具和开发板。uClinux应用于没有内存管理单元MMU的微处理器的Linux的衍生操作系统。uClinux支持多任务,由于它的很多核心代码都为没有被MMU的处理器重新编写过,所以它的内核要比常规的Linux内核小很多;它同时保留了常规Linux操作系统绝大多数的优点。 在移植uClinux之前要做一些准备工作,比如调试器是否可以正常工作,交叉编译环境的建立等。然后,再开始启动代码的移植和uClinux的移植。考虑到以下需求 硬件需求: 我们需要一个Altera公司的开发包,本文选用的是CDK4NIOS,它是NIOS的交叉开发包。同时选用CYCLONE board。 软件需求: 我们下载一个最新版本的uClinux,以及搭建一个NIOS 的GNU C编译环境。
2.引导程序U-boot的移植 Bootloader的设计除了依赖于 CPU 的体系结构外,它实际上也依赖于具体的嵌入式板级设备的配置。这也就是说,对于两块不同的嵌入式板而言,即使它们是基于同一种 CPU 而构建的,要想让运行在一块板子上的 Bootloader 程序也能运行在另一块板子上,通常也都需要修改 Bootloader 的源程序。在移植操作系统时,这部分代码必须加以改写。 Bootloader 引导加载程序是系统加电后运行的第一段软件代码。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。启动代码可以利用已有的开放源代码的启动代码进行改动移植到己的板卡上。常见的Bootloader有ARMBOOT、EDBOOT、DBUG、BLOB等。由于大多数Bootloader完的功能比较类似,因此选择一个免费的开放源码的Bootloader进行移植是比较可行的做法。这里采用U-boot为引导程序并进行了移植。 U-boot是由早期的ppcboot的基础上发展起来的,并作为 PowerPC 、 ARM9 、 Xscale 、 X86 等系统通用的Linux Bootloader备受青睐. 它对Linux有特别的引导功能,而且还在开发和完善中,这些功能对我们来说足够了。下面介绍U-boot移植过程。 (1)宿主机上建立交叉编译环境 首先要在Linux机器上建立NIOS的交叉编译环境。从http://www.uclinux.org/ 上下载的NIOS-elf-tools安装在Linux宿主机上的/usr/local/bin目录下。现在的U-boot和将来的uClinux都要在这个环境下编译。 (2)选择下载适当的U-boot版本并安装U-boot的源代码要寻找到移植过程中需要改动最少的U-boot版本,可以选用U-boot-1.0.0.tar,我们可以用它开始U-boot移植 . (3)选择适当的uClinux版本并安装uClinux源代码 因为在编译U-boot的时候U-boot需要uClinux的SOURCE CODE,所以我们现在就需要将uClinux的源代码下载并安装在这台宿主机上。uClinux也要选择一个需要改动最少的版本进行移植,同样,我们选择的是http://www.start-web.net/tpu/ 上下载的uClinxu-2.4.17-uc1.tgz 。将它安装在宿主机上的某一个目录上/path/to/nioslinux/source 。这个uClinux-2.4.17-uc1.tgz就是我们选择的要进行移植的uClinux版本。 (4)通过U-boot的Configure检验U-boot编译环境是否建立. 根据U-boot的README,我们试图在宿主机上先将U-boot build起来!这一步我们将要用configure命令检查宿主机上的U-boot交叉编译环境是否正确的安装配置,并且通过configure文件的内容对U-boot各子目录的makefile进行修改。也许最后的make会报错,但这在此并不重要。这一步只要保证./configure通过就可以了。 (5)用建立起来的交叉编译环境编译 最初的U-boot这一步要编译通过U-boot生成初始的U-boot。因为编译器的不同,所以允许编译器对NIOS指令的解释有所不同。我们用NIOS-elf-*来编译这个U-boot-1.0.0。编译通过后,就建立好了U-boot的编译环境,下一步可开始针对开发板的特殊情况进行移植工作了。 (6)修改U-boot源代码进行移植 这一步是向开发板移植U-boot。上面的工作建立起编译U-boot的环境,下面要修改与开发板相关的源文件,然后编译得到U-boot即可。这一步需要参考./doc/NIOS文件的内容,这里讲的就是如何移植U-boot。大概需要修改以下文件。 ◆ ./congiure,是可执行的脚本文件,里面有NIOS-elf-gcc的编译选项。要针对开发板修改 ◆ ./src/lib/led.c中的点灯和关灯函数需要针对自己的板卡中LED的地址进行修改。 ◆ ./src/lib/serial.c,是相关串行口的。看看它的主频设置。 ◆ ./src/U-boot/ledasm.S,需要根据板卡中LED的地址来修改,同led.c 。 ◆ ./src/U-boot/start.S,是系统加电后最开始运行的部分,也是将要写到零地址的内容。里面将要对一系列NIOS的寄存器进行填充。 ◆ ./src/U-boot/main.c,相当于U-boot的核心主控程序,我们关心的是int main(void)函数。它提供给用户一个简单的命令行,控制着U-boot的行为。 ◆ ./src/U-boot/linux.c,是启动Linux内核U-boot的最后的代码,由它跳离U-boot然后跳转到Linux核心。这里我们关心的是static int boot_linux(int argc, char *arg函数,它首先设置Linux启动参数,做好最后启动的准备,然后跳转到the Kernel。整个启动流程如图:

以上便是需要修改的大部分文件。修改后,参考README中的内容重新把U-boot build起来,最终编译出来的./src/U-boot/目录下的U-boot,就是我们最终需要的可以直接运行在Flash中的执行代码。 (7)编译后的U-boot下载到开发板中完成U-boot移植 这是最后一步,将修改并编译后的U-boot通过Flash编程下载到开发板中Flash的零地址,这样U-boot的移植工作就完成了。此时只要将开发板重新加电或者RESET,系统就将从Flash中零地址的U-boot开始执行。此时,我们可以通过串口(windows的超级终端或Linux的minicom)来观察控制开发板上的U-boot;将来就可以通过这个开发板上的U-boot下载编译好的uClinux内核以及ramdisk。这一步为uClinux的移植开发打下了非常好的基础。
4. uClinux移植 U-boot移植成功后,我们就可以开始uClinux的移植,移植过程如下: uClinux的内核配置 在编译uClinux内核之前,首先要对内核进行配置。可以用make menuconfig进行内核的配置,要根据我们的板卡将必要的选项选中,将没有必要的选项去掉。 (1)系统类型的配置 在System Type中,选定NIOS system type,然后设置SDRAM/Flash的地址。 (2)通用内核选项General setup的配置我们针对将来的应用选择选项。 (3)块设备Block devices的选择和配置我们选定RAM disk support并且设置RAMDISK的大小(Default RAM disk size)为1024KB,同时将它设置为Initial RAM disk (initrd) support。这样它可以作为根文件系统的块设备。引导程序U-boot提供了RAM DISK的支持,使得使用和调试RAMDISK更加方便容易。 (4)文件系统的选择和配置有了块设备,还要选择它上面的文件系统。首先选定 /proc file system support,这是/proc文件系统,记录着系统运行时的信息。还要选定ROM file system sup-port ,这里我们选择ROM fs作为RAMDISK块设备上面的根文件系统(可以直接genromfs,即可生成所需大小的romfs,而不像RAMDISK一定要生成1024KB的映像)。然后选择Second extend fs support,这是设备ram0 ,ram1上所用的文件系统。 (5)选择字符设备驱动Character devices这一步要选择串行口驱动,进入Serial drivers选项,然后选定NIOS serial port support ,这样在内核中加入了对NIOS的串行口的支持,就可以通过串口将内核打印的信息传递给主机。至此完成了初步的uClinux内核的配置。 修改并编译内核 将下载好的uclinux源代码解压到/home目录下,会产生/home/uClinux-dist目录,进入该目录,依次键入: make menuconfig make dep make 在/home/uClinux-dist/image目录中产生Image.rom,Image.ram,Romfs.Img,他们分别是内核的映像,文件系统的映像文件。Make menuconfig时会出现开发平台,内核配置,文件系统应用程序的配置界面,可以根据需要配置。 配置uClinux的文件系统 在内核启动之后,就会将romfs作为根文件系统;而romfs中的应用程序需要保证有init和sh。这样在内核运行的最后,将有一个简单的shell界面,我们也可以向romfs中添加自己的应用。将下载的uClinux-dist-20030909.tar.gz 解压缩到宿主机上的一个目录下,准备配置编译使用这个uClinux-dist中的文件系统。在./uClinux-dist/目录下运行make menuconfig 。然后 编译 make clean dep linux。这一步我们只需要里面的文件系统部分。最后在./uClinux-dist目录下生成了romfs目录。里面的内容就是我们所需要的。查看编译结果的文件系统部分并进行修改。查看一下romfs目录下的每个目录,看看里面是不是所需要的文件,生成系统romfs.img. 在开发板上运行uClinux 给开发板加电,系统自动开始运行U-boot。超终端显示了U-boot运行的信息,然后回车进入命令行状态,得到提示符,用xdownload kernel下载zImage。下载结束后,用xdownload ramdisk下载romfs.img。都结束后运行 boot,会出现starting kernel,然后便是Uncompressing Linux.....................booting the kernel。内核正在开始启动。在启动的最后便是uClinux的欢迎信息和简单的shell提示符。 下载到开发板上的Flash中 当uClinux内核比较稳定并不需要经常修改的时候,可以将它下载到开发板中的Flash中。此时可以继续为开发板开发它的应用,然后将应用加入到romfs中。当romfs不需要经常修改的时候它也被下载到开发板中的Flash中。这样便完成了开发板uClinux的移植。
结束语: uClinux是Linux的一个分支,它保留了Linux稳定和优异的网络能力以及优秀的文件系统支持的特点,同时又克服了Linux必须依赖与MMU的不足,是一种优秀的嵌入式操作系统。同时NIOS又是一种高效、低功耗的RISC处理器。二者的结合将使基于NIOS和uClinux的嵌入式产品有更高的竞争力。 参考文献: [1]阳富民 徐刚 涂刚 胡贯荣 。基于EDB7312开发板的嵌入式LINUX的实现 计算机工程与应用 2003.18:138 [2]AlteraCorporation.News&Views, Sencond Quarter 2002:15~22 [3] Altera Corporation。Simulating Nios Embeded Processor Designs. AN-189-2.1,February 2003:14~30 [4]王彩云。嵌入式Nios微处理器在FPGA中的开发应用。电子设计与应用,2003。8 :58~61 [5]Altera Corporation.Custom Instruction for the Nios Embeded Processor.AN-188-1.2,September 2002:1~9
|