嵌入式linux系统开发手册

更新时间:2023-04-24 12:17:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

嵌入式Linux系统

开发手册

郭万永(yong_bvcom@)

2003-6-23

目录

引言

第一章 嵌入linux简介

1.1 嵌入linux发展

1.2 嵌入linux开发步骤简介 1.3 嵌入linux开发模型

第二章 嵌入linux开发前期准备工作 2.1 主机系统

2.1.1 安装开发编译环境 2.1.2 配置DHCP

2.1.3 配置TFTP 2.1.4 配置NFS

2.2 目标系统 2.3 软件包获取

第三章 PPCBOOT/U-BOOT的移植 3.1 PPCBOOT/U-BOOT简介

3.2 U-BOOT源代码分析

3.2.1 与目标板相关的代码 3.2.2 与CPU相关的代码 3.2.3 头文件 3.3.4 公共代码 3.3.5 网络传输代码 3.3.6 Makefile文件

3.3.7 关键的驱动程序文件 3.3移植步骤

3.3.1 编译测试

3.3.2 U-BOOT的启动过程

3.3.3 添加自己的开发配置文件

3.3.4 目标板系统参数配置

3.3.5 串口初始化

3.3.6 SDRAM初始化

3.3.7 FLASH驱动

3.3.8 FEC以太网口初始化 3.3.9 其它 3.4 编译调试 3.4.1 编译

3.4.2 目标代码烧写 3.4.3 调试

3.5 U-BOOT命令 3.6 小结

第四章 嵌入Linux的移植 4.1 整体分析

4.1.1 平台支持 4.1.2 组件支持 4.1.3 文件系统 4.1.4 网络支持 4.2 内核源代码简单分析 4.3 重要代码说明及修改 4.3.1 串口驱动

4.3.2 FLASH驱动及MTD支持 4.3.3 FEC以太网口驱动 4.4 内核编译控制 4.4.1 内核编译 4.4.2 内核调试选项 4.5 内核的装载

4.6 引导嵌入Linux系统

4.7 关于文件系统 4.7.1 简介

4.7.2 嵌入Linux文件系统分析 4.7.3 DOC支持

4.7.4 实例分析-在FLASH上构造JFFS2文件系统 4.8 小结

第五章 应用程序开发

5.1 简介

5.2 实例:TCP SERVER及CLIENT

第六章 SNMP的实现 第七章 WEB的支持

引言:

本手册结合MPC860T硬件平台,详细叙述了PPCBOOT/UBOOT以及嵌入Linux的移植过程,介绍了SNMP和WEB组件在嵌入平台上的移植过程,同时这也可以作为在其它硬件平台上移植嵌入Linux的参考手册。 鉴于篇幅有限,本文将不会列出所涉及的源代码,主要目的是是讨论进行PPCBOOT/UBOOT和嵌入Linux移植的步骤和通常做法,不会对源代码做过多解释叙述。

第一章 嵌入linux简介

1.1 嵌入linux的发展

伴随着linux的快速成长,嵌入linux在近两年也发展迅速,与传统商业性操作系统象vxworks、psos等相比,嵌入linux没有昂贵的版权费,而且完全开放源代码,在internet上有着丰富的开发资源,支持众多CPU架构象PPC、COLDFIRE、ARM、X86、MIPS,这些有点吸引了众多的商家投入linux的怀抱。

与vxworks等典型嵌入操作系统相比,实时性是Linux的弱项,因此一些公司对linux进行了二次包装,以提高嵌入linux的实时性,比较优秀的嵌入linux有Montavista公司的Hardhat Linux,还有RTLinux、Bluecat Linux等。

优秀的网络性能是linux的招牌,嵌入linux同样对网络有着良好的支持,支持TCP/IP、PPP、IGMP、IPV6,而且提供了对ATM协议的支持。

1.2 嵌入linux的开发步骤

嵌入linux的移植开发是一项很有趣的工作,在开发的过程中会感受到linux强大

的吸引力。

首先我们以我们常见的PC来描述一下整个系统的工作流程。从打开电源的一刹那,你的CPU就开始了第一次心跳(上电复位),然后CPU会迈出自己的第一步―跳向指令的入口地址,通常是在EEPROM,FLASH ROM等永久记忆体当中,然后CPU就会按部就班的进行对自身进行最初的初始化工作,通常这些工作都是由汇编代码完成的,因为有一些寄存器只有用汇编语言才可以进行读写。

一旦跳到C语言的领域,一切变的明朗起来,无非就是对外围设备的初始化,对DRAM/SDRAM的初始化,对串口、网口等初始化,对总线设备的初始化等,不过虽然说起来容易,但事实上非常复杂,因为你要对你的所有硬件设备都很了解,这些工作完成之后就要将接力棒传给Linux的内核了,上面的工作就是我们常说的计算机BIOS所要做的工作,在嵌入Linux系统中我们给它取了新的名字,BSP(board support package)板级支持包,Bootloader引导者。

BIOS的工作完成之后就会将CPU完整的交给Linux kernel,此时BIOS的使命就结束了,剩下的就是linux内核启动,加载设备驱动程序,初始化网络协议,启动系统服务象FTP,WEB,SNMP等,详细的过程在随后的章节中在叙述。

怎么样,我想现在大概有个简单的概念了吧!嵌入linux系统从在这里我们暂且把它分为三个大部分:硬件系统、bootloader和linux kernel,他们的关系如下图:

图1 嵌入linux系统概念图

按照这个概念图来说,我们的开发步骤很简单:

设计自己的硬件系统

编写bootloader

裁减自己的linux内核

是不是太简单了,别着急,后面几章会一一把他们分解开来详细叙述。

1.3 嵌入linux开发模型

通常嵌入linux的开发分为主机系统和目标系统,他们之间通过网络接口和串口互连,网口一般用以下载程序和内核映象文件,串口一般作为console控制台来使用,在主机通过超级终端与目标系统进行命令交互,就像PC的键盘和显示器。

如果你第一次接触嵌入系统,可能会问什么是主机系统和目标系统?很简单,主机系统就是我们一般用的计算机或者工作站,用来编写代码和编译;目标系统就是你的嵌入开发系统中的硬件板。在主机开发好的目标执行代码通过网络接口或者烧写到目标系统中的永久记忆体(通常是flash或者DOC -Disk On Chip),目标系统执行这些代码。

模型如下图所示:

图2 嵌入linux系统开发模型

很简单吧,不过要注意,虽然需求很少,但有两个必要:主机至少要有一个232的通用串口(有些笔记本上却没有),还要有一个10M或100M的以太网口(关键看你的目标系统是那种网络接口),然后还有一根串口线和两根网线,如果不用HUB的话,一根单机对联线就解决问题了。硬件系统这样就搞定了!

第二章 嵌入linux开发前期准备工作

硬件系统搞定之后,还有一些软件的准备工作,俗话说“磨刀不误砍柴功!”,在未 进行正式的开发工作之前,对系统有个全面的认识,做好充足的准备,会避免好多后期将可能会出现的问题。

2.1 主机系统

前面我们讲过,主机系统通常就是我们使用的计算机或工作站,当然操作系统要是Linux,这里我的主机系统为硬件配置为: CPU: PIII550 SDRAM:256MB HARDDISK:20G

100M快速以太网卡一块,通用串行232接口 操作系统: Redhat Linux8.0 完全安装

2.1.1 安装开发编译环境 主机准备好之后还要安装交叉编译环境,用于编译目标系统可执行的代码。为什么要这个交叉编译环境呢?大家知道一般我们用的PC CPU的架构为X86,我们的目标系统为8XX架构的,所以要有一个编译器,链接器用于将C语言的代码编译为8XX系统可识别的目标代码。 你完全可以自己建立嵌入linux的交叉编译环境,可是有点烦琐,所以如果你有Montavista的CDK,那么是最好的选择了,如果没有,也可以到德国的DENX软件中心的FTP站点上下载他们的ELDK。这里以CDK为例,安装很简单,执行一个简单的Install即可,安装完成之后会在一个固定的目录下多了一些可执行文件,以8xx系统为例,在*/bin/下会有ppc_8xx-gcc ppc_8xx-objcopy ppc_8xx-ld等。

ELDK的安装相对也很简单,下载它的ELDK,实际是一个编译控制文件Makefile, 你要将所需要的源代码(一般为tar格式的)下载之后放到它指定的目录中,然后执行make, 如果没有什么错误,就会在根目录下产生一个新目录LinuxPPC,里面就是产生的编译器连接器的执行文件。这里不再详细叙述了,相关的说明可以在他们的Readme中看到。 安装好之后可以用“which ppc_8xx-gcc”来查找一下产生的目标执行文件在哪里,如果告诉你没有发现,那么很不幸你的安装没有成功(当然,首先你要将路径加到系统路径中)。

2.1.2 配置DHCP 主机系统需要设置DHCP服务器,用于目标系统在采用BOOTP启动时获取IP地址。设置之前首先要知道目标系统的MAC地址,同时要保证主机系统安装了DHCPD服务器。下面是一个典型配置,在/etc/dhcpd.conf文件中: ddns-update-style none; allow bootp;

subnet 200.162.162.0 netmask 255.255.255.0 { default-lease-time 1209600; max-lease-time 31557600; group {

host linux-8xx {

hardware Ethernet 08:00:3e:26:9d:5b; fixed-address 200.162.162.190; option root-path “/dev/nfs”; } } }

用如下命令重新启动dhcpd服务: #/etc/init.d/dhcpd restart

同时启动dhcpd服务,使主机每次启动时自动启动该服务。 2.1.3 配置TFTP服务器 TFTP(简单文件传输协议)服务器用于目标系统从主机系统上获取可执行的代码或内核映象文件。 以超级用户登录主机系统,编辑下面文件: #vim /etc/xinetd.conf 去掉下面一行的注释:

tftp dgram udp wait root /usr/sbin/tcdp in.tftpd 根目录下创建tftpboot目录: #mkdir tftpboot

将每次编译好的目标代码拷贝到该目录下,在系统服务中启动TFTPD服务。 (运行#setup , 在“System services”中选择。)然后重新启动系统即可。

2.1.4 配置NFS

NFS在我们的开发系统中主要是给目标系统提供一个根文件系统(Root Filesystem)。 首先,编辑配置文件/etc/exports: #cd /etc #vim exports 如果原来不存在,添加一行: /opt/nfsfilesystem/ *(rw,insecure,sync,no_root_squash) “/opt/nfsfilesystem/”是根文件系统所在的目录, “*”允许主机所在网段所有机器访问。 和配置TFTP一样,在系统服务中启动nfs服务,重新启动系统或运行: #/etc/init.d/nfs restart 至此,主机配置基本完毕,前期的准备工作基本搞定,还有一些小工作要做!

2.2 目标系统

目标系统就是我们的开发板,我们用的是自己开发的MPC860T开发板的一个最小系统。 一般的最小系统要包括以下几个方面: CPU肯定是要有的了; SDRAM/DRAM 最好32M或更大(反正这东西便宜);

FLASH或者DOC:FLASH最好8M或更大,这样可以建立一个可读写的文件系统,DOC最大可以到100多MB,也是不错的选择。 以太网口,当然你不要也可以,从串口下载程序吧!

串口,这可是必须的! 我们的目标系统如下: CPU: MPC860T 80MHz SDRAM: 32MB FLASH: 8/16MB 网口: FEC 100Mb

串口: rs232 X 2

目标系统硬件没什么可以说的,很简单!这里提一下一个比较重要的问题,要做好整个系统的地址分配,这在后面会用到!

2.3 软件包获取

最后要获取相关的软件开发包,假设你什么也没有,那么去DENX的FTP看看,基本可以满足需要了: ftp.denx.de.

主要获取以下软件包:

某个版本的PPCBOOT/UBOOT源代码 ELDK(如果你有CDK,这就不用了) 某个版本的LINUX KERNEL

下载这些软件包之后在某个目录下解压,以我们的为例: 下载u-boot0.2.0.tar.bz2到目录/opt; 解压: #cd /opt #bzip2 –cd u-boot0.2.0 | tar xf – 解压完成之后会产生一个目录“u-boot-0.2.0”。 内核的解压和这差不多。

当然,在Internet上有很多可以获取这些代码的地方,这里不一一列举了,举几个网站的例子:

/ /

第三章 PPCBOOT/U-BOOT的移植

3.1 PPCBOOT/U-BOOT简介

ppcboot的前身是8XXROM和FADSROM,其最高版本为PPCBOOT2.0,2.0版本以后名称就改为了U-BOOT,是由德国DENX软件中心依照GPL发布的公共软件,本手册我们结合所用的u-boot-0.2.0(其版本划分为 u-boot-*.*.*,分别为 version.subversion.patchlevel)来详细叙述整个的porting过程。我们所用的版本为u-boot-0.2.0,支持BOOTP,TFTP,SERIAL代码下载,后续版本可以引导OpenBSD, NetBSD, FreeBSD,4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR, VxWorks,LynxOS, pSOS, QNX内核映象,目前支持NetBSD,Linux,Vxworks和QNX;支持的目标CPU架构Alpha, ARM, Intel x86, IA64, MIPS, MIPS, PowerPC, IBM S390, SuperH, Sparc, Sparc 64 Bit,目前支持PowerPC。详细的说明可以参见U-BOOT目录下的README文件。

3.2 U-BOOT源代码分析

经过漫长的准备工作,现在终于可以进行实质性的工作了!首先我们来分析一下U-BOOT的源代码分布,这样才可以做到“知己知彼,百战不殆”!首先列出它的源码树(图3),然后再解剖它。

3.2.1 与目标板相关的代码

目前U-BOOT支持大多数比较常见的目标板,象MOTOROLA的ADS和FADS板,一般我们设计的主板和这些主板都是大同小异,不会有太大的差别。源代码树中board/下的每个文件夹对应一个或几个主板,象/board/fads目录对应的就是FADS板和ADS板的源代码,一些主板上的资源例如SDRAM和FLASH的初始化代码就在这个文件夹中。

3.2.2 与CPU相关的代码 该版本的U-BOOT只支持PowerPC系列的主板,与CPU相关的代码未于源代码树下的CPU/下的各个目录当中,例如我们用的相关CPU的代码就位于/cpu/mpc8xx/文件夹中,其中start.S是U-BOOT的入口代码,用汇编语言写的,是整个代码的入口,serial.c是串口的初始化代码。相应的,目录/cpu/mpc8260/对应的就是8260CPU的相关代码。

3.2.3 头文件 头文件位于源码树下的include/下,其中各种主板的配置文件位于/include/configs/文件夹中,象FADS860T主板的配置文件为/include/configs/FADS860T.h;目录/include/asm-ppc是一些比较底层的头文件,编译时会根据不同的配置与/include/configs/asm建立一个符号链接。

3.2.4 公共代码 除了和主板,CPU特性相关的代码外,其他大部分都是公用的代码,位于/common/下面,象U-BOOT的命令解析代码/common/command.c,U-BOOT环境变量处理代码environment.c等都位于该目录下。还有一个公共的代码就是PowerPC系列的主板初始化代码也是公用的,位于/lib_ppc/board.c中,在完成CPU的初始化之后就会跳到这个文件中,而与主板相关代码的执行都是在这个文件中调用的。

图3 U-BOOT源代码树

3.3.5 网络传输代码

网络传输代码位于目录中的/net/下面,象arp.c ,bootp.c,eth.c,tftp.c等都在这里,BOOTP,TFTP,以太网初始化等功能的实现也是由这些代码完成的 3.3.6 Makefile文件

Makefile文件位于U-BOOT的根目录下,是整个编译的控制主文件,后面我们会讲到如何修改该文件以添加我们自己主板的编译控制。 3.3.7 关键的驱动程序文件

U-BOOT中几个比较关键的外设驱动代码包括串口的初始化,以太网口驱动,SDRAM初始化,FLASH初始化,以FADS板为例,分别位于:

串口: /cpu/mpc8xx/serial.c

SDRAM: /board/fads/fads.c FLASH: /board/fads/flash.c ETHERNET: /cpu/mpc8xx/scc.c

FAST ETHERNET: /cpu/mpc8xx/fec.c

在我们移植的过程中这些都是我们要修改和关注的代码。

3.3 移植步骤

好了,对U-BOOT的代码有了了解之后,下面我们就一步一步的在做一个可以在我们自己主板上跑的U-BOOT! 3.3.1 编译测试

在主机开发系统上进入U-BOOT的目录中,以我的系统为例(后面的命令皆以我的系统为例):#cd /opt/u-boot-0.2.0 , 在进行编译之前设置目标板配置,U-BOOT支持的主板种类在其目录中的README中可以查到,针对FADS860T主板: #make FADS860T_config 屏幕出现:

rm –f include/config.h include/config.mk Configuring for FADS860T board… 配置成功,然后运行命令: #make

进行编译,编译完毕产生目标代码u-boot.srec u-boot.bin u-boot,说明U-BOOT和交叉编译环境都可以正常使用,下面我们就可以放心的做我们自己的主板U-BOOT了,如果有错误出现,至少不用怀疑U-BOOT和交叉编译环境了(不是完完全全不用啊!!!)。 3.3.2 U-BOOT启动过程

从哪里入手呢?先看看它的启动过程待会就知道从哪里入手了!

CPU入口函数(FLASH中运行): /cpu/mpc8xx/start.S CPU初始化(FLASH中运行): /cpu/mpc8xx/cpu_init.c

主板初始化(FLASH中运行): /lib_ppc/board.c (调用串口初始化:/cpu/mpc8xx/serial.c, sdram初始化: /board/fads/fads.c)

主板初始化(RAM中运行): /lib_ppc/board.c (调用其它公共函数)

3. 3.3 添加自己的配置文件

参照Makefile文件,选择一个与自己目标板最为相近的一个主板,我们选 择FADS860T板,在Makefile文件中 FADS860T_config: unconfig

@./mkconfig $(@:_config=) ppc mpc8xx fads

后面添加:

SUMMER860T_config: unconfig

@./mkconfig $(@:_config=) ppc mpc8xx fads

其中ppc是CPU的架构, mpc8xx是CPU对应的目录,fads是主板对应的目录,也可以新建一个目录,然后指向新的目录。

Makefile修改完毕还要添加对应的头文件,SUMMER860T_config对应的头文件应该是SUMMER860T.h, 在/include/configs/下添加该文件,你可以将FADS860T拷贝一份,命名为SUMMER860T.h:

#cd /opt/u-boot-0.2.0/include/configs #cp FADS860T.h SUMMER860T.h 完成之后,可以测试一下你的配置: #make SUMMER860T_config #make

编译成功!OK了,当然这时你编译出来的目标代码和FADS860T是一模一样的,下一步我们要根据我们的目标板进行修改了! 3.3.4 目标板系统参数配置

目标板系统参数在/include/configs/SUMMER860T.h中配置,实际只要我们对自己主板有足够的了解,然后对FADS板有足够了解,然后修改一二即可以了,下面是我修改的参数以及一些比较关键的配置说明:

#define CONFIG_MPC860 1

这不用说了,肯定是必须的

#define CONFIG_MPC860T

1

MPC860的家族有好几种CPU,他们之间有一些差别,如果你的CPU是MPC860T,这个可别忘了,不然到时你的FEC至少会跑不起来的,其它的我还不知道! #define CONFIG_FADS

1

FADS用的是SDRAM,如果你比较懒,把这个也定义上,到时把相关代码和你主板对应起来也可以用了

#define CONFIG_8xx_CONS_SMC1

1

用SMC1当串口使用,作为你的CONSOLE #define CONFIG_BAUDRATE

19200

串口的波特率,到时你的主机系统的超级终端要和这个对应,不然超级终端会有一堆乱码出现的

#define MPC8XX_FACT

1

晶阵倍频,FADS是12,我的主板设为1 #define MPC8XX_XIN

50000000

/* 4 MHz in */

晶阵频率,FADS860T是4MHz的,我的主板是50MHz的 #define MPC8XX_HZ ((MPC8XX_XIN) * (MPC8XX_FACT))

工作频率

#undef CONFIG_WATCHDOG /* watchdog disabled */

WATCHDOG先关掉 #define CFG_SDRAM_BASE

0x00000000

SDRAM起始地址,这可不能错! #define CFG_FLASH_BASE

0x02800000

FLASH的起始地址,我为它分配的基地址为0x2800000

((uint)(2 * 1024 * 1024)) /* max 8Mbyte */

#define CFG_FLASH_SIZE

FLASH的大小,悲惨,我只有2MB,不过先凑合着用,最后我会有8MB,到时又得修改它了

#define CFG_ENV_IS_IN_FLASH 1

U-BOOT的环境变量参数在FLASH中,没错,我的就是在FLASH中

0x1fc000

#define CFG_ENV_OFFSET

FLASH有TOP-BOOT-SECTOR和BOTTOM-BOOT-SECTOR之分(不知是否有那种每个SECTOR都一般大的,应该有吧?)我们用的是TOP-BOOT-SECTOR,我把U-BOOT的环境变量存在FLASH的最后一个SECTOR中,这是它在FLASH中的偏移地址。 #define CFG_ENV_SIZE

0x4000 /* Total Size of Environment Sector */

U-BOOT环境变量所占空间大小,这个足够了

#define CFG_ENV_SECT_SIZE 0x4000 /* see README – env sector total size */

U-BOOT环境变量所在FLASH SECTOR的空间大小,README中说要修改u-boot.lds,可是修改时有错误,干脆不修改了,也可以使用,是不是有什么潜在的危险呀?

#define CFG_IMMR 0xff000000

随便找个你没有用到的地址空间分配给它吧,它是内部寄存器的基地址,我给他分配我0xff000000, 不过要保证这个基地址要有64K大小的访问空间,这个地址范围可不能和其它外设的地址范围有重叠

下面还有一些寄存器的初始值设置,我没有做什么修改,但和MEMORYCONTROLLER有关的积存器还是有修改的,根据自己的主板特性,修改吧!涉及以下积存器:

OR0—OR7 BR0-BR7 MAMR/MBMR等。

其中,OR BR积存器的设置是对应你目标系统的地址划分的,你可以灵活的编程来确定每一个片选CS0—CS7所对应的地址空间。

目标板配置文件修改的差不多了,下面要进行代码修改了!

3.3.5 串口初始化

CPU的入口函数/cpu/mpc8xx/start.S不用做修改(反正我的主板没有做修改),在进 行完CPU的上电初始化之后就跳入/cpu/mpc8xx/cpu_init.c进行一些寄存器的初始化,讲起来太费时间了,找个860UM看看吧。这里我基本没有修改。CPU初始化完成后就调用/lib_ppc/board.c中的board_init_r(),首先就进行串口初始化,因为串口正常工作之后我们就可以从超级终端上看到调试信息了,那就方便了。

串口初始化代码位于/cpu/mpc8xx/serial.c,FADS板上有一个CPLD的逻辑,我们的目标板上没有,所以对应于BCSR的设置改为自己相应管脚配置。其它不用做什么修改。 这里顺便提一下,串口初始化完成之后要调用check_cpu(), check_board(), 在check_board()中FADS板会有一些访问BCSR地址的代码,我把他们屏蔽掉了!

3.3.6 SDRAM初始化

上面的工作全部是在FLASH中进行的,程序的限制很多,U-BOOT仅仅是在MPC860T内部的一小片RAM中开了一个小小的堆栈用于程序使用,你不能定义大的变量,郁闷!好,马上进行我们32MB SDRAM的初始化,完成后就可以为所欲为了。

SDRAM的初始化代码位于/board/fads/fads.c中,对应不同的SDRAM,它的UPM表是不一样的。什么是UPM表?UPM表说白了就是一些总线时序抽象为十六进制数字的产物,用数字来表示SDRAM的读写,刷新等时序。我是问我们硬件工程师要的,密密麻麻一堆数字。还有一个SDRAM上电的初始化时序,叫SDRAM POWERUP UPM表。修改时要注意,这里就不列出修改后的代码了。

SDRAM的初始化是/lib_ppc/board.c中的board_init_f()调用的,入口为intidram()。 3.3.7 FLASH驱动

在进行完SDRAM的初始化之后,U-BOOT会将代码拷贝到SDRAM中,在SDRAM中再次对CPU和CONSOLE进行一次初始化(参阅函数/lib_ppc/board.c中的board_init_r()),这些代码都基本不用做修改,其中对FLASH的初始化是我们要修改的一个部分。

FLASH的驱动位于/board/fads/flash.c,代码中涉及FLASH型号的探测,擦除,编程,扇区保护和取消保护等操作。其中有一个公共结构体flash_info_t flash_info[CFG_MAX_FLASH_BANKS]用于保存FLASH的参数。这部分要根据目标系统所用的FLASH的型号进行修改,要注意的是FLASH的数据总线宽度,是8bit,16bit还是32bit,其它按照FLASH的编程手册修改驱动即可以了。

3.3.8 FEC快速以太网口初始化

FEC快速以太网口的初始化也是在/lib_ppc/board.c中的board_init_r()函数中完成的,调用eth_initialize(),该函数位于/net/eth.c中,其中调用fec_initialize()注册了快速以太网设备FEC。

FEC的驱动程序位于/cpu/mpc8xx/fec.c文件中,我们目标系统用的PHY为LX970A,不用做大的修改,只要将FADS中涉及到BCSR控制管脚的地方改为目标系统想对应的管脚即可以了。详细的代码请参阅/cpu/mpc8xx/fec.c。

3.3.9 其它 至此,代码修改基本完成了。其它的比如打开调试信息在/include/common.h中定义 “#define DEBUG”, 此外你也可以在你比较关注的地方自己添加调试信息。

3.4 编译调试

3.4.1 编译

代码修改完毕,进行编译吧!编译之前要根据你目标系统程序入口修改你的程序代码地址(位于/board/fads/config.mk中),我们的目标系统和FADS一样为0x2800000,没有进行修改。然后运行前面提到的命令(当然要在U-BOOT的目录下): #make SUMMER860T_config #make

当然,如果你比较粗心,会出来一堆错误,不过没关系,一个一个的消灭,可以把编译信息输出到一个文件中,这样比较方便查找问题所在,用下面指令替代“#make”:

#make &>out 然后可以用:

#more out | less查看你在哪里犯了错误,把他们搞定之后,编译产生了目标执行代码u-boot.srec, u-boot.bin, u-boot, 编译完成了! 3.4.2 目标代码烧写

对于生成的三个目标文件,u-boot.srec是MOTOROLA S-Recoder格式的,u-boot.bin是二进制的,u-boot是ELF(Executable and Link Format)二进制格式的。

DENX的网站上说他们烧写FLASH用的是硬件BDM仿真器BDI2000,对这个东西不是很 了解,我们用的是WindRiver 的vision probe BDM仿真器,当然你用其它的也可以,只要能将代码烧写到FLASH中就行。我用的是ELF二进制文件,用BDM调试仿真环境vision click7.8将u-boot进行转换获得u-boot.bin,然后烧写到FLASH中,记得在FLASH的偏移地址要为0x100(针对ppc系列),烧写OK! 3.4.3 调试

好了,所有的工作基本都完成了,现在激动人心的时刻来临了,关闭目标系统电源,拔掉BDM仿真器,主机系统打开超级终端,目标系统加电,启动…, 超级终端没有任何信息出来,失败了!难道不成功?再插上BDM仿真器,单步跟踪,将PC指针设为0x2800100,执行,没有问题,程序再执行,说明生成的目标代码是有效的,可能是程序代码有问题! 调试吧,在我们移植的过程中,用BDM仿真器无法进行C语言的跟踪仿真(在调试vxworks时是可以的,可能是某个地方没有做好),另想它法吧!焊几个发光二极管到目标板上,在程序中分段点亮这几个二极管,这样可以看到程序在哪个段落出问题然后再分段查找!还有一个方法就是在程序中你认为可能出问题的地方添加对某个通用寄存器赋值的代码,然后用vision click跟踪汇编代码,到出错时查看该通用寄存器,同样可以知道程序大约运行到哪个地方!

好,先焊两个发光二极管(记着用那些没有使用的通用I/O口来控制),然后在程序中添加几个赋值语句,为OR1(我们的开发板没有用到CS1,如果你的用到了,可不能随便乱改,选一个没有用到的寄存器)赋值,不是没有信息出来吗,首先考虑是不是串口初始化失败,所以在串口初始化中添加赋值语句,重新编译U-BOOT,烧写,重新启动,二极管是亮

的,程序确实在运行,然后就是用vision click来跟踪吧,反正我最后找到的问题是在全局变量 gd(global data)结构中有个gd->flags, 在FLASH中运行代码和在RAM中运行代码时CONSOLE是不一样的,但我的console.c中在FLASH中运行puts时确调用的在RAM中运行的fputs,当然会有问题!问题就出在gd->flags,于是我把它先初始化为0(在U-BOOT中没有对gd进行初始化,这样是不是会有一些未知的问题出现?至少我觉得flags就是一个,或者是我在做CPU初始化的时候在别的地方对其进行初始化,因为此时gd是在860的内部RAM中的),改掉之后重新编译,烧写,重新启动,令人振奋!!!信息出现了: U-Boot 0.2.0 (Jun 20 2003 – 15:18:50)

CPU: XPC860xxZPnnD4 at 50 MHz: 4 kB I-Cache 4 kB D-Cache FEC present Board: SNOIC MPC860T 100M ethernet network board(Ver 1.0). DRAM: (32 MB SDRAM) 32 MB FLASH: 2 MB In: serial Out: serial Err: serial Net: FEC ETHERNET

Hit any key to stop autoboot: 2

当然了,还有其它一些调试过程就不一一叙述了,因为不同的目标系统可能遇到的问题不一样,我在调试的过程中SDRAM和FLASH都出现或多或少的问题,但是一旦console可以输出调试信息了,所有的问题都变的简单了,你可以随便添加printf(),查看任何你想看的信息,这样还有什么搞不定呢?我把调试的过程分为几个阶段: 程序代码可以在目标系统上运行 console可以输出调试信息 可以在SDRAM中运行了 其它

最基本的 具有划时代意义的 胜利的冲锋号 打扫战场

此时,u-boot的移植工作已经基本完成了。

3.5 U-BOOT命令

U-BOOT运行稳定后,可以用它的内部命令来查看目标系统的信息,设置环境变量等,

本文来源:https://www.bwwdw.com/article/jxxq.html

Top