这是在用的时候想修改原有环境变量,但是莫名的出了问题,这篇来追查这个问题的原因。

1. 错误的样式

新增(原来不存在的变量)似乎是没有问题,但是修改原有环境变量的值,就变成了全ff

上图中是用al1举例说明的。

修改之后,重启,环境变量就不可用了。

1.1 还有一个新发现:先删除后加入,就不会有问题

修改后重启,环境变量确实是更新了。

2. 源代码保留一份吧,方便以后查找问题

int tgt_setenv(char *name, char *value)
{char *ep;int envlen;char *nvrambuf;char *nvramsecbuf;
#ifdef NVRAM_IN_FLASHchar *nvram;
#endif/* Non permanent vars. */if (strcmp(EXPERT, name) == 0) {return (1);}/* Calculate total env mem size requiered */envlen = strlen(name);   //变量名的长度if (envlen == 0) {return (0);}if (value != NULL) {envlen += strlen(value);  //加上对应值的长度}envlen += 2;       /* '=' + null byte */  //多用两个字节if (envlen > 255) {                  //超出范围return (0);    /* Are you crazy!? */}/* Use first defined flash device (we probably have only one) */
#ifdef NVRAM_IN_FLASHnvram = (char *)(tgt_flashmap())->fl_map_base;    //0xbfc00000/* Deal with an entire sector even if we only use part of it */nvram += NVRAM_OFFS & ~(NVRAM_SECSIZE - 1);   //0xbfcff000
#endif/* If NVRAM is found to be uninitialized, reinit it. */if (nvram_invalid) {  //0 表示已经初始化了printf("2022-03-08 tgt_setenv nvram_invalid\n");nvramsecbuf = (char *)malloc(NVRAM_SECSIZE);if (nvramsecbuf == 0) {printf("Warning! Unable to malloc nvrambuffer!\n");return (-1);}
#ifdef NVRAM_IN_FLASHmemcpy(nvramsecbuf, nvram, NVRAM_SECSIZE);
#endifnvrambuf = nvramsecbuf + (NVRAM_OFFS & (NVRAM_SECSIZE - 1));memset(nvrambuf, -1, NVRAM_SIZE);nvrambuf[2] = '\0';nvrambuf[3] = '\0';cksum((void *)nvrambuf, NVRAM_SIZE, 1);printf("Warning! NVRAM checksum fail. Reset!\n");
#ifdef NVRAM_IN_FLASH#ifdef BOOT_FROM_NANDmemcpy(nvram, nvramsecbuf, NVRAM_SECSIZE);//update_env_to_nand( nvram, nvramsecbuf,NVRAM_SECSIZE);update_rom_to_nand_1block(nvram,(char *)(tgt_flashmap())->fl_map_base);
#elseif (fl_erase_device(nvram, NVRAM_SECSIZE, FALSE)) {printf("Error! Nvram erase failed!\n");free(nvramsecbuf);return (-1);}if (fl_program_device(nvram, nvramsecbuf, NVRAM_SECSIZE, FALSE)) {printf("Error! Nvram init failed!\n");free(nvramsecbuf);return (-1);}
#endif#elsenvram_put(nvramsecbuf);
#endifnvram_invalid = 0;free(nvramsecbuf);}//end if (nvram_invalid)/* Remove any current setting */tgt_unsetenv(name);    //删除原来的/* Find end of evironment strings */nvramsecbuf = (char *)malloc(NVRAM_SECSIZE);   //分配一片空间 500字节if (nvramsecbuf == 0) {printf("Warning! Unable to malloc nvrambuffer!\n");return (-1);}
#ifndef NVRAM_IN_FLASHnvram_get(nvramsecbuf);
#elsememcpy(nvramsecbuf, nvram, NVRAM_SECSIZE); //把数据都回来
#endifnvrambuf = nvramsecbuf + (NVRAM_OFFS & (NVRAM_SECSIZE - 1));//printf("2022-03-08 nvrambuf = %p nvramsecbuf = %p\n",nvrambuf,nvramsecbuf);/* Etheraddr is special case to save space */
#if 1               /*added by tangyt */if (strcmp("activecom", name) == 0) {activecom = strtoul(value, 0, 0);printf("set activecom to com %d\n", activecom);} else if (strcmp("em_enable", name) == 0) {em_enable = strtoul(value, 0, 0);printf("set em_enable to com %d\n", em_enable);} else
#endifif (strcmp("ethaddr", name) == 0) {   //如果名字是"ethaddr"char *s = value;int i;int32_t v;for (i = 0; i < 6; i++) {gethex(&v, s, 2);hwethadr[i] = v;s += 3;   /* Don't get to fancy here :-) */}}else {  //不是"ethaddr"ep = nvrambuf + 2;if (*ep != '\0') {do {while (*ep++ != '\0') ;} while (*ep++ != '\0');ep--;}if (((int)ep + NVRAM_SIZE - (int)ep) < (envlen + 1)) {free(nvramsecbuf);return (0); /* Bummer! */}/**  Special case heaptop must always be first since it*  can change how memory allocation works.*/if (strcmp("heaptop", name) == 0) {bcopy(nvrambuf + 2, nvrambuf + 2 + envlen,ep - nvrambuf + 1);ep = nvrambuf + 2;while (*name != '\0') {*ep++ = *name++;}if (value != NULL) {*ep++ = '=';while ((*ep++ = *value++) != '\0') ;} else {*ep++ = '\0';}} else {while (*name != '\0') {*ep++ = *name++;}if (value != NULL) {*ep++ = '=';while ((*ep++ = *value++) != '\0') ;} else {*ep++ = '\0';}*ep++ = '\0'; /* End of env strings */}}cksum(nvrambuf, NVRAM_SIZE, 1);
#ifdef NVRAM_IN_FLASHbcopy(&activecom, &nvrambuf[ACTIVECOM_OFFS], 1);bcopy(&em_enable, &nvrambuf[MASTER_BRIDGE_OFFS], 1);
#endifbcopy(hwethadr, &nvramsecbuf[ETHER_OFFS], 6);
#ifdef NVRAM_IN_FLASH#ifdef BOOT_FROM_NANDmemcpy(nvram, nvramsecbuf, NVRAM_SECSIZE);//update_env_to_nand( nvram, nvramsecbuf,NVRAM_SECSIZE);update_rom_to_nand_1block(nvram, (char *)(tgt_flashmap())->fl_map_base);
#elseif (fl_erase_device(nvram, NVRAM_SECSIZE, FALSE)) {printf("Error! Nvram erase failed!\n");free(nvramsecbuf);return (0);}if (fl_program_device(nvram, nvramsecbuf, NVRAM_SECSIZE, FALSE)) {printf("Error! Nvram program failed!\n");free(nvramsecbuf);return (0);}
#endif#else  // ifdef NVRAM_IN_FLASH 不执行nvram_put(nvramsecbuf);
#endiffree(nvramsecbuf);return (1);
}

3. 结合上述的现象,修改失败原因不明。所以想修改一下流程:就是要删除的变量,不再从flash中删除(先读出来,再写进去),而是想直接在内存中改,然后再写进入flash。

3.1 在调试的时候,还发现一旦调用了删除环境变量的操作后,再次读取flash的数据就变为了0xff。不知道是设备忙,还是没写进去,还是什么原因。

3.2 修改后的代码(原环境变量读到内存中,直接在内存中修改,再写入flash一次),功能可用了。感觉可能的原因是不能短时间内多次编程/擦擦操作flash

//2022-03-08 added by zhaozhi
//在内存中把某个环境变量删除
//返回1,表示成功,0表示越界,不要写入flash
static int tgt_setenv_inmem(const char* name,const char* value,int envlen,char * nvrambuf)
{char *ep = nvrambuf + 2;char *np,*sp;while ((*ep != '\0') && (ep <= nvrambuf + NVRAM_SIZE)) {np = name;sp = ep;while ((*ep == *np) && (*ep != '=') && (*np != '\0')) {  //找到了相同的名字ep++;np++;}if ((*np == '\0') && ((*ep == '\0') || (*ep == '='))) {while (*ep++) ;while (ep <= nvrambuf + NVRAM_SIZE) {*sp++ = *ep++;   //把后面的数据移过来}if (nvrambuf[2] == '\0') {   //全部删除完了,没得数据了nvrambuf[3] = '\0';    //连续两个0}//  cksum(nvrambuf, NVRAM_SIZE, 1);  //算出校验和,填充      break;} else if (*ep != '\0') {   //不等于0,就表示前面没找到相同的while (*ep++ != '\0') ;}}//把数据加进去{  //不是"ethaddr"ep = nvrambuf + 2;if (*ep != '\0') {    //指针向后移动do {while (*ep++ != '\0') ;} while (*ep++ != '\0');ep--;}if (((int)ep + NVRAM_SIZE - (int)ep) < (envlen + 1)) {  //是否越界//free(nvramsecbuf);   //不再修改flashreturn (0);  /* Bummer! */}/**  Special case heaptop must always be first since it*  can change how memory allocation works.*/if (strcmp("heaptop", name) == 0) {  //如果是heaptopbcopy(nvrambuf + 2, nvrambuf + 2 + envlen,ep - nvrambuf + 1);  //要放在最前面,把数据向后移动ep = nvrambuf + 2;   //填入heaptop 的数据while (*name != '\0') {*ep++ = *name++;}if (value != NULL) {*ep++ = '=';while ((*ep++ = *value++) != '\0') ;} else {*ep++ = '\0';}} else {   //如果不是heaptop,就直接填吧while (*name != '\0') {*ep++ = *name++;}if (value != NULL) {*ep++ = '=';while ((*ep++ = *value++) != '\0') ;} else {*ep++ = '\0';}*ep++ = '\0';   /* End of env strings */}}cksum(nvrambuf, NVRAM_SIZE, 1);    //最后计算校验和return 1;
}//#if 1  //modify by zhaozhi 2022-03-08
int tgt_setenv(char *name, char *value)
{char *ep;int envlen;char *nvrambuf;char *nvramsecbuf;int ret = 0;
#ifdef NVRAM_IN_FLASHchar *nvram;
#endif/* Non permanent vars. */if (strcmp(EXPERT, name) == 0) {return (1);}/* Calculate total env mem size requiered */envlen = strlen(name);   //变量名的长度if (envlen == 0) {return (0);}if (value != NULL) {envlen += strlen(value);  //加上对应值的长度}envlen += 2;       /* '=' + null byte */  //多用两个字节if (envlen > 255) {                  //超出范围return (0);    /* Are you crazy!? */}//printf("2022-03-08 envlen = %d\n",envlen);/* Use first defined flash device (we probably have only one) */
#ifdef NVRAM_IN_FLASHnvram = (char *)(tgt_flashmap())->fl_map_base;    //0xbfc00000/* Deal with an entire sector even if we only use part of it */nvram += NVRAM_OFFS & ~(NVRAM_SECSIZE - 1);   //0xbfcff000
#endif/* If NVRAM is found to be uninitialized, reinit it. */if (nvram_invalid) {  //0 表示已经初始化了printf("2022-03-08 tgt_setenv nvram_invalid\n");nvramsecbuf = (char *)malloc(NVRAM_SECSIZE);if (nvramsecbuf == 0) {printf("Warning! Unable to malloc nvrambuffer!\n");return (-1);}
#ifdef NVRAM_IN_FLASHmemcpy(nvramsecbuf, nvram, NVRAM_SECSIZE);
#endifnvrambuf = nvramsecbuf + (NVRAM_OFFS & (NVRAM_SECSIZE - 1));memset(nvrambuf, -1, NVRAM_SIZE);nvrambuf[2] = '\0';nvrambuf[3] = '\0';cksum((void *)nvrambuf, NVRAM_SIZE, 1);printf("Warning! NVRAM checksum fail. Reset!\n");
#ifdef NVRAM_IN_FLASH#ifdef BOOT_FROM_NANDmemcpy(nvram, nvramsecbuf, NVRAM_SECSIZE);//update_env_to_nand( nvram, nvramsecbuf,NVRAM_SECSIZE);update_rom_to_nand_1block(nvram,(char *)(tgt_flashmap())->fl_map_base);
#elseif (fl_erase_device(nvram, NVRAM_SECSIZE, FALSE)) {printf("Error! Nvram erase failed!\n");free(nvramsecbuf);return (-1);}if (fl_program_device(nvram, nvramsecbuf, NVRAM_SECSIZE, FALSE)) {printf("Error! Nvram init failed!\n");free(nvramsecbuf);return (-1);}
#endif#elsenvram_put(nvramsecbuf);
#endifnvram_invalid = 0;free(nvramsecbuf);}//end if (nvram_invalid)/* Remove any current setting *///tgt_unsetenv(name);    //删除原来的            修改的部分2022-03-08/* Find end of evironment strings */nvramsecbuf = (char *)malloc(NVRAM_SECSIZE);   //分配一片空间 500字节if (nvramsecbuf == 0) {printf("Warning! Unable to malloc nvrambuffer!\n");return (-1);}
#ifndef NVRAM_IN_FLASHnvram_get(nvramsecbuf);
#elsememcpy(nvramsecbuf, nvram, NVRAM_SECSIZE); //把数据都回来
#endifnvrambuf = nvramsecbuf + (NVRAM_OFFS & (NVRAM_SECSIZE - 1));//printf("2022-03-08 nvrambuf = %p nvramsecbuf = %p\n",nvrambuf,nvramsecbuf);/* Etheraddr is special case to save space */
#if 1               /*added by tangyt */if (strcmp("activecom", name) == 0) {activecom = strtoul(value, 0, 0);printf("set activecom to com %d\n", activecom);} else if (strcmp("em_enable", name) == 0) {em_enable = strtoul(value, 0, 0);printf("set em_enable to com %d\n", em_enable);} else
#endifif (strcmp("ethaddr", name) == 0) {   //如果名字是"ethaddr"char *s = value;int i;int32_t v;for (i = 0; i < 6; i++) {gethex(&v, s, 2);hwethadr[i] = v;s += 3;   /* Don't get to fancy here :-) */}}else {  //不是"ethaddr"   //修改的部分!!!!2022-03-08if(0 == tgt_setenv_inmem(name,value,envlen,nvrambuf)){printf("tgt_setenv_inmem return 0\n");return 0;}}//cksum(nvrambuf, NVRAM_SIZE, 1);
#ifdef NVRAM_IN_FLASHbcopy(&activecom, &nvrambuf[ACTIVECOM_OFFS], 1);   //这里不包括checksum? 有问题bcopy(&em_enable, &nvrambuf[MASTER_BRIDGE_OFFS], 1);
#endifbcopy(hwethadr, &nvramsecbuf[ETHER_OFFS], 6);
#ifdef NVRAM_IN_FLASH#ifdef BOOT_FROM_NANDmemcpy(nvram, nvramsecbuf, NVRAM_SECSIZE);//update_env_to_nand( nvram, nvramsecbuf,NVRAM_SECSIZE);update_rom_to_nand_1block(nvram, (char *)(tgt_flashmap())->fl_map_base);
#elseif (fl_erase_device(nvram, NVRAM_SECSIZE, FALSE)) {printf("Error! Nvram erase failed!\n");free(nvramsecbuf);return (0);}if (fl_program_device(nvram, nvramsecbuf, NVRAM_SECSIZE, FALSE)) {printf("Error! Nvram program failed!\n");free(nvramsecbuf);return (0);}
#endif#else  // ifdef NVRAM_IN_FLASH 不执行nvram_put(nvramsecbuf);
#endiffree(nvramsecbuf);return (1);
}

有两个地方修改:

1. 删除了原来调用删除环境变量的操作  tgt_unsetenv(name); 这个函数会操作flash(从flash读数据到内存,在内存中删除数据,擦除flash,再把修改后的数据编程到flash),就没必要了。

2. 调用了我自己写的一个函数  tgt_setenv_inmem(name,value,envlen,nvrambuf),在这个函数中先去从flash读数据到内存,在内存中删除原有的,然后加入新的。再计算一次校验和,擦除flash,再把修改后的数据编程到flash,这样对flash的操作就只有一次读,一次擦除和一次写操作。

目前测试了,对于加入一个新的环境变量,删除一个有的环境变量,修改一个存在的环境变量,都能正常工作了。

龙芯2k1000-pmon(5)- pmon无法修改环境变量的问题相关推荐

  1. 迅为龙芯2K1000开发板PMON开发之配置nand flash之配置pmon

    pmon 支持俩种接口类型的 nand flash,一个是 nand 控制器接口,一个是 spi 接口.龙芯核心板上板载了一个 nand 控制器接口的 flash. 1 配置 pmon 首先我们需要在 ...

  2. 基于龙芯2K1000移植uboot之NAND

    基于龙芯2K1000移植uboot之NAND 移植环境 开始移植 利用原生驱动(不成功) 利用PMON驱动移植(成功) 移植环境 CPU:LS2K1000 NAND:MT29F16G08 编译环境:U ...

  3. 基于龙芯2K1000移植uboot之DDR

    基于龙芯2K1000移植uboot之DDR 移植环境 开始移植 额外说明 移植环境 CPU:LS2K1000 DDR:SCB13H8G162BF-13KI 编译环境:Ubuntu16.04+gcc-4 ...

  4. 龙芯2K1000使用nfs挂载文件系统进行使用

    龙芯2K1000使用nfs挂载文件系统进行使用 在使用龙芯2K1000板子进行开发时,最方便的方式就是通过网络挂载文件系统NFS进行程序开发,这样能大大提高开发效率. 准备: 在龙芯2K上使用nfs挂 ...

  5. 龙芯2K1000开发板资料1.2版更新了

    叮,今日更新已送达. 本次指南更新新增了pmon下操作GPIO章节和pmon下Ejtag使用章节,感兴趣的快来看看吧~ 更新重点 1.新增了9.6 pmon下操作GPIO章节 2.新增了9.7 pmo ...

  6. 4.龙芯2k1000 系统制作及安装

    4.龙芯2k1000 系统制作及安装 文章目录 4.龙芯2k1000 系统制作及安装 (一).制作系统启动U盘 (二).操作系统拷贝 准备材料: 系统内核文件vmlinuz buildroot根文件系 ...

  7. 迅为龙芯2K1000开发板国产处理器操作系统

    1.硬件配置 国产龙芯处理器,双核64位系统,板载2GDDR3内存,流畅运行Busybox.Buildroot.Loognix.QT5.12 系统! 2.接口全 板载4路USB HOST.2路千兆以太 ...

  8. 基于龙芯 2K1000 的嵌入式 Linux 系统移植和驱动程序设计(二)

    第 3 章 嵌入式软件系统移植 本课题中嵌入式系统正常工作的前提是嵌入式软件系统完整且能正常工作, 以便为之后的软件开发提供一个能够正常工作的平台.引导程序 PMON 需要完成 内核引导,嵌入式 Li ...

  9. 基于龙芯2K1000适配WIFI模块(型号:Intel 8265NGW)

    硬件平台:龙芯2K1000 evb开发板 + Intel 8265NGW 开发环境:Ubuntu16.04+gcc-4.9.3-64-gnu 平台环境1:PMON+linux3.10+loongnix ...

  10. 双核64位系统龙芯2K1000开发板高配置,真的绝了

    硬件配置:国产龙芯处理器,双核64位系统,板载2G DDR3内存,流畅运行busybox.buiroot.buiroot.Loognix.QT5.12系统. 接口全:板载4路USB HOST.2路千兆 ...

最新文章

  1. WePy 整合云开发
  2. Linux c编译库路径,【一点一点学Linux C】交叉编译时候如何配置连接库的搜索路径...
  3. [react] 在React中组件和元素有什么区别?
  4. ActiveMQ objecmessage 无法调用问题。
  5. Docker 构建 redis 集群
  6. 数据结构知识点大汇总(二)
  7. CSDN Markdown 文本居中、右对齐、左对齐
  8. c语言kmeans算法具体步骤,k-均值聚类算法c语言版
  9. PHP对象注入 PHP Object Injection
  10. 序列两两比对算法_学会正确选择多序列比对(coding-sequences)软件
  11. (PKCS1)RSA公私钥pem文件解析
  12. Python chain
  13. 计算机重装系统后无法重启,u盘安装系统之后重启电脑没反应怎么办
  14. 共享单车调度_原来你是这样的共享单车调度员:每天抬1万斤,走2万多步
  15. Java 用NIO实现一个聊天室(多人聊天、单人聊天)
  16. ActivityManager: Waited long enough for: ServiceRecord 问题解决
  17. C++实现行列式的相关操作
  18. nginx与react配合二级路由
  19. 题目59 考勤记录(ok)
  20. python开源自动化测试平台_8款开源自动化测试框架

热门文章

  1. 南京大学计算机复试离散数学,南京大学计算机复试线 历年南京大学计算机考研复试离散数学题集.doc...
  2. MATLAB —— 散点图绘制
  3. Magisk升级Zygisk
  4. HTML5网页设计 (一)
  5. html5在线+网站,15个在线HTML5网页设计工具
  6. Java|二叉树基础详解
  7. Java 二叉树层次遍历
  8. 格力空调通讯协议_格力空调485通讯协议格式 485总线上modbus通信协议?
  9. 一起学ORBSLAM2(9)ORBSLAM的PNP解决方案
  10. 云优CMS插件不需要云优CMS授权码的插件