百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

移植u-boot-2016.03到Jz2440之剪裁、修改默认参数、设置分区

csdh11 2025-04-09 15:18 14 浏览

8. u-boot-2016.03移植之剪裁、修改默认参数、设置分区

从前面编译出来的u-boot.bin文件大小490多KB,其实其中有很多我们不用的代码,我们可以通过裁减uboot去掉我们没用的功能,以减少u-boot.bin文件的大小,同时也方便我们烧uboot。

8.1 修改include/configs/jz2440.h文件剪裁uboot

(1) 去掉usb支持,如下图所示:

(2) 去掉RTC支持,如下图所示:

(3) 去掉bootp选项,如下图所示:

(4) 去掉不需要的命令行配置,如下图所示:

(5) 去掉文件系统的支持,如下图所示:

(6) 在uboot顶层目录输入以下命令重新编译:

make distclean
make jz2440_defconfig
make 

(7) 查看u-boot的大小,输入命令:ls u-boot.bin -l,此时的uboot大小有490多KB减少到250多KB,如下图所示:

8.2 设置uboot分区

我们可以从uboot中输入help命令来查找uboot有哪些命令,在这些命令中我们可以找到定义分区相关的命令,如下图所示:

然后,我们可以尝试从uboot中输入mtdparts 命令观察有什么输出,输入命令后,uboot输出的结果如下图所示:

从uboot的顶层目录输入搜索命令:grep -nR "mtdids not defined, no default present",搜索结果如下图所示:

进入cmd/mtdparts.c文件中,发现mtdids not defined, no default presentmtdparts_init函数中,该函数的部分代码如下:

int mtdparts_init(void)
{
        /* get variables */
    ids = getenv("mtdids");    
    parts = getenv("mtdparts");
    current_partition = getenv("partition");

        ... ...

        /* if mtdids varible is empty try to use defaults */
    if (!ids) {
        if (mtdids_default) {
            debug("mtdids variable not defined, using default\n");
            ids = mtdids_default;
            setenv("mtdids", (char *)ids);
        } else {
            printf("mtdids not defined, no default present\n");
            return 1;
        }
    }
        ... ...
}

输入mtdparts命令时,串口输出mtdids variable not defined, using default,显然是ids = 0mtdids_default = 0 执行了 else 分支语句。在该文件中有如下定义:

从上面source insight的代码截图可知,MTDIDS_DEFAULTMTDPARTS_DEFAULT都是黑的,显然是没有定义。那么如定义呢?我们可以参考其他单板的定义。最后我们在include/configs/jz2440.h中修改添加如下代码:

/*
 *mtdparts
 */
#define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_DEVICE
#define MTDIDS_DEFAULT      "nand0=jz2440-0"    /* 表示哪一个设备 */
#define MTDPARTS_DEFAULT    "mtdparts=jz2440-0:256k(u-boot),"   \
                                "128k(params),"     \
                                "2m(kernel),"   \
                                "-(rootfs)"     \

然后让uboot启动时自行设置分区,所以需要在uboot进入mainloop死循环之前执行mtdparts default命令。因此,在runmain_loop函数里添加代码:run_command("mtdparts default",0);,如下图所示:

重新编译uboot,并烧写到开发板的NOR Flash,重启开发板从串口输入mtdparts命令,输出结果如下:

从上图可知,uboot把NAND Flash成功的分成了4个分区。

8.3 修改默认参数

上图显示:CRC的参数错误,使用默认的环境变量。那么我们就从这个问题引入,在uboot中搜索:using default environment,在common/envcommon.c中可找到它是在setdefault_env函数里打印的,该函数的代码如下:

void set_default_env(const char *s)
{
    int flags = 0;

    if (sizeof(default_environment) > ENV_SIZE) {
        puts("*** Error - default environment is too large\n\n");
        return;
    }

    if (s) {
        if (*s == '!') {
            printf("*** Warning - %s, "
                "using default environment\n\n",
                s + 1);
        } else {
            flags = H_INTERACTIVE;
            puts(s);
        }
    } else {
        puts("Using default environment\n\n");
    }

    if (himport_r(&env_htab, (char *)default_environment,
            sizeof(default_environment), '\0', flags, 0,
            0, NULL) == 0)
        error("Environment import failed: errno = %d\n", errno);

    gd->flags |= GD_FLG_ENV_READY;
}

从上面的代码可以找到default_environment,它是一个全局字符数组,保存的是默认环境变量参数,该数组如下:

const uchar default_environment[] = {
#ifdef    CONFIG_ENV_CALLBACK_LIST_DEFAULT
    ENV_CALLBACK_VAR "=" CONFIG_ENV_CALLBACK_LIST_DEFAULT "\0"
#endif
#ifdef    CONFIG_ENV_FLAGS_LIST_DEFAULT
    ENV_FLAGS_VAR "=" CONFIG_ENV_FLAGS_LIST_DEFAULT "\0"
#endif
#ifdef    CONFIG_BOOTARGS
    "bootargs=" CONFIG_BOOTARGS         "\0"
#endif
#ifdef    CONFIG_BOOTCOMMAND
    "bootcmd="  CONFIG_BOOTCOMMAND      "\0"
#endif
#ifdef    CONFIG_RAMBOOTCOMMAND
    "ramboot="  CONFIG_RAMBOOTCOMMAND       "\0"
#endif
#ifdef    CONFIG_NFSBOOTCOMMAND
    "nfsboot="  CONFIG_NFSBOOTCOMMAND       "\0"
#endif
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
    "bootdelay="    __stringify(CONFIG_BOOTDELAY)   "\0"
#endif
#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
    "baudrate=" __stringify(CONFIG_BAUDRATE)    "\0"
#endif
#ifdef    CONFIG_LOADS_ECHO
    "loads_echo="   __stringify(CONFIG_LOADS_ECHO)  "\0"
#endif
#ifdef    CONFIG_ETHPRIME
    "ethprime=" CONFIG_ETHPRIME         "\0"
#endif
#ifdef    CONFIG_IPADDR
    "ipaddr="   __stringify(CONFIG_IPADDR)  "\0"
#endif
#ifdef    CONFIG_SERVERIP
    "serverip=" __stringify(CONFIG_SERVERIP)    "\0"
#endif
#ifdef    CONFIG_SYS_AUTOLOAD
    "autoload=" CONFIG_SYS_AUTOLOAD     "\0"
#endif
#ifdef    CONFIG_PREBOOT
    "preboot="  CONFIG_PREBOOT          "\0"
#endif
#ifdef    CONFIG_ROOTPATH
    "rootpath=" CONFIG_ROOTPATH         "\0"
#endif
#ifdef    CONFIG_GATEWAYIP
    "gatewayip="    __stringify(CONFIG_GATEWAYIP)   "\0"
#endif
#ifdef    CONFIG_NETMASK
    "netmask="  __stringify(CONFIG_NETMASK) "\0"
#endif
#ifdef    CONFIG_HOSTNAME
    "hostname=" __stringify(CONFIG_HOSTNAME)    "\0"
#endif
#ifdef    CONFIG_BOOTFILE
    "bootfile=" CONFIG_BOOTFILE         "\0"
#endif
#ifdef    CONFIG_LOADADDR
    "loadaddr=" __stringify(CONFIG_LOADADDR)    "\0"
#endif
#ifdef    CONFIG_CLOCKS_IN_MHZ
    "clocks_in_mhz=1\0"
#endif
#if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)
    "pcidelay=" __stringify(CONFIG_PCI_BOOTDELAY)"\0"
#endif
#ifdef    CONFIG_ENV_VARS_UBOOT_CONFIG
    "arch="     CONFIG_SYS_ARCH         "\0"
    "cpu="      CONFIG_SYS_CPU          "\0"
    "board="    CONFIG_SYS_BOARD        "\0"
    "board_name="   CONFIG_SYS_BOARD        "\0"
#ifdef CONFIG_SYS_VENDOR
    "vendor="   CONFIG_SYS_VENDOR       "\0"
#endif
#ifdef CONFIG_SYS_SOC
    "soc="      CONFIG_SYS_SOC          "\0"
#endif
#endif
#ifdef    CONFIG_EXTRA_ENV_SETTINGS
    CONFIG_EXTRA_ENV_SETTINGS
#endif
    "\0"
#ifdef DEFAULT_ENV_INSTANCE_EMBEDDED
    }
#endif
};

从上面的代码可知:① bootargs是传给内核的启动参数,可以设置文件系统的相关分区等;② bootcmd是uboot用来启动内核的参数;③ ipaddrserveripgatewayipnetmask分别是开发板的IP地址、服务器IP地址、网关、掩码;④ 忽然发现,上面默认的环境变量里竟然没有设置默认MAC地址的环境变量 ethaddr,那么我们可以ipaddr的设置添加ethaddr环境变量,代码如下:

#ifdef  CONFIG_ETHADDR
        "ethaddr="  __stringify(CONFIG_ETHADDR)     "\0"
#endif

我们只需要修改相关宏就可以修改默认环境变量参数了,总的修改如下:(在include/configs/jz2440.h修改)

#define CONFIG_BOOTARGS  "console=ttySAC0 root=/dev/mtdblock3"
#define CONFIG_BOOTCOMMAND  "nand read 30000000 kernel;bootm 30000000"
#define CONFIG_ETHADDR         00:0c:29:4d:e4:f4  /*定义MAC地址*/
#define CONFIG_NETMASK        255.255.255.0
#define CONFIG_IPADDR        192.168.0.200
#define CONFIG_SERVERIP        192.168.0.100
#define CONFIG_GATEWAYIP    192.168.0.1

重新编译,烧写启动新uboot时就会默认使用上面的环境变量,不需要每次启动都去修改变量了。启动开发板后,串口输入print命令,串口的打印信息如下:

8.4 修改支持保存环境变量

之前我们设置好参数之后,每次都不敢save,就是怕破坏FLASH;在jz2440.h配置文件中,找到如下环境变量的相关定义,如下图所示:

那么我们重新定义这些宏,该怎么定义呢?在uboot命令行使用help命令查看save相关的信息,如下图所示:

然后我们在uboot源码中搜索字符串:grep -nR "saveenv" 找到了类似这样的语句:common/env_nand.c:181:int saveenv(void) 我们去common目录下看看Makefile,看看envnand.c的编译依赖哪个宏?找到了下面这句:obj-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o,说明编译envnand.c依赖的是CONFIGENVISINNAND这个宏的定义。 那么我们就定义这个宏CONFIG_ENV_IS_IN_NAND,所以我们将上面环境变量的宏重新定义如下:

#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_OFFSET       0x00040000
#define CONFIG_ENV_SIZE         0x20000
#define CONFIG_ENV_RANGE        CONFIG_ENV_SIZE

重新编译uboot,烧写到开发板,测试如下:

从上图可知,环境变量参数被保存到NAND Flash的第二个分区了。

相关推荐

探索Java项目中日志系统最佳实践:从入门到精通

探索Java项目中日志系统最佳实践:从入门到精通在现代软件开发中,日志系统如同一位默默无闻却至关重要的管家,它记录了程序运行中的各种事件,为我们排查问题、监控性能和优化系统提供了宝贵的依据。在Java...

用了这么多年的java日志框架,你真的弄懂了吗?

在项目开发过程中,有一个必不可少的环节就是记录日志,相信只要是个程序员都用过,可是咱们自问下,用了这么多年的日志框架,你确定自己真弄懂了日志框架的来龙去脉嘛?下面笔者就详细聊聊java中常用日志框架的...

物理老师教你学Java语言(中篇)(物理专业学编程)

第四章物质的基本结构——类与对象...

一文搞定!Spring Boot3 定时任务操作全攻略

各位互联网大厂的后端开发小伙伴们,在使用SpringBoot3开发项目时,你是否遇到过定时任务实现的难题呢?比如任务调度时间不准确,代码报错却找不到方向,是不是特别头疼?如今,随着互联网业务规模...

你还不懂java的日志系统吗 ?(java的日志类)

一、背景在java的开发中,使用最多也绕不过去的一个话题就是日志,在程序中除了业务代码外,使用最多的就是打印日志。经常听到的这样一句话就是“打个日志调试下”,没错在日常的开发、调试过程中打印日志是常干...

谈谈枚举的新用法--java(java枚举的作用与好处)

问题的由来前段时间改游戏buff功能,干了一件愚蠢的事情,那就是把枚举和运算集合在一起,然后运行一段时间后buff就出现各种问题,我当时懵逼了!事情是这样的,做过游戏的都知道,buff,需要分类型,且...

你还不懂java的日志系统吗(javaw 日志)

一、背景在java的开发中,使用最多也绕不过去的一个话题就是日志,在程序中除了业务代码外,使用最多的就是打印日志。经常听到的这样一句话就是“打个日志调试下”,没错在日常的开发、调试过程中打印日志是常干...

Java 8之后的那些新特性(三):Java System Logger

去年12月份log4j日志框架的一个漏洞,给Java整个行业造成了非常大的影响。这个事情也顺带把log4j这个日志框架推到了争议的最前线。在Java领域,log4j可能相对比较流行。而在log4j之外...

Java开发中的日志管理:让程序“开口说话”

Java开发中的日志管理:让程序“开口说话”日志是程序员的朋友,也是程序的“嘴巴”。它能让程序在运行过程中“开口说话”,告诉我们它的状态、行为以及遇到的问题。在Java开发中,良好的日志管理不仅能帮助...

吊打面试官(十二)--Java语言中ArrayList类一文全掌握

导读...

OS X 效率启动器 Alfred 详解与使用技巧

问:为什么要在Mac上使用效率启动器类应用?答:在非特殊专业用户的环境下,(每天)用户一般可以在系统中进行上百次操作,可以是点击,也可以是拖拽,但这些只是过程,而我们的真正目的是想获得结果,也就是...

Java中 高级的异常处理(java中异常处理的两种方式)

介绍异常处理是软件开发的一个关键方面,尤其是在Java中,这种语言以其稳健性和平台独立性而闻名。正确的异常处理不仅可以防止应用程序崩溃,还有助于调试并向用户提供有意义的反馈。...

【性能调优】全方位教你定位慢SQL,方法介绍下!

1.使用数据库自带工具...

全面了解mysql锁机制(InnoDB)与问题排查

MySQL/InnoDB的加锁,一直是一个常见的话题。例如,数据库如果有高并发请求,如何保证数据完整性?产生死锁问题如何排查并解决?下面是不同锁等级的区别表级锁:开销小,加锁快;不会出现死锁;锁定粒度...

看懂这篇文章,你就懂了数据库死锁产生的场景和解决方法

一、什么是死锁加锁(Locking)是数据库在并发访问时保证数据一致性和完整性的主要机制。任何事务都需要获得相应对象上的锁才能访问数据,读取数据的事务通常只需要获得读锁(共享锁),修改数据的事务需要获...