Chinaunix首页 | 论坛 | 博客
  • 博客访问: 17940
  • 博文数量: 8
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 50
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-08 19:10
文章分类
文章存档

2013年(5)

2012年(3)

我的朋友

分类: 嵌入式

2013-01-25 14:58:48

原文地址:uboot移植问题总结 作者:tianchunlong

 
1,Warning - bad CRC or NAND, using default environmen
 
 

when uboot start,dispaly following info:

U-Boot 1.1.6 (Mar 19 2008 - 14:02:12)

DRAM: 32 MB
NAND: 1024 MiB
*** Warning - bad CRC or NAND, using default environment

so google and find ,the

*** Warning - bad CRC or NAND, using default environment

means nothing wrong ,but need some environment variables for uboot when booting.

you can just ignore this info ,and "The message will go away as soon as you save the envrionment variables using the saveenv command"

digest from :

【后记】

具体解释一下*** Warning - bad CRC or NAND, using default environment的原因和解决办法:

【原因】

Uboot中的逻辑是,汇编执行完之后,掉转到C代码入口处,(此处是arm平台),此处是lib_arm\board.c中的start_armboot,其在一系列的初始化后,会去调用

/* initialize environment */
env_relocate ();

去加载环境变量,在common\env_common.c中的env_relocate():

if (gd->env_valid == 0) {
#if defined(CONFIG_GTH) || defined(CONFIG_ENV_IS_NOWHERE) /* Environment not changable */
   puts ("Using default environment\n\n");
#else
   puts ("*** Warning - bad CRC, using default environment\n\n");
   show_boot_progress (-60);
#endif
   set_default_env();
}
else {
   env_relocate_spec ();
}

会去根据gd->env_valid 前面有没有被初始化,是否为1,而决定,

是直接调用默认环境变量,(我此处的uboot中定义的是#define CONFIG_ENV_IS_IN_NAND
,其在env_nand.c中的env_init()中已经初始化了 gd->env_valid = 1;)

还是去调用env_relocate_spec ()去重新(从你指定的设备,我这里的是之前指定的nand)装载你之前存储的环境变量。

而我这里,按照上面说明,就是去执行env_relocate_spec (),

在common\env_nand.c中

void env_relocate_spec (void)
{
#if !defined(ENV_IS_EMBEDDED)
int ret;

ret = readenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr);
if (ret)
   return use_default();

if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc)
   return use_default();
#endif /* ! ENV_IS_EMBEDDED */
}

static void use_default()
{
puts ("*** Warning - bad CRC or NAND, using default environment\n\n");
set_default_env();
}

可以很清楚的看到,如果是readenv读取环境变量失败,那么就调用use_default,使用默认环境变量。

如果即使数据读的对了,但是crc32校验失败,那么也是去调用use_default,使用默认环境变量。

而这两种情况下,调用use_default,就会打印*** Warning - bad CRC or NAND, using default environment,然后使用你原先在编译Uboot的时候,在自己的头文件里面定义那些默认的值,比如对于常用到的启动参数和启动命令来说,我代码里面的是:

/* read kernel from mtdblock2 no matter for 24/4K pagesize nand */
#define CONFIG_BOOTCOMMAND "nand read 0x40007FC0 0x100000 0x200000;bootm 0x40007FC0"
/* mmcblk0p2 -> rootfs Partition */
#define CONFIG_BOOTARGS "root=/dev/mtdblock2 rw init=/linuxrc console=ttyAMA1,115200 mem=64M rootfstype=yaffs2"
,反之,如果你上面从你指定的nand设备里面读取的环境变量是正常的话,那么就会用那些值,而不是你代码里面写的值。

【解决办法】

知道了具体原因,解决起来就好办了:

1.正常的办法是,如果你确定你已经实现了saveenv,即,

已经在头文件中,定义了对应的值:

以我的此处的用nand存储env举例来说就是类似于这样的:

/* use nand to store env */
#define CONFIG_ENV_IS_IN_NAND
/*
current layout:
0-0x100000, uboot;
0x100000 - 0x800000, kernel;
0x800000 - 0x900000, env;
0x900000 - ~ , rootfs;
*/
#define CONFIG_ENV_OFFSET    0x800000
#define CONFIG_ENV_ADDR    CONFIG_ENV_OFFSET /* duplicate define */
#define CONFIG_ENV_SIZE    0x4000 /* 16KB is large enough */
/* set the block size to the max one: 128KB of 2K, 512KB of 4k pagesze nand */
#define CONFIG_ENV_SECT_SIZE   0x80000
#define CONFIG_SYS_ENV_OVERWRITE 1
#define CONFIG_CMD_SAVEENV             1

并且保证你的读取数据的代码是OK的:

即保证你的nand驱动相关操作函数等功能已经实现了,可以正常读取/写入数据,擦除块了。

那么,saveenv就应该可以正常工作了。

此时,你就可以在第一次启动后(第一次会有此警告),进入uboot(一般是按s键,前提是你代码里面设置了uboot等待一定的时间,运行你进入uboot)后,执行saveenv,就可以把第一次,从代码里面获取的默认的那些env的值,存储到nand里面了。此后,就不会出现这样的提示了,因为可以正常从指定的nand设备中读取和写入对应的env了。

2.如果你想特殊点,不想让别人改你的启动参数等env值,那么你可以去在头文件中,不要定义CONFIG_SYS_ENV_OVERWRITE,然后也不要定义类似于这样的CONFIG_ENV_IS_IN_NAND定义。

然后别人无法修改这些环境变量,同时,也会每次都提示你

*** Warning - bad CRC or NAND, using default environment,此时,你就再直接把那行打印注释掉,就可以了。。。,虽然做法不雅,但是还是可以实现目的的。。。

【总结】

一句话,只要有源码,就没有解决不了的问题。一切问题,参考源码,都能找到根本原因。

此处对于arm+nand来说,具体涉及的文件和函数,总结如下:

1. lib_arm\board.c

void start_armboot (void)
{

。。。

for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
   if ((*init_fnc_ptr)() != 0) { //此处会去调用env_init()
    hang ();
   }
}

。。。

/* initialize environment */
env_relocate ();

。。。

}

2.对于env_init(),此处因为指定的是CONFIG_ENV_IS_IN_NAND,所以对应着:

common\env_nand.c:

int env_init(void)
{

。。。

gd->env_valid = 1;

。。。

}

3.common\env_common.c:

void env_relocate (void)
{

。。。

if (gd->env_valid == 0) {
#if defined(CONFIG_GTH) || defined(CONFIG_ENV_IS_NOWHERE) /* Environment not changable */
   puts ("Using default environment\n\n");
#else
   puts ("*** Warning - bad CRC, using default environment\n\n");
   show_boot_progress (-60);
#endif
   set_default_env();
}
else {
   env_relocate_spec ();
}
。。。

}

4.此处的env_relocate_spec,这里对应的是common\env_nand.c:

void env_relocate_spec (void)
{
#if !defined(ENV_IS_EMBEDDED)
int ret;

ret = readenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr);
if (ret)
   return use_default();

if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc)
   return use_default();
#endif /* ! ENV_IS_EMBEDDED */
}

5.对于数据读取有误或者读出来的数据crc32有误的话,都会调用common\env_nand.c:

static void use_default()
{
puts ("*** Warning - bad CRC or NAND, using default environment\n\n");
set_default_env();
}

因此才会提示有误。OK,总结完毕。有问题,最好自己跟踪代码,最后都是可以搞定的。


阅读(898) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~