六,移植uboot-设置默认环境变量,完善u-boot

文档时间:2018-08-14

交叉编译器:arm-linux-gcc-4.3.2

Ubuntu版本:16.04

uboot版本:2013.10

1,修改 uboot 默认环境变量

前面章节得到的 uboot 串口打印信息如下:

可以看出,读出的是坏的CRC,使用默认的环境变量,搜索 "using default environment" ,找到位于 common/env_common.c 文件 set_default_env 函数中,定位此处:

从上面的代码可以猜到,默认的环境变量都保存在 default_environment 中,进入到 default_environment :

这里面的内容比较多,我们以其中的 bootargs 为例,搜索 bootargs 字样,可以在其它单板中看到如下语句:

bootargs=noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0

//root 指定文件系统位置

//init 指定内核启动后执行的第一个应用程序

//console 指定使用哪个终端,这里的 ttySAC0 指的就是串口0

其它宏也是这样,比如我们熟悉的有:

"bootcmd=",用来启动内核的命令

"bootdelay=",uboot启动倒计时,默认值为5s,只有设置了bootcmd,它才有用

"baudrate=",波特率,默认为115200

"ipaddr=",IP 地址

"serverip=",服务器IP地址

"netmask=",子网掩码

"gatewayip=",网关

"mtdparts=",mtd分区表

仿照其它单板在 include/configs/jz2440.h中添加相应的宏来设置默认环境变量,代码如下(红色为添加代码):

#define CONFIG_BOOTARGS "noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0" //bootargs
#define CONFIG_BOOTCOMMAND "nand read 0x30000000 0x60000 0x200000; bootm 0x30000000" //bootcmd
#define CONFIG_ETHADDR 00:0c:29:3b:22:2a //MAC地址

/* autoboot */
#define CONFIG_BOOTDELAY 5
#define CONFIG_BOOT_RETRY_TIME -1
#define CONFIG_RESET_TO_RETRY
#define CONFIG_ZERO_BOOTDELAY_CHECK

#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 192.168.2.90
#define CONFIG_SERVERIP 192.168.2.101

2,设置 mtdparts 分区

1),设置环境变量保存位置

在之前的打印信息中虽然会出现,"bad CRC,using default environment",后面我们通过手动设置环境变量,也是可以执行我们想要的操作,但是我们并没有使用过 save 命令将其保存到 flash 中,

这是因为在 flash 中,我们没有对 uboot,params,kernel,rootfs 进行分区,save 命令不能保存到我们想要保存的位置,因此,为了不破坏flash原有的内容,此前未使用 save 命令

所以,首先我们先找到 save 在代码中的位置,在 uboot 上,输入 save -help 命令,打印如下:

搜索关键字 saveenv :

发现很多文件中都有对 saveenv 函数的定义,由于我们只需要把环境变量保存到 flash 中,所以只需要关注与 flash 有关的文件,如上图所示:

common/env_nand.c 文件,和common/env_flash.c 文件,前者是将环境变量保存到 nand 中,后者保存到 nor 中,打开 common 目录下的 Makefile 文件,查看编译这两个文件所依赖的宏:

可以看出,编译 env_flash.c 文件需要 CONFIG_ENV_IS_IN_FLASH 宏,编译 env_nand.c 文件需要 CONFIG_ENV_IS_IN_NAND 宏,在 jz2440.h 文件中查找这两个宏有无定义:

发现只有与nor 相关宏的定义,没有与 NAND 相关宏的定义,而在本例程中,nand 启动不支持 nor flash 操作,所以我们将环境变量保存在 nand flash 中,

参照其它单板对 nand 宏的定义,修改代码:

//#define CONFIG_ENV_ADDR            (CONFIG_SYS_FLASH_BASE + 0x070000)
//#define CONFIG_ENV_IS_IN_FLASH
//#define CONFIG_ENV_SIZE            0x10000

#define CONFIG_ENV_IS_IN_NAND        /* U-Boot env in NAND Flash  */
#define CONFIG_ENV_SIZE            0x20000        //128kb
#define CONFIG_ENV_OFFSET        0x80000    //给uboot预留512kb

其中还有一个 CONFIG_ENV_RANGE 宏,这个宏可以不定义,如果不定义的话,在env_nand.c 中,会把它设置为 CONFIG_ENV_SIZE

重新编译,烧写uboot,就可以使用 save 命令保存环境变量了。

2),设置分区,支持mtdparts命令

如果想要查看 uboot,kernel等的分区,在uboot中输入 mtdparts 打印如下:

发现不支持该命令,修改代码使 uboot 支持 mtdparts 命令,搜索 mtdparts,在 commong/cmd_mtdparts.c 中频繁出现,猜测跟此文件有关,

打开 common 目录下的 Makefile ,发现要想编译 cmd_mtdparts.c 文件,需定义 CONFIG_CMD_MTDPARTS 宏,如下图所示:

搜索 CONFIG_CMD_MTDPARTS ,参照别的单板对这个宏的设置,在 jz2440.h里 设置相关宏使其支持 mtdparts,修改代码如下(红色部分为增加代码):

/* mtdparts command line support */
#define CONFIG_MTD_DEVICE        /* needed for mtdparts commands */
#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT        "nand0=JZ2440-0"
/* default mtd partition table */
#define MTDPARTS_DEFAULT    "mtdparts=JZ2440-0:512k(u-boot),"                             "128k(params),"                             "4m(kernel),"                             "-(rootfs);" \

然后修改之前设置的 bootcmd (位于 jz2440.h 中),红色部分为修改代码:

#define CONFIG_BOOTCOMMAND "nand read 0x30000000 kernel; bootm 0x30000000" //bootcmd  

修改好之后,我们还要修改 board_init_r 函数(位于 arch/arm/lib/board.c 文件中),代码修改如下(红色部分为增加代码):

    run_command("mtdparts default", 0);       //added by zhyy

    /* main_loop() can return to retry autoboot, if so just run it again. */
    for (;;) {
        main_loop();
    }

这样,uboot每次启动时都会执行一次mtdparts default 命令,使它根据默认参数来自动分区,这样 mtdparts 就设置好了

编译,烧写,测试,在uboot中输入 mtd/mtdparts,打印如下:

可以看出,uboot已经支持mtdparts 命令,打印信息与我们设置相符,接下来利用文件名来烧写文件,输入命令:

烧写 uboot 命令:

tftp 30000000 u-boot.bin
nand erase.part u-boot
nand write 30000000 ubootreset        //重启 uboot

烧写内核命令:

tftp 30000000 uImage
nand erase.part kernel
nand write 30000000 kernel
bootm 30000000        //启动内核

烧写jffs2文件系统(目前还不支持yaffs文件系统的烧写):

tftp 30000000 xxx.jffs2        //xxx表示文件系统名称
nand erase.part rootfs
nand write.jffs2 30000000 4a0000 $filesize
reset

3,裁剪 uboot

经过上述步骤编译出来的 uboot 大概有 378kb,这实在是太大了(因为 uboot的功能主要是启动内核,给内核传递参数),所以接下来我们需要对 uboot 进行裁剪,uboot 很多文件都是基于 Makefile 里的宏来进行编译的,而这些宏的定义基本上都在 include/configs/jz2440.h 中,所以我们需要修改 jz2440.h 文件,去掉不需要的宏:

1),去掉USB相关的宏

/************************************************************
 * USB support (currently only works with D-cache off)
 ************************************************************/
//#define CONFIG_USB_OHCI
//#define CONFIG_USB_OHCI_S3C24XX
//#define CONFIG_USB_KEYBOARD
//#define CONFIG_USB_STORAGE
//#define CONFIG_DOS_PARTITION

2),去掉 RTC 支持

/************************************************************
 * RTC
 ************************************************************/
//#define CONFIG_RTC_S3C24X0

3),去掉 BOOTP 选项

/*
 * BOOTP options
 */
//#define CONFIG_BOOTP_BOOTFILESIZE
//#define CONFIG_BOOTP_BOOTPATH
//#define CONFIG_BOOTP_GATEWAY
//#define CONFIG_BOOTP_HOSTNAME

4),去掉部分文件系统的支持

/*
 * File system
 */
//#define CONFIG_CMD_FAT
//#define CONFIG_CMD_EXT2
//#define CONFIG_CMD_UBI
//#define CONFIG_CMD_UBIFS
#define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_DEVICE
#define CONFIG_MTD_PARTITIONS
//#define CONFIG_YAFFS2
//#define CONFIG_RBTREE

编译,打印如下错误:

打开 include/usb.h,定位到169行,屏蔽以下代码:

//#error USB Lowlevel not defined

编译, 打印如下错误:

打开 common 目录下的 Makefile,定位到 cmd_date 关键字,如下:

可以看出编译 cmd_date.c 需要CONFIG_CMD_DATE 的支持,在 jz2440.h 中找到该宏,将其屏蔽:

//#define CONFIG_CMD_DATE

编译,打印如下错误:

打开 common 目录下的 Makefile,定位到 usb 关键字,如下:

可以看出编译 usb.c 需要宏 CONFIG_CMD_USB 的支持,在 jz2440.h 中找到该宏,将其屏蔽:

//#define CONFIG_CMD_USB

编译,成功,看一下uboot的大小,只有221kb,裁剪的差不多了

4,支持 yaffs 文件系统

在我们的uboot中输入 nand write.yaffs 30000000 0 0 打印如下:

可以看出,我们的uboot目前不支持 yaffs 文件系统的烧写,接下来,修改代码,使其支持 yaffs文件系统的烧写。

我们在使用 nand 命令时,会进入到 do_nand 函数(位于 common/cmd_nand.c 文件中),打开 cmd_nand.c 文件,定位到 do_nand 函数,代码如下:

可见,要想支持yaffs,需要添加 宏 CONFIG_CMD_NAND_YAFFS,在 jz2440.h 中添加该宏:

#define CONFIG_CMD_NAND_YAFFS

然后进入 nand_write_skip_bad 函数(位于 drivers/mtd/nand/nand_util.c 文件中):

int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
        size_t *actual, loff_t lim, u_char *buffer, int flags)
{

  ............  

if (!need_skip && !(flags & WITH_DROP_FFS)) {    //需要修改
        rval = nand_write(nand, offset, length, buffer);    //正常拷贝,不考虑OOB问题
        if (rval == 0)
            return 0;        //拷贝完,return

        *length = 0;
        printf("NAND write to offset %llx failed %d\n",
            offset, rval);
        return rval;
    }

    while (left_to_write > 0) {
        size_t block_offset = offset & (nand->erasesize - 1);
        size_t write_size, truncated_write_size;

        WATCHDOG_RESET();

        if (nand_block_isbad(nand, offset & ~(nand->erasesize - 1))) {
            printf("Skip bad block 0x%08llx\n",
                offset & ~(nand->erasesize - 1));
            offset += nand->erasesize - block_offset;
            continue;
        }

        if (left_to_write < (blocksize - block_offset))
            write_size = left_to_write;
        else
            write_size = blocksize - block_offset;

#ifdef CONFIG_CMD_NAND_YAFFS
        if (flags & WITH_YAFFS_OOB) {
            int page, pages;
            size_t pagesize = nand->writesize;
            size_t pagesize_oob = pagesize + nand->oobsize;
            struct mtd_oob_ops ops;

            ops.len = pagesize;
            ops.ooblen = nand->oobsize;
            ops.mode = MTD_OPS_AUTO_OOB;    //需要修改
            ops.ooboffs = 0;

            pages = write_size / pagesize_oob;
            for (page = 0; page < pages; page++) {    //循环烧写每一页
                WATCHDOG_RESET();

                ops.datbuf = p_buffer;
                ops.oobbuf = ops.datbuf + pagesize;

                rval = mtd_write_oob(nand, offset, &ops);    //烧写 OOB
                if (rval != 0)       break;          //烧写失败,退出for循环

    ...............
}

将上面的 if (!need_skip && !(flags & WITH_DROP_FFS)) 改为 if (!need_skip && !(flags & WITH_DROP_FFS) &&!(flags&WITH_YAFFS_OOB))

因为避免输入 nand write.yaffs 直接进入该判断,然后不执行下面的 while (left_to_write > 0)语句

将上面的MTD_OPS_AUTO_OOB 修改为 MTD_OOB_RAW(我也不知道为啥,参考别人的)

(PS:此段参考别人)

编译,烧写,测试,输入以下命令:

tftp 30000000 xxx.yaffs2        //xxx代表文件系统名称
nand erase.part rootfs
nand write.yaffs 30000000 4a0000 $filesize

打印如下信息:

表示下载成功,说明uboot已经支持 yaffs 文件系统了。

到此为止,uboot 的移植已经基本完成了。

5,打补丁

打补丁之前,使用以下命令清除make编译的文件

make distclean
rm u-boot.dis

然后输入以下命令进行打补丁:

cd ..
mv u-boot-2013.10 u-boot-2013.10_zhyy
tar -xjf u-boot-2013.10.tar.bz2            //解压创建源文件
diff -urN u-boot-2013.10 u-boot-2013.10_zhyy > u-boot-2013.10_zhyy.patch            //注意,源文件在前,新文件在后

uboot 移植到此结束。。。

原文地址:https://www.cnblogs.com/zhyy-mango/p/9470845.html

时间: 2024-11-06 03:38:28

六,移植uboot-设置默认环境变量,完善u-boot的相关文章

windows上自动设置java环境变量的脚本

转:http://www.cnblogs.com/flowwind/p/4066146.html 近期打算学习安卓开发,于是乎要准备java开发环境,安装好jdk后,就要设置java环境变量,java环境变量要设置 JAVA_HOME,Path,CLASSPATH三个值,每次配置查百度复制粘贴都很麻烦,所以想着偷懒下,用脚本直接执行就很快了,搜了下bat的命 令,写了个配置java环境变量的脚本. 这里默认设置了java jdk的安装路径为C:\Program Files\Java\jdk1.7

【转】windows上自动设置java环境变量的脚本

转载:http://www.cnblogs.com/flowwind/p/4066146.html 近期打算学习安卓开发,于是乎要准备java开发环境,安装好jdk后,就要 设置java环境变量,java环境变量要设置JAVA_HOME,Path,CLASSPATH三个值,每次配置查百度复制粘贴都很麻烦,所以想着偷懒 下,用脚本直接执行就很快了,搜了下bat的命令,写了个配置java环境变量的脚本. 这里默认设置了java jdk的安装路径为C:\Program Files\Java\jdk1.

centos7下设置opencv环境变量

最近要装YOLO,但是MAKE的时候总是找不到OPENCV的路径, 原因是:我以前卸载过一次OPENCV,然后自己重新安装了opencv2.4.10,  因为当时只在QT 中用,所以编译完也没有设置环境变量,导致现在装YOLO的时候找不到库路径.. 一.安装opencv(这里不再讲述) 从官网去找教程 二.添加库路径(创建opencv.conf文件) 输入命令:vi /etc/ld.so.conf.d/opencv.conf 输入/usr/local/lib,并保存退出 三.添加环境变量 输入命

python 设置linux环境变量

在linux上设置临时环境变量: export PGPASSWORD = 'postgres' 若用python实现,错误的方法: os.system("export PGPASSWORD='postgres'") 正确的方法: os.environ['PGPASSWORD'] = 'postgres' 版权声明:本文为博主原创文章,未经博主允许不得转载.

为什么要设置Java环境变量(windows)

在学习JAVA的过程中,涉及到多个环境变量(environment variable)的概念,如PATH.正确地配置这些环境变量,是能够顺利学习.开发的前提.而经常出现的问题是:有的学习者能够按照提示一步一步地正确配置,但时间一长就忘了,出现了问题也无从下手.究其原因,就是对这些概念没有理解,知其然但不知其所以然.下面的内容,就是帮助大家知其所以然. 一.基本原理 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:临时文件夹位置和系

Linux中如何设置java环境变量

这里介绍Linux下如何设置java环境变量. 工具/原料 Linux java环境变量 方法/步骤 1 查看java的安装路径   查看java执行路径   配置java环境变量   java的安装路径和执行路径   注意这里的JAVA_HOME后面一定要带上bin路径,路径设置完成一定要用 export输出,注意export单词不要写错了   设置环境变量后使用java的v参数测试,还是失败,因为没有执行source命令   环境变量修改后执行source命令,使得配置生效   运行sour

为什么需要设置pythonpath环境变量?

# -*- coding: utf-8 -*- #python 27 #xiaodeng #为什么需要设置pythonpath环境变量? #只需设置pythonpath,从而可以从正在用的目录(也就是正在交互模式下使用的当前目录,或者包含顶层文件的目录)以外的其他目录进行导入

windows下如何设置mysql环境变量

方法一: windows下如何设置mysql环境变量 关键词: mysql, Setting Environment Variables, 环境变量设置 我的电脑->属性->高级->环境变量 选择PATH,在其后面添加: 你的mysql文件夹路径/bin (如:D:\Program Files\MySQL\MySQL Server 5.0\bin ) PATH=.......;D:\Program Files\MySQL\MySQL Server 5.0\bin (注意为追加,不是覆盖)

Linux下设置oracle环境变量

Linux设置Oracle环境变量 方法一:直接运行export命令定义变量,该变量只在当前的shell(BASH)或其子shell(BASH)下是有效的,shell关闭了,变量也就失效了,再打开新shell时就没有这个变量,需要使用的话还需要重新定义. 以设置oracle环境变量为例 export ORACLE_BASE=/data/app/oracle; export ORACLE_HOME=$ORACLE_BASE/product/12.1.0/dbhome_1; export ORACL