基于龙芯平台的PMON研究与开发
2011-06-05吴亚杰刘卫东曾小光
吴亚杰, 刘卫东 ,, 曾小光
(1.中国海洋大学 信息科学与工程学院,山东 青岛 266100;2.海信电器股份有限公司 山东 青岛 200071)
龙芯是中国科学院计算所研制的通用CPU,已获得MIPS科技公司的MIPS指令集的专利授权。龙芯1号的CPU主频是266 MHz,最早在2002年开始产业化应用。龙芯2号主频最高为1 GHz。龙芯3号于2010年推出成品,其设计的目标则在多核心的设计[1]。随着龙芯的发展,龙芯CPU已不仅仅局限于个人桌面计算机领域,在嵌入式开发领域,龙芯CPU也同样发展迅速,从2000年以来,越来越多的产品开始采用龙芯CPU。在计算机的体系结构中,无论是个人计算机、服务器还是嵌入式领域,基本输入输出系统BIOS是必不可少的,因为BIOS负责计算机系统的开机自检、板级硬件初始化、加载操作系统内核以及基本I/O功能。
PMON是一款ROM-Monitor型的开源软件,最初是为了LSI Logic MIPS R3000评估板的功能需求而开发的。经过多年发展,目前已经能够支持MIPS、ARM、PPC和X86等CPU体系[2]。PMON具有强大而丰富的功能,除基本的I/O功能外,还包括CPU初始化、板级外设初始化与检测、操作系统引导和调试等功能,并且 PMON支持从Flash、IDE、TFTP以及USB来启动操作系统。
1PMON框架分析
1.1PMON目录结构说明
PMON源代码的目录结构如图1所示,对于图示中关键模块说明如下:
图1 PMON目录结构Fig.1 PMON composition
1)Targets目录 Targets目录下存放的是与板级相关的代码,该目录下的每个子目录都对应着某一个具体的开发板,当要将PMON移植到一个新的开发板时,就需要在该目录新建一个子目录,并向新建的子目录中添加开发板相关的代码,其中主要有以下几个重要文件:start.S文件位于Targets/mips_board/mips_board目录下,是整个PMON运行的起点;tgt_machdep.c文件位于 Targets/mips_board/mips_board目录下,完成大部分板级外设的初始化工作;Targets/mips_board/dev目录存放板级外设的驱动程序,所需移植的网卡驱动文件即存放于此目录中;Targets/mips_board/conf目录主要存放与硬件板相关的配置文件。大部分的文件都在Targets/mips_board/compile/mips_board目录中完成编译,调试用的pmon.gdb文件即位于此目录。
2)conf目录 Conf目录下存放的是整个PMON系统的配置文件。
3)pmon目录 该目录下存放的是PMON公用的代码,包括PMON所支持的各种命令,与CPU相关的代码以及文件系统相关的代码,主要有以下几个子目录:arch目录下的子目录存放的是与CPU相关的代码;cmds目录下存放的是各种在PMON中可以使用的命令文件,比如:ifup、devcp、g等命令,如果要想向PMON中添加新的命令,需要在此目录下添加源文件、实现该命令功能即可;fs目录下存放的是与各文件系统相关的代码;common目录下存放的是一些通用代码,比如:命令解析、调试接口、异常处理、环境变量设置程序等部分;netio目录下存放的是与网络相关的命令的实现代码。
4)Sys目录 Sys目录存放的是系统支持文件。
5)Lib目录 Lib目录存放的是库的实现代码。
6)zloader.mips_board目录 最终烧写到 Nand Flash中的的gzrom.bin文件就是在该目录下经过链接而生成的。
1.2PMON初始化流程
当开发板上电之后,CPU即从0xBFC00000处取指令执行,整个PMON的入口位于start.S文件。该汇编程序主要完成CPU的初始化工作,设置异常向量入口、设置栈、初始化UART、初始化内存、初始化CACHE,并完成对PMON的代码拷贝工作,即由Nor Flash搬运到SDRAM,以提高代码执行速度[3]。最后PC指针跳转到PMON的C入口initmips函数处继续执行,从此进入C语言的执行环境。整个执行流程如图2所示。
图2 PMON初始化流程Fig.2 Flow chart of PMON initializing
在initmips函数中主要通过dbginit这个函数来完成大部分的初始化工作,主要有以下几个函数来实现初始化工作:
1)__init函数: 初始化带有 __attribute__ ((constructor))属性的函数。
2)envinit函数:环境变量初始化。
3)init_net函数:网络初始化,网卡设备的部分初始化也在这个函数中完成。
4)histinit函数:初始化历史命令记录。
在initmips函数完成初始化任务后,即跳转到pmon/common/main.c中的main函数执行,在main函数中设置完一些参数后,即进入一个while循环,等待用户输入命令,while循环内部主要有两个函数get_line和do_cmd函数。get_line函数一直试图获取用户输入的命令,而do_cmd函数负责解析命令,解析成功后,则分派相应的命令函数去执行;解析失败则返回到while循环,继续等待用户输入命令。执行到这里PMON已经完全运行起来了。此时如果需要加载内核,用load命令将内核加载到内存中,接着用g命令则传递参数给内核,并开始启动操作系统。
1.3 PMON中调试命令介绍
PMON与其他Bootloader相比,其优势在于PMON的调试功能强大。PMON本身能支持设置断点命令b、查看/设置寄存器命令r、单步执行命令t、查看堆栈信息命令bt以及继续执行命令c等调试相关的命令。b命令用于设置断点,需要注意的是在PMON中最多可以支持32个断点。r命令用于显示/设置CPU寄存器,直接输入r后会打印所有寄存器的信息。t命令用于单步执行。bt命令用于显示当前堆栈信息。c命令用于继续执行,即从当前断点处继续往下执行,相当于gdb的continue命令。除了上面列出的调试命令外,PMON还支持很多其它命令,比如:用于烧写Nor Flash的devcp命令、显示设备的devls命令、设置环境变量的set命令、显示环境变量的env命令、加载文件的load命令、运行程序的g命令等。
2PMON中网卡驱动的实现
2.1PMON查找设备
以上重点描述了PMON的整体执行过程,接下来就要具体实现在PMON中的网卡移植过程。首先要在配置文件Targets/Hiview/conf/file.Hiview中添加如下部分:
上面这部分内容定义了网卡挂载的总线,以及需要编译的网卡驱动的源代码文件等,在重新编译PMON时需要执行make cfg这个命令,此时会读取配置文件,从而生成一个名为cfdata的数组,在PMON的启动过程中会通过configure函数去配置已知的各个设备,并通过扫描有哪些设备挂在了总线上,PMON根据cfdata数组依次扫描设备。PMON首先通过config_rootfound函数来查找根设备,查找成功后再通过config_rootsearch函数来查找根设备上的子设备,子设备查找成功后则执行相应的子设备的挂载函数,通知PMON该子设备已找到,并将相应的子设备操作函数注册到PMON中。
2.2 网卡初始化
若网卡设备查找成功,则执行网卡的挂载函数,即fxp_attach函数,在fxp_attach函数中完成中断处理函数fxp_intr的注册,调用tgt_poll_register函数将中断处理函数fxp_intr注册到查询列表poll_list上。在fxp_attach函数中完成的另外一个重要工作是将网卡驱动的函数添加到PMON中,以便PMON的上层接口能够正确调用到网卡设备的下层驱动函数来实现功能,这里通过填充net_device结构体来实现,如下代码即实现了该工作:
其中打开网络设备通过net_fxp_open函数来完成,net_fxp_open主要工作是初始化网卡设备的相关寄存器,并分配用于接收、发送数据的缓冲区,设置好缓冲区的状态。net_fxp_close函数则是在关闭网络设备时调用,主要完成清除发送队列,关闭网卡的发送、接收使能等工作。net_fxp_hard_start_xmit则负责启动网卡发送数据[4]。
2.3 网卡发送与接收数据过程
当网卡设备接口处有数据传进来时就会触发一个中断,然后调用网卡接收程序net_fxp_rx函数进行处理。当网卡接收程序net_fxp_rx接收完数据或者网卡发送程序net_fxp_hard_start_xmit发送完数据后,也会触发一个中断,fxp_intr对接收到的中断进行检测,扫描网卡设备的中断寄存器,判断是接收中断还是发送完毕中断,然后根据检测结果跳转到不同的处理函数去执行,如果是接收中断,则转到net_fxp_rx_poll函数中去处理传过来的数据,并将其传递给上层协议。如果是包发送完毕中断,则跳转到net_fxp_tx_done函数,通过该函数检查网卡的发送状态并记录下发送数据的字节数等信息,检查发送队列判断是否要接着发送数据,还是发送数据任务已经全部完成。若是已完成数据的发送,则更新缓冲区状态,然后返回到中断处理函数[5]。
2.4 编译PMON
龙芯LS232 CPU是兼容MIPS指令集的,故在该CPU平台下可采用MIPS的工具链。本文的开发环境是REHL 5.5操作系统,gcc编译器采用的是gcc-3.4.6版本,在制作交叉工具链时需要加上--target=mipsel-linux参数[6]。添加完网卡驱动后,需要重新编译PMON,依次执行以下命令:
编译成功后,会在此目录下生成一个gzrom.bin文件,将其烧入Nor Flash的0xbfc00000地址处即可[7]。
2.5 测试结果
在添加完网卡驱动后,PMON重新编译成功。启动PMON后,通过使用ping程序测试(如图3所示),测试结果表明网卡驱动功能正常。
图3 ping测试Fig.3 Ping testing
3 结束语
本文是研究基于龙芯平台下的一种Bootloader(PMON)的实现。分别分析了PMON的整体框架、初始化流程、PMON的源码,在此基础上进行了网卡驱动的移植工作。代码编写及网卡移植后,完成单元测试、功能验证,PMON及网卡模块功能正常、运行稳定。
[1]龙芯官方论坛.龙芯的历程[EB/OL].(2011-05-04)[2011-06-09].http://www.loongson.cn/about_two.php?id=10&sub=龙芯的历程.
[2]PMON-LinuxMIPS.PMON[EB/OL].(2010-02-08)[2011-06-10].http://www.linux-mips.org/wiki/PMON.
[3]aaaaatiger.PMON启动流程[EB/OL].(2007-06-04)[2011-06-12].http://blog.csdn.net/aaaaatiger/article/details/1638182.
[4]宋宝华.Linux设备驱动开发详解[M].2版.北京:人民邮电出版社,2010.
[5]CorbetJ.LINUX设备驱动程序[M].魏永明,耿岳,钟书毅,译.北京:中国电力出版社,2006.
[6]STRONGCHINA.Loongson GCC安装和发布事项 2.2[EB/OL].(2008-10-07)[2011-06-23].http://bbs.lemote.com/viewthread.php?tid=18816&extra=page%3D1.
[7]CAIMOUSE.编译PMON指南 [EB/OL]. (2006-12-24)[2011-06-23].http://www.lemote.com/bbs/viewthread.php?tid=3147&extra=page%3D1%26filter%3Ddigest.