显示标签为“uboot”的博文。显示所有博文
显示标签为“uboot”的博文。显示所有博文

星期日, 二月 17, 2008

一种在U-BOOT中嵌入千兆网络功能的方法【转】

摘 要:U-BOOT是一种开放源码的、用于多种嵌入式微处理器的引导加载程序,目前U-BOOT仅支持10M/100M网络功能。本文介绍了一种让U- BOOT支持千兆网络功能的方法及所需的硬件平台结构,重点介绍了此千兆网络驱动程序的结构及设计方法,并给出了驱动程序在U-BOOT中的移植过程。该 设计可以使U-BOOT功能更加强大,使用更加方便,同时也能使嵌入式系统网络接口设计更加灵活。
关键词: U-BOOT;千兆网;AX88180;驱动

引言
U-BOOT是德国DENX小组开发的用于多种嵌入式微处理器的引导加载程序,它是系统上电后运行的第一段程序代码,用于初始化目标板 硬件,为嵌入式操作系统提供目标板硬件配置信息,并装载、引导和运行嵌入式操作系统等。U-BOOT支持网络功能,在下载操作系统内核和大的文件系统时, 比其它不支持网络的引导加载程序速度更快、更方便。目前U-BOOT仅支持10M/100M的网络功能,随着科学技术发展,千兆网络功能必将大量应用在嵌 入式系统中。本文介绍了一种让U-BOOT支持千兆网络功能的方法,可以使U-BOOT功能更加强大,使用更加方便。

U-BOOT简介
U-Boot的全称是Universal Boot Loader,它遵循GPL条款的开放源码项目,支持多种处理器,如ARM、PowerPC、MIPS等,也支持Linux、VxWorks、QNX、RTEMS、ARTOS、LynxOS等嵌入式操作系统。
U- BOOT包含两种不同的工作模式:启动加载模式和下载模式。启动加载模式也称为自主模式,即U-BOOT从目标机上的某个固态存储设备上将操作系统加载到 RAM 中运行,这种模式是U-BOOT的正常工作模式。下载模式就是在开发或生产过程中,U-BOOT通过网络连接等通信手段从主机下载操作系统内核和文件系统 等到目标机的 RAM 中,然后再写到目标机上的FLASH 类固态存储设备中。U-BOOT允许用户在这两种工作模式间进行切换,系统启动时会延时等待一段时间,如果这时用户没有按键,U-Boot就默认进入启动 加载模式。
U-BOOT代码采用一种高度模块化的编程方式,可以很方便地在不同的硬件平台上进行移植。U-BOOT下包含多个目录,如图1所示。 其中BOARD目录下存放了所有其支持的目标板子目录,比如BOARD/SMDK2440/就是本文将要用到的目标板;COMMON目录是与体系结构无关 的文件,实现各种命令的C文件;CPU目录存放了其支持的CPU类型, 比如arm920t、mips、mpc8260和nios等,每个特定的子目录中都包括cpu.c和interrupt.c、start.S; DRIVERS目录存放了各种外设接口的驱动程序,其中就包含本文用到的千兆网络的驱动程序;FS目录存放了一些文件系统,U-BOOT现在支持 cramfs、fat、fdos、jffs2和registerfs;net目录存放的是与网络有关的代码,BOOTP协议、TFTP协议、RARP协议 和NFS文件系统的实现;INCLUDE目录存放了一些相关头文件,还有对各种硬件平台支持的汇编文件、系统的配置文件和对文件系统支持的文件。



图1? U-BOOT目录

硬件平台
本文使用的硬件平台是基于S3C2440A的开发板和基于非PCI千兆以太网控制芯片AX88180的嵌入式网卡,如图2所示。 S3C2440A是ARM920T 核的16/32 位RISC嵌入式微处理器,运行频率高达500MHz,开发板上有64M NAND闪存、64M SDRAM;网卡由MAC芯片AX88180、PHY芯片88E1111、RJ45等电路组成;S3C2440A目标板与网卡之间采用目标板32位扩展总 线相连接,在产品设计时也可以将这两部分设计在同一块板上。

驱动程序
在U-BOOT中嵌入千兆网络功能需要设计千兆网卡驱动程序,并在U-BOOT中进行移植,在相应的硬件平台上实现通过千兆网口下 载等功能。网卡驱动程序主要由初始化程序eth_init(bd_t*bd)、关闭网络设备程序eth_halt(void)、发送数据包程序 eth_send(volatilevoid* packet,intlength)、接收数据包程序inteth_rx(void)等组成。初始化程序的工作主要是配置和初始化硬件,在初始化程序里可 以完成对网络控制芯片AX88180和PHY芯片的配置,比如将接口设置为1000Mbps、全双工模式等。数据发送就是将上层协议打包好的数据放在发送 数据缓冲区,然后由网卡发送到网络上;数据接收就是在网卡接收到网络传来的数据包产生中断后,从缓冲区将数据取出交给上层协议程序进行解包处理。中断服务 程序处理网卡发送数据包后、接收到数据包后产生的中断以及PHY产生的中断等。



图2 硬件平台结构框图


网卡初始化程序如下:
int eth_init (bd_t * bd)
{
...
memset (&axlocal, 0, sizeof(AX88180_PRIVATE));
RESET_MAC;
DISABLE_INTERRUPT;
WRITE_MACREG(CMD, WAKEMOD);
tmp16 = bd->bi_enetaddr[1];
macid0_val = (tmp16 << 8) | bd->bi_enetaddr[0];
tmp16 = bd->bi_enetaddr[3];
macid1_val = (tmp16 << 8) | bd->bi_enetaddr[2];
tmp16 = bd->bi_enetaddr[5];
macid2_val = (tmp16 << 8) | bd->bi_enetaddr[4];
WRITE_MACREG(MACID0, macid0_val);
WRITE_MACREG(MACID1, macid1_val);
WRITE_MACREG(MACID2, macid2_val);
ax88180_PHY_initial();
ax88180_meida_config();
WRITE_MACREG(RXFILTER, DEFAULT_RXFILTER);
INIT_TXRX_VARIABLES;
READ_MACREG(ISR, tmp_regval);
PRINTK(INIT_MSG, "ax88180: The interrupt status = 0x%08lx\n", tmp_regval);
if (tmp_regval)?WRITE_MACREG(ISR, tmp_regval);
WRITE_MACREG(CMD, RXEN | TXEN | WAKEMOD);
return 0;}

驱动移植
驱动移植是在基于S3C2440A硬件平台的U-BOOT中添加驱动程序代码和相关配置,具体如下:
1. 在drivers/目录中添加网口设备驱动程序ax88180.c和ax88180.h。
2. 在lib_arm/board.c中相应位置(参考CS8900)添加如下代码:
#ifdef CONFIG_DRIVER_AX88180
extern void ax88180_get_ enetaddr (uchar * addr);
#endif
#ifdef CONFIG_DRIVER_AX88180
ax88180_get_enetaddr (gd->bd->bi_enetaddr);
#endif
3. 在include/configs/smdk2440.h中相应位置(参考CS8900)添加如下代码:
#define CONFIG_DRIVER_AX88180?1
#define AX88180_BASE???0x08000000
4. 最后在drivers/Makefile中加入ax88180.o,重新编译生成U-BOOT即可。

结语
U-BOOT广泛应用在嵌入式系统中,本文阐述的方法可以使U-BOOT功能更强大、使用更方便,文中介绍的硬件平台给嵌入式系统千兆 网络功能的设计提供了一定的指导。本设计虽然基于S3C2440A平台,对其它类似的系统也有很好的借鉴作用,本文介绍的方法已经在产品中得到应用,效果 良好。 ■

参考文献
1. 钱峰. U-Boot在S3C44B0上的移植[J].微计算机信息.2006年第9-2期:P119-121
2. 聂强,孙贺. linux_mig_ release.pdf. http://www.hhcn.com/chinese/files
3. Allan Chou. ax88180.c.ASIX Electronics Corporation.2006

Read More...

星期四, 一月 17, 2008

使U-BOOT正确引导linux内核

1、为了能使得U-BOOT正确引导linux内核。必须传递合适的参数给内核。
修改include/configs/zj2410.h如下:
/************************************************************
* RTC
************************************************************/
#define CONFIG_RTC_S 24X0 1
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#define CONFIG_BAUDRATE 115200
/************************************************************/
/* My Add */
/* enable passing of ATAGs */#define CONFIG_CMDLINE_TAG 1
#define CONFIG_SETUP_MEMORY_TAGS 1
#define CONFIG_INITRD_TAG 1
/***********************************************************
* Command definition
***********************************************************/
#define CONFIG_COMMANDS \
(CONFIG_CMD_DFL | \
CFG_CMD_CACHE | \
CFG_CMD_NAND | \
/*CFG_CMD_EEPROM |*/ \
/*CFG_CMD_I |*/ \
/*CFG_CMD_USB |*/ \
CFG_CMD_REGINFO | \
CFG_CMD_DATE | \
CFG_CMD_ELF)
2、为了能稳定正确引导linux内核,得修改UBOOT的2410CPU频率。
smdk2410的U-BOOT原来运行频率是 ,在这个频率我已开始能正确引导内核,但是后来突然就不能引导了,
总是死在下面这个地方:
Uncompressing Linux....................................................... done, booting the kernel.
按照网上的说法,内核中,在\arch\arm\mach_s 2410\s 2410.c 中
fclk = s 2410_get_pll(MPLLCON, xtal); //读出来的fclk结果和bootloader的频率不一致。
既然不能用 ,VIVI的 能跑得好好的,那我把U-BOOT的频率改成 , 2.6.20 .3的内核和阳初光盘的2.4.18的内核都能正确稳定地引导了。
修改board/yangchu2410/smdk2410.c文件如下:
#define FCLK_SPEED 1
#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */
#define M_MDIV 0xC3
#define M_PDIV 0x4
#define M_SDIV 0x1
#elif FCLK_SPEED==1 /* Fout = 202.8MHz */
//#define M_MDIV 0xA1
//#define M_PDIV 0x3
//#define M_SDIV 0x1
#define M_MDIV 0x /* Fout = 200MHz */
#define M_PDIV 0x4
#define M_SDIV 0x0
#endif
好了,编译烧写U-BOOT到NAND FLASH,通过setenv 设置bootargs,引导内核时就可以将bootargs传递给内核了。
注意:
1、 对于U-BOOT而言,启动内核时候使用bootm命令才能传递内核参数,使用go命令是不传递内核参数的。
2、 bootm命令引导的只能是用U-BOOT的mkimage工具做过的内核映像,所以要引导阳初光盘带的内核映像,必须用其工具转换一下,至于这个工具怎么用,到U-BOOT的tools目录下找这个工具去吧,./mkimage --help 或者网上找找资料看下就知道了。^_^。

Read More...

移植uboot到2410上总结

这两天有点空闲时间,自己忙里偷闲,偷偷的在实验室的板子上移植了uboot
板子是我们自己制版焊接的,所以稳定性不是很好,不过凑合也能正常工作,一直以来工作都是用vivi,但是这个版本的vivi没有tftp下载功能,所以用xmodem协议下载zImage的时候太漫长了,而自己想移植个带tftp功能的vivi,可是由于没那么多时间就一直没成功,一直uboot也是试试,如果折腾折腾没成功,估计最后也得放弃,毕竟现在没那么多时间,而且主管也没给那个时间,这一切都是凭着工作之余,自己的兴趣所在。
板子是参考广州斯道2410的公版,还有友善之臂,反正内核什么的都没改直接就用他们的这些能正常在我们的板子上跑,我想硬件都一样吧,要不然也不能正常的跑,而且都是smdk2410公版的修改,(硬件是另一个同事做的,我具体不是很懂,不过应该和我想想的一样)
uboot是1.1.4的主要参考了
要参考了luofuchong 大侠
http://www.hhcn.com/cgi-bin/topic.cgi?forum=3&topic=562&start=0&show=
和bekars大侠
http://dev.csdn.net/article/84/84538.shtm
代码就是直接下载的xiaoluo的代码,然后打上他的补丁就ok了
make distclean
make clean
make smdk2410_config
make
就可以生成u-boot.bin了
用sjf2410烧写可以看到能够在板子上启动
一切都比较顺利(我想这都是因为xiaoluo都已经改过了)
但是还是有些问题,那就是不能正常引导内核
到Uncompressing Linux....................................................... done, booting the kernel的时候就停住了
这时候自己连uboot的基本命令都还不懂,又上网查了查用法
继续试验,还是不行,后来参考了另一个帖子,说是因为内核参数没有正确传递的原因,内核应该启动起来了,可是就是没有输出信息,和我在调试其他驱动的时候把console设为tty0一样,于是就朝着这个方向去解决问题
修改board目录下smdk2410.c
#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */
#define M_MDIV 0xC3
#define M_PDIV 0x4
#define M_SDIV 0x1
#elif FCLK_SPEED==1 /* Fout = 202.8MHz */
//#define M_MDIV 0xA1
//#define M_PDIV 0x3
//#define M_SDIV 0x1
#define M_MDIV 0x /* Fout = 200MHz */
#define M_PDIV 0x4
#define M_SDIV 0x0

#endif
在include/configs/smdk2410.h中加上

#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */

#define CONFIG_SETUP_MEMORY_TAGS 1

#define CONFIG_INITRD_TAG 1

然后重新编译uboot

重新下载后,问题还是一样,很是郁闷,就有上网抠,查到还有人说是频率不对,我下面转的

几个帖子就是。
smdk2410的U-BOOT原来运行频率是202.8M,把U-BOOT的频率改成200M,

"board/smdk2410/smdk2410.c"

#define FCLK_SPEED 1

#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */
#define M_MDIV 0xC3
#define M_PDIV 0x4
#define M_SDIV 0x1
#elif FCLK_SPEED==1 /* Fout = 202.8MHz */
//#define M_MDIV 0xA1
//#define M_PDIV 0x3
//#define M_SDIV 0x1
#define M_MDIV 0x5c /* Fout = 200MHz */
#define M_PDIV 0x4
#define M_SDIV 0x0
#endif

重新少些后问题依然,郁闷ing
后来又反复试验,在快要放弃的时候,突然发现有一次能引导kernel了
发现在这个uboot中有个bootargs参数要正确设置,由于受vivi影响,一直都是这么设置的
setenv bootargs="noinitrd console=ttyS0 root=/dev/mtdblock/4"
然后就saveenv了
以为没有问题,所以反复试验都没查这个,但是后来仔细printenv一看
bootargs="noinitrd=console=ttyS0 root=/dev/mtdblock/4"
不知道为什么多了个“=”
又反复设置,就是不能像vivi那样,不明白了,是不是这个uboot的bug还是uboot就是这样,没用过uboot不知道了
后来看设置bootcmd的时候是这样的:
setenv bootcmd=nand read 0x30000 0x1d0000
没有引号,不是自己想象的那样用引号括起来。
于是重新设置bootargs
setenv bootargs=noinitrd console=ttyS0 root=/dev/mtdblock/4
saveenv
这下终于可以boot kernel了
查点到这里就放弃了,回想起来,细心和坚持很重要,要不是坚持,可能这个问题就这么放过去了。
坚持!!!!!!!!!
再一次鼓励了我,虽然这次没什么太多的技术含量(个人感觉没有什么技术含量,就是google,还有就是直觉)
后来重新试验,发现上面修改的频率是有作用的,如果

#define M_MDIV 0x5c /* Fout = 200MHz */
#define M_PDIV 0x4
#define M_SDIV 0x0
改为
#define M_MDIV 0x5c /* Fout = 200MHz */
#define M_PDIV 0x4
#define M_SDIV 0x2
就出现了乱码,可能是波特率也随着改变了,所以有输出但是乱码,
但是

#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */

#define CONFIG_SETUP_MEMORY_TAGS 1

#define CONFIG_INITRD_TAG 1

这个还没有机会试验呢,但是我想也应该有作用的
不然kernel的参数就传递不过来了

Read More...

星期三, 一月 16, 2008

U-BOOT移植到阳初2410的板子【转】

这个好东西是从阳初论坛上下载的。我自己还没有研究,希望有兴趣的朋友可以研究一下。附件上有源代码,还有专门的word文档说明。以后研究了再放上更多的详细介绍,先发给大家玩玩!最近忙考试和制作简历,没时间!!呵呵!!!!!

以下是作者在论坛的讨论的内容:

晕死,发了半天,居然都没发上来,说我字数限制,我都没几个字。

只能传了。

写的匆忙,还没来得及改,有错的地方,望各位指出。^_^

我的工作环境:

RedHat 9

arm-linux-gcc 4.1.1(glibc2.3.2)

U-BOOT1.2.0

目标板:阳初S3C2410开发板V2.3版

买回来,板子上没有NOR FLASH,给的也只有VIVI,我想用U-BOOT(这个用的比较广),所以只能修改U-BOOT从NAND FLASH启动了。

我的内容包括:

NAND FLASH启动;

NAND FLASH驱动,让U-BOOT可以对NAND FLASH读写;

环境变量保存到NAND FLASH。

引导linux内核

参照的主要是网上的文章,我只不过相当于拼凑了一下。呵呵。

我晕,大小上传也只有100KB。只能压缩传了。

顺便把U-BOOT中修改后的几个文件也发上来:

点击浏览该文件

编译后的U-BOOT.bin,可以利用JTAG烧写到NAND FLASH运行的:

点击浏览该文件

晕,之前做的U-BOOT不能正确阳初光盘编译好的linux映像内核。

下载到板子上0x30008000运行,不行,用bootm和go命令的结果都是和前面的结果一样,最后死在这里:

……

……

Uncompressing Linux....................................................... done, booting the kernel.

往下就没了。网上查了很多文章,说法不一,各人的遇到的特殊情况不同吧。

于是,我用2.6.20.3源码make s3c2410_defconfig默认配置,编译了一下,在板子上跑了一下,结果跑起来了,但是查看启动信息,发现U-BOOT的bootargs并没传递给内核:

U-BOOT的bootargs如下:

bootargs=root=/dev/ram rw initrd="0x308000",6000000 console="ttyS0",115200 mem="64M"

而内核启动显示如下:

Kernel command line: root="/dev/hda1" ro init="/bin/bash" console="ttySAC0"

说明U-BOOT并没有设置bootargs到参数里去。
再查看U-BOOT的include/configs/yangchu2410.h文件,发现没有定义如下:

#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */

#define CONFIG_SETUP_MEMORY_TAGS 1

#define CONFIG_INITRD_TAG 1

而#define CONFIG_CMDLINE_TAG 1是在传递cmdline时候必须设置的,所以在include/configs/yangchu2410.h文件中添加如上定义。

定义之后,重新编译U-BOOT,烧写到NAND FLASH中,启动板子。

再跑上面编译的2.6.20.3linux,内核启动信息中显示的参数信息和U-BOOT中设置的一致了。

设置U-BOOT的bootargs:noinitrd root="/dev/mtdblock/2" console="ttyS0" mac="00:01:5d:68:7a:0f",再跑阳初光盘带的linxu内核,往下看到兴奋的字眼了:

YANGCHU2410 # bootm 30008000

## Booting image at 30008000 ...

Image Name: yangchu_linux2.4.18

Created: 2007-08-26 8:06:16 UTC

Image Type: ARM Linux Kernel Image (uncompressed)

Data Size: 772272 Bytes = 754.2 kB

Load Address: 30008000

Entry Point: 30008040

Verifying Checksum ... OK

XIP Kernel Image ... OK

Starting kernel ...

Uncompressing Linux....................................................... done, booting the kernel.

Linux version 2.4.18-rmk7-pxa1 (fc@localhost.localdomain) (gcc version 2.95.3 20010315 (release)) #441 7 10 11:29:04 CST 2007

CPU: ARM/CIRRUS Arm920Tsid(wb) revision 0

Machine: Samsung-SMDK2410

On node 0 totalpages: 16384

zone(0): 16384 pages.

zone(1): 0 pages.

zone(2): 0 pages.

Kernel command line: noinitrd root="/dev/mtdblock/2" console="ttyS0" mac="00:01:5d:68:7a:0f"
……
……

楼顶的文章我已经改过了,上传了我更新过的文章。

相应要要修改的U-BOOT以及编译好的uboot.bin也重新上传了

UBOOT引导内核真是搞怪,前几天还能引导的,这几天又不能引导了,但是这些内核用VIVI都是能引导的,搞得头痛死了,总是死在下面这个地方:
Uncompressing Linux....................................................... done, booting the kernel.

后来发现是频率的问题。因为网上有人也遇到此问题,相关说法如下:

之后用仿真器追踪内核结果发现:

start_kernel函数的time_init()中程序进入死循环~~

我随之进入time_init()

继续进入 system_timer->init();

结果发现,我的fclk,pclk都不能得到正确的值,积存器正确,我拿笔都能算出来,可是他就是总出错,所以我一气之下把他们全部写死.

具体如下:
在\arch\arm\mach_s3c2410\s3c2410.c 中 搜索 fclk ;

fclk = s3c2410_get_pll(MPLLCON, xtal); //这是他原来的,结果不是我们想要的200MHZ
fclk =200*1000*1000 ; // 这是我加的
在\arch\arm\mach_s3c2410\time.c 中搜索 pclk:

pclk = clk_get_rate(clk); //这是原来的

pclk = 50*1000*1000; //这是我加的

当然这都是根据2410的DATASHEET而定的

我现在用的是FCLK : HCLK : PCLK = 1 : 2 : 4 ,所以我分别写死为200M 100M 50M.

看来我的问题差不多也出在这边了,fclk得不到正确的值,由于没有仿真器,只能这么推测了。因为我终端上显示出来的传递参数都没有问题。

我再看了看VIVI,它里面用的就是200M。

smdk2410的U-BOOT原来运行频率是202.8M,后来把U-BOOT的频率改成200M,2.6.20.3的内核和阳初光盘的2.4.18的内核都能稳定地引导了。

修改文件如下:

"board/yangchu2410/smdk2410.c"

#define FCLK_SPEED 1

#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */
#define M_MDIV 0xC3
#define M_PDIV 0x4
#define M_SDIV 0x1
#elif FCLK_SPEED==1 /* Fout = 202.8MHz */
//#define M_MDIV 0xA1
//#define M_PDIV 0x3
//#define M_SDIV 0x1
#define M_MDIV 0x5c /* Fout = 200MHz */
#define M_PDIV 0x4
#define M_SDIV 0x0
#endif

Read More...