这里首先我得相当佩服鲁郁大哥的精彩的帖子。幽默风趣,看得我直乐了,你的帖子相当不错,对了,在这里声明一下,你说的地址的问题,已经在我的板子上改过来了,看来你说的对。这里我把这为大哥的东西在重复一下吧。
先下载一个叫loader.bin的小程序,
这个小程序的主要任务就是初始化基本的硬件。AT91rm9200初始上电时是不可能知道你的板
上的硬件配置的,比如SDRAM的信息。每个人设计的硬件千差万别,SDRAM的映射地址和容量
都不一样,处理器怎么可能知道这些信息?loader.bin就是帮助来完成这些最基本的工作,
而loader.bin是绝对硬件相关的,硬件资源如果改动,loader.bin也要做相应改动,仔细看
看 loader的源代码就会有更深刻的认识。有人会问:为什么不直接利用U-
boot来干这个活呢?U-boot也是很硬件相关的呀?
这个问题就牵扯到AT91rm9200的片内资源:
在硬件初始化完成之前,程序只有片内sram可用,多大容量呢? 绝对少于20KB.
所以只可能跑一些很小很高效的程序,而U-
boot的功能非常强大,代价之一就是其身躯略显臃肿,多臃肿呢?在我的编译结果里,
其大小在100KB左右,所以在一开始是不能跑U-boot的。
于是我先用XModem下载loader.bin,完成硬件初始化,然后再下载我刚编译完的U-
boot.bin,然后.......就死翘翘了。什么也没有出现,连一句问候都没有。
我仔细擦了擦眼镜,依然什么也没有;我使劲按了按AT91rm9200,还是什么都没有;
而我用别人编译好地1.1.0的版本一切正常。我知道, 真正的战斗开始了。
于是昏天黑地, 没日没夜, 上窜下跳的折腾了一个星期,找到问题所在了:
在这个文件, u-boot.1.1.4/include/configs/at91rm9200dk.h 里,
有一个预编译宏CONFIG_SKIP_LOWLEVEL_INIT。 这个宏如果没有定义, U-
boot就要自己来初始化硬件了。在我的情况下, 这一步已经被loader.bin干过了,
再干一次会出问题。 所以我需要略过这一步, 于是我定义该宏如下:
#define CONFIG_SKIP_LOWLEVEL_INIT
然后回过头从新make,新的错误出现:
cpu/arm920t/start.o(.text+0xec):/home/luyu/proj/u-boot-1.1.4/cpu/arm920t/start.S:265: undefined reference to `lowlevel_init'
make: *** [u-boot] Error 1
打开文件cpu/arm920t/start.S, 看起来是U-boot1.1.4的一个臭虫:
如果不定义CONFIG_SKIP_LOWLEVEL_INIT, 如下代码就不会被编译,
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
但是他忘了把cpu_init_crit这个函数一起预编译出局。于是我加了预编译宏代码如下:
/*
*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/
//added by Yu Lu
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
/*
* flush v4 I/D caches
*/
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
/*
* disable MMU stuff and caches
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
orr r0, r0, #0x00000002 @ set bit 2 (A) Align
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
mcr p15, 0, r0, c1, c0, 0
/*
* before relocating, we have to setup RAM timing
* because memory timing is board-dependend, you will
* find a lowlevel_init.S in your board directory.
*/
mov ip, lr
bl lowlevel_init
mov lr, ip
mov pc, lr
//added by Yu Lu
#endif
从新make. 一切正常。 这次从新下载loader.bin和新的u-boot.bin. 感谢如来佛,
我终于看到了久违的问候界面!试着键入help, 看来一切都正常。 除了IP地址和server
IP地址。在include/configs/at91rm9200dk.h 文件里, 我定义了如下的环境变量:
#define CONFIG_DEFAULT_ENVIRONMENT
#define CONFIG_BOARDNAME "AT91RM9200DK"
#define CONFIG_ETHADDR "00:11:22:33:44:55"
#define CONFIG_IPADDR "192.168.0.110"
#define CONFIG_SERVERIP "192.168.0.100"
#define CONFIG_GATEWAYIP "192.168.0.1"
#define CONFIG_BOOTCOMMAND "tftp 0x20008000 zImage_at; tftp 0x21000000 ramdisk; go 0x20008000"
#define CONFIG_DEFAULT_KERNEL "2.6.17"
但现在我的IP地址是0.192.168.0, serverip也是0.192.168.0。 这是很奇怪的事情,
看起来U-boot只取了我定义的环境变量的前3个字节,然后把ip地址的第一位置0。
二话不说, 开始调试。现在容易多了,因为我可以用串口输出中间变量的值来DEBUG。
一会儿功夫,发现罪魁:
在文件net/net.c, 有一个函数IPaddr_t getenv_IPaddr(char *var),
其功能是从环境变量(字符串类型)中获取IPaddr_t格式的ip地址。var应该包含我在at91rm9
200dk.h里的输入, 这里应该是192.168.0.100, 但是我的调试显示,
其值是"192.168.0.100", 第一个"因为不是合法字符, 所以u-
boot将第一个IP地址的字节设为0,
然后从后面的合法字符中取3个字节。就成了0.192.168.0。 改之:
IPaddr_t getenv_IPaddr (char *var)
{
/* new code changed by Yu Lu ,
to solve the problem of
mess up the ip addr from environment variables */
char tmp_str[64];
// printf("DebugLY1: /n/r");
//puts(getenv(var));
strcpy(tmp_str, getenv(var) );
if(isxdigit(*tmp_str))
return (string_to_ip( tmp_str ));
else
return (string_to_ip( tmp_str+1 ));
//return (string_to_ip(getenv(var)+1));
/* old code is the below */
// return (string_to_ip(getenv(var)));
}
然 后关于什么配置啊。flash的修改。在上面的文章都讲过了,参考一下。回到make, again. 下载, 跑, OK! 一切尽在掌握。如果你有nand。那么相应的修改和我前面说的一样。这里就不在重复。看看u-boot-1.1.1里关于nand的部分就知道了。但注意 AT91RM9200dk.h少了两个寄存器的定义。自己定义就是了。在at91rm9200dk.c里
//*AT91C_PMC_PCER = 1 << AT91C_ID_PIOB;
//*AT91C_PMC_PCER = 1 << AT91C_ID_PIOC;
给注视掉,不然找不到你的NAND。也就是如果用了at91rm9200dk.c的nand_init初始化,则要执行cmd_nand.c
,你可以打开调试开关来调试就知道了。