|
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中的邏輯是,匯編執(zhí)行完之后,掉轉(zhuǎn)到C代碼入口處,(此處是arm平臺(tái)),此處是lib_arm\board.c中的start_armboot,其在一系列的初始化后,會(huì)去調(diào)用
/* initialize environment */ env_relocate ();
去加載環(huán)境變量,在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 (); }
會(huì)去根據(jù)gd->env_valid 前面有沒有被初始化,是否為1,而決定,
是直接調(diào)用默認(rèn)環(huán)境變量,(我此處的uboot中定義的是#define CONFIG_ENV_IS_IN_NAND ,其在env_nand.c中的env_init()中已經(jīng)初始化了 gd->env_valid = 1;)
還是去調(diào)用env_relocate_spec ()去重新(從你指定的設(shè)備,我這里的是之前指定的nand)裝載你之前存儲(chǔ)的環(huán)境變量。
而我這里,按照上面說(shuō)明,就是去執(zhí)行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讀取環(huán)境變量失敗,那么就調(diào)用use_default,使用默認(rèn)環(huán)境變量。
如果即使數(shù)據(jù)讀的對(duì)了,但是crc32校驗(yàn)失敗,那么也是去調(diào)用use_default,使用默認(rèn)環(huán)境變量。
而這兩種情況下,調(diào)用use_default,就會(huì)打印*** Warning - bad CRC or NAND, using default environment,然后使用你原先在編譯Uboot的時(shí)候,在自己的頭文件里面定義那些默認(rèn)的值,比如對(duì)于常用到的啟動(dòng)參數(shù)和啟動(dòng)命令來(lái)說(shuō),我代碼里面的是:
/* 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設(shè)備里面讀取的環(huán)境變量是正常的話,那么就會(huì)用那些值,而不是你代碼里面寫的值。
【解決辦法】
知道了具體原因,解決起來(lái)就好辦了:
1.正常的辦法是,如果你確定你已經(jīng)實(shí)現(xiàn)了saveenv,即,
已經(jīng)在頭文件中,定義了對(duì)應(yīng)的值:
以我的此處的用nand存儲(chǔ)env舉例來(lái)說(shuō)就是類似于這樣的:
/* 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
并且保證你的讀取數(shù)據(jù)的代碼是OK的:
即保證你的nand驅(qū)動(dòng)相關(guān)操作函數(shù)等功能已經(jīng)實(shí)現(xiàn)了,可以正常讀取/寫入數(shù)據(jù),擦除塊了。
那么,saveenv就應(yīng)該可以正常工作了。
此時(shí),你就可以在第一次啟動(dòng)后(第一次會(huì)有此警告),進(jìn)入uboot(一般是按s鍵,前提是你代碼里面設(shè)置了uboot等待一定的時(shí)間,運(yùn)行你進(jìn)入uboot)后,執(zhí)行saveenv,就可以把第一次,從代碼里面獲取的默認(rèn)的那些env的值,存儲(chǔ)到nand里面了。此后,就不會(huì)出現(xiàn)這樣的提示了,因?yàn)榭梢哉闹付ǖ膎and設(shè)備中讀取和寫入對(duì)應(yīng)的env了。
2.如果你想特殊點(diǎn),不想讓別人改你的啟動(dòng)參數(shù)等env值,那么你可以去在頭文件中,不要定義CONFIG_SYS_ENV_OVERWRITE,然后也不要定義類似于這樣的CONFIG_ENV_IS_IN_NAND定義。
然后別人無(wú)法修改這些環(huán)境變量,同時(shí),也會(huì)每次都提示你
*** Warning - bad CRC or NAND, using default environment,此時(shí),你就再直接把那行打印注釋掉,就可以了。。。,雖然做法不雅,但是還是可以實(shí)現(xiàn)目的的。。。
【總結(jié)】
一句話,只要有源碼,就沒有解決不了的問(wèn)題。一切問(wèn)題,參考源碼,都能找到根本原因。
此處對(duì)于arm+nand來(lái)說(shuō),具體涉及的文件和函數(shù),總結(jié)如下:
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) { //此處會(huì)去調(diào)用env_init() hang (); } }
。。。
/* initialize environment */ env_relocate ();
。。。
}
2.對(duì)于env_init(),此處因?yàn)橹付ǖ氖荂ONFIG_ENV_IS_IN_NAND,所以對(duì)應(yīng)著:
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,這里對(duì)應(yīng)的是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.對(duì)于數(shù)據(jù)讀取有誤或者讀出來(lái)的數(shù)據(jù)crc32有誤的話,都會(huì)調(diào)用common\env_nand.c:
static void use_default() { puts ("*** Warning - bad CRC or NAND, using default environment\n\n"); set_default_env(); }
因此才會(huì)提示有誤。OK,總結(jié)完畢。有問(wèn)題,最好自己跟蹤代碼,最后都是可以搞定的。
|