本文转自:http://blog.csdn.net/g_salamander/article/details/13772043
1、setenv 命令
该命令用于设置环境变量,用法介绍如下
- # setenv
- setenv - set environment variables
- Usage:
- setenv name value ...
- - set environment variable 'name' to 'value ...'
- setenv name
- - delete environment variable 'name'
2、mmc 命令
该命令用于初始化 SD 存储卡,用法介绍如下
- mmc - MMC sub-system
- Usage:
- mmc init [dev] - init MMC sub system
- mmc device [dev] - show or set current device
3、fatload 命令
该命令用于从 FAT 文件系统设备中读取指定文件放入指定内存中,用法介绍如下:
- usage: fatload <interface> <dev[:part]> <addr> <filename> [bytes]
4、fatinfo 命令
该命令用于查看 FAT 格式设备的基本信息,用法介绍如下:
- usage: fatinfo <interface> <dev[:part]>
- Interface: MMC
- Device 0: Vendor: Rev: Prod:
- Type: Hard Disk
- Capacity: 3789.0 MB = 3.7 GB (7759872 x 512)
- Partition 1: Filesystem: FAT32 "NO NAME "
该命令用于查看 FAT 格式设备的目录和文件信息,用法介绍如下:
- usage: fatls <interface> <dev[:part]> [directory]
- ./
- ../
- 4106240 arm_tools.tar
- 1713 readme_cn.txt
- gen_customer/
- file(s), 3 dir(s)
1、烧录问题:以前经常遇到用串口烧录 xloader、uboot、boot 的时候串口传输出错,就会导致烧录失败并且开不了机,而且在双 uboot 的情况下仍然开不了机。只能用硬件的方式进入强制烧录模式才行。在查看相关源码后发现在烧录的时候不管传输的镜像文件是否完整,都会去做烧录的动作,而且只对传输过去的内容做crc校验,这也造成了crc校验失去了应有的意义。
解决方案:在烧录动作之前加入了镜像完整性检测,如果加载的镜像不完整就不会更新emmc中原有的镜像,这样就解决此问题了。
2、环境变量丢失的问题:有的时候会发现系统里面的一些重要参数(如:电池电量表、充电电流等)丢掉了,这些参数是通过 uboot 环境变量的形式保存在 emmc 中的,如果这些重要参数丢掉了会导致严重的问题,但遇到这种情况的概率比较小,就一直认为是 emmc 的随机问题,还做了环境变量备份的机制。后来通过客户那边的反馈信息才发现一种必现的情况,就是开机的时候一起按住Power 键 +音量加键 ,按照这种情况,系统应该进入烧录模式,也就是会从 SD 卡中读取镜像开始烧录了,如果 SD 卡没有系统镜像则会烧录失败,而测试到的情况表明烧录失败后,重启手机那些环境变量就已经丢掉了。
解决方案:分析代码才发现原来只要进入烧录模式的第一个动作就是擦除原有的环境变量,而不管用户是否有插入 SD 卡或者 SD 卡中是否有镜像,于是将擦除环境变量的动作移动到了 uboot 烧录完成之后,这样就能保证用户误操作开机不会导致环境变量异常丢失了。
3、环境变量备份:为了防止 emmc 或者 nand 异常出错导致环境变量错误,需要对环境变量做一个备份。
解决方案:系统的环境变量(env1)保存在 emmc 偏移为 0x400000 的地址处,长度只有 8192,在设计时为环境变量预留的保存空间为 2M,所以有很大的空间可以用来做备份(env2),现在选定偏移地址为 0x480000 为备份起始地址,长度同样为 8192。在开机的时候,会分别对两处环境变量分别做 crc 检验,然后与其保存的 crc 校验值比较,如果相同则表示环境变量没有错误,如果不同则说明当前环境变量出错,如果出错了则将正确的那处环境变量读到内存中使用,并将出错的那处环境变量重写,如果两处都出错,则应该维修了。为了简化处理流程,在写新的环境变量的时候,同时会写到两处,写的过程则是先完成 env1 的擦除和重写再做 env2 的擦除和重写同时更新 crc 校验值。在 uboot 中把不必要的环境变量都去掉了,这样一般只有在烧录系统的时候才会对环境变量有改写,这样也减少了出错的概率。以下是开机时判断环境变量是否出错的代码:
- void env_relocate_spec (void)
- {
- int crc1_ok = 0, crc2_ok = 0, b_save_env = 0;
- env_t *tmp_env1, *tmp_env2;
- /* 申请两块内存用来保存从 emmc 读取出来的环境变量 */
- tmp_env1 = (env_t *) malloc(CONFIG_ENV_SIZE);
- tmp_env2 = (env_t *) malloc(CONFIG_ENV_SIZE);
- /* 读取环境变量 */
- if (readenv(CONFIG_ENV_OFFSET, (u_char *) tmp_env1))
- printf("No Valid First Environment Area Found\n");
- if (readenv(CONFIG_ENV_BK_OFFSET, (u_char *) tmp_env2))
- printf("No Valid Secondary Environment Area Found\n");
- /* 对环境变量做 crc 校验并与保存值比较 */
- crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc);
- crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc);
- /* 判断环境变量是否出错 */
- if(!crc1_ok && !crc2_ok) {
- free(tmp_env1);
- free(tmp_env2);
- printf("Env crc1 and crc2 is not OK\n");
- return use_default();
- } else if(crc1_ok && !crc2_ok) {
- gd->env_valid = 1;
- b_save_env = 1;
- } else if (!crc1_ok && crc2_ok) {
- gd->env_valid = 2;
- } else {
- /* both ok - check serial */
- if(tmp_env1->crc == 0 && tmp_env2->crc != 0) {
- gd->env_valid = 2;
- } else if(tmp_env2->crc == 0 && tmp_env1->crc != 0){
- gd->env_valid = 1;
- b_save_env = 1;
- } else if(tmp_env2->crc == 0 && tmp_env1->crc == 0) {
- printf("No Vaild Env, return to default Env.\n");
- return use_default();
- } else { /* crc are equal - almost impossible */
- gd->env_valid = 1;
- }
- printf("The Same Environment.\n");
- }
- /* 包含部分异常处理 */
- free(env_ptr);
- if(gd->env_valid == 1) {
- env_ptr = tmp_env1;
- if(b_save_env) run_command("saveenv", 0);
- printf ("Env1 is OK\n\n");
- free(tmp_env2);
- } else {
- env_ptr = tmp_env2;
- printf ("Save env2 to env1 \n\n");
- run_command("saveenv", 0);
- free(tmp_env1);
- }
- gd->env_addr = env_ptr->data;
- if(getenv("second_env") == NULL)
- return;
- setenv("second_env", 0);
- /* 将代码中的环境变量保存到 emmc 中,仅在烧录系统时作用 */
- add_sencond_env();
- }