歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 【已解決】*** Warning - bad CRC or NAND, using default environment

【已解決】*** Warning - bad CRC or NAND, using default environment

日期:2017/3/1 10:44:40   编辑:Linux編程

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"

【後記】

具體解釋一下*** 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,總結完畢。有問題,最好自己跟蹤代碼,最後都是可以搞定的。

Copyright © Linux教程網 All Rights Reserved