历史上的今天
今天是:2025年07月30日(星期三)
2021年07月30日 | 移植uboot-设置默认环境变量,裁剪,并分区
2021-07-30 来源:eefocus
在上一章使uboot支持网卡传输文件后,但是每次启机时,环境变量都要变为默认值,需要重新设置ip,MAC地址才行,由于没有配置mtdparts命令,启动内核也不成功
所以本章主要学习:
1)修改环境变量默认值
2)裁剪uboot
3)分区,设置mtdparts命令
1.修改之前,先来理解下uboot的环境参数
首先,uboot会去校验(CRC)存放环境变量的一段空间 ,若CRC有效则使用该空间里的环境变量,无效则用默认的环境变量.
而我们移植的uboot,由于一直没有使用save,所以没有读不出CRC校验,使用的默认环境变量,如下图所示:

2.来修改uboot的默认环境变量
(PS:uboot此时的内存分区还没修改,所以每次设置环境后,不能用save保存,怕破坏掉nand里面的内容)
2.1搜索using default environment,找到位于set_default_env()函数:

从上面代码可以看到, default_environment这个变量,这是个全局字符数组,从字面上就可知道,这个是默认环境变量数组,里面保存了各个环境值
2.2进入default_environment[]看看

这个数组比较长,所以只剪切一部分,其中MK_STR()的作用就是将数值转换为字符串
这些都是环境参数,比如"bootargs="(环境变量里最重要的一个),里面会保存文件系统位置,控制台console等等
我们以bootargs为例:
在default_environment[]数组里,若CONFIG_BOOTARGS宏有值,便会组成一串字符串"bootargs=... ..."
比如在以前的uboot里,可以看到:
bootargs=noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0
//root:指定文件系统位置
//init:指定内核启动后执行的第一个应用程序
//console:指定使用哪个终端,比如串口0,使用ttySAC0
其它宏也是这样.比如我们熟悉的有:
"bootcmd=", 用来启动内核的命令
"bootdelay=",uboot启动的倒计时,默认值为5S,只有设置了bootcmd,该倒计时才有用
"baudrate=",波特率,默认为115200
"ethaddr=",网卡的MAC地址(也叫物理地址)
"ipaddr=",ip地址
"serverip=",使用tftp时的服务器地址
"netmask=",掩码, 默认值为255.255.255.0
"mtdparts=",mtd分区表
2.3所以接下来,便修改smdk2440.h里面与环境相关的宏
设置默认环境变量宏(位于include/configs/smdk2440.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_BOOTDELAY 10 //uboot 倒计时
#define CONFIG_NETMASK 255.255.255.0 //掩码
#define CONFIG_IPADDR 192.168.2.103 //本机IP
#define CONFIG_SERVERIP 192.168.2.101 //电脑IP
#define CONFIG_ETHADDR 08:00:3e:26:0a:5b //MAC地址
其中bootcmd是随意写的,因为此时的内核位置还不确定放在哪(后面配置mtdparts命令后,会在4.6小节修改)
由于nand中要划分bootload空间、环境变量空间、内核空间、系统空间
而uboot就有400多k,所以我们需要裁剪uboot,裁剪后再来划分内存分区
3.裁剪uboot
uboot很多文件都是基于Makefile,里面通过判断宏来加载文件.而宏大部分都定义在include/configs/smdk2440.h
3.1进入smdk2440.h,把不需要的功能的宏去掉,比如usb,文件系统,rtc等
1)去掉usb支持
/************************************************************
// * USB support (currently only works with D-cache off)
// ************************************************************/
//#define CONFIG_USB_OHCI
//#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)去掉部分不需要的命令行配置
// #define CONFIG_CMD_DHCP //动态主机配置协议命令行
// #define CONFIG_CMD_USB //USB命令行
5)去掉文件系统
/*
// * 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_RBTR
3.2 编译
由于屏蔽的宏在其它文件也会用到,而make在之前用过,再次make只会编译修改过的文件.
所以输入:
make clean
make s3c2440config
make
make后,打印以下错误:
common/libcommon.o: In function `do_date':
/work/system/u-boot-2012.04.01/common/cmd_date.c:60: undefined reference to `rtc_reset'
/work/system/u-boot-2012.04.01/common/cmd_date.c:63: undefined reference to `rtc_get'
/work/system/u-boot-2012.04.01/common/cmd_date.c:72: undefined reference to `rtc_set'
/work/system/u-boot-2012.04.01/common/cmd_date.c:81: undefined reference to `rtc_get'
make: *** [u-boot] 错误 1
上面的cmd_date.c文件以及出错变量rtc_xxx,从字面上来看显然是与RTC有关,我们直接屏蔽该文件
通过Makefile,找到需要屏蔽宏CONFIG_CMD_DATE(宏定义位于include/configs/smdk2440.h):
![]()
屏蔽后,make成功,可以看到uboot只有200kb了:

接下来,便开始分区,使我们的环境变量能保存在uboot指定位置里
4.设置分区
以前,我们每次启动内核时,都会打印以下分区信息:
Creating 4 MTD partitions on "NAND 256MiB 3,3V 8-bit":
0x00000000-0x00040000 : "bootloader" //存放uboot
0x00040000-0x00060000 : "params" //存放环境变量
0x00060000-0x00260000 : "kernel" //存放内核
0x00260000-0x10000000 : "root" //存放文件系统
所以,我们新的uboot,还是照着这个来分区
还记得之前,我们每次设置了环境变量,都不敢用save命令来保存.
4.1所以我们通过sava -help命令,看它位于哪个文件,找到save命令相关宏
如下图所示:

4.2然后在si里搜索saveenv
搜索如下图所示:

可以发现,在env_flash.c 和env_nand.c这两个文件都有saveenv()函数.
显然env_flash.c的作用是,通过save命令将环境变量保存在nor flash.
而env_nand.c,是将环境变量保存在nand flash里.
4.3接下来在common/Makefile搜索,看看这两个文件依赖哪两个宏
如下图所示:
![]()
![]()
4.4然后在smdk2440.h搜索这两个宏,看看板卡默认配置的是不是env_nand.c
如下图所示:

可以看到,smdk2440.h是将环境变量保存在nor flash,由于2440在nand启动下是无法支持nor,所以我们需要屏蔽这三处宏,重新设置宏
4.5设置save相关宏
在其它板卡里搜索CONFIG_ENV_IS_IN_NAND,看看别人是怎么通过宏配置save的,然后在env_nand.c文件里搜索宏,来看宏是怎么用的
最终宏修改为如下所示(位于include/configs/smdk2440.h):
//#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x070000)
//#define CONFIG_ENV_IS_IN_FLASH
//#define CONFIG_ENV_SIZE 0x10000
#define CONFIG_ENV_SIZE 0x20000 //环境变量空间大小
#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_OFFSET 0x40000 //位于0x40000~(0X40000+0x20000)
#define CONFIG_ENV_RANGE CONFIG_ENV_SIZE //环境变量的擦除范围,要>=SIZE
上面的CONFIG_ENV_RANGE宏,其实不定义,内核也会自动定义(位于env_nand.c):

然后重新编译新的uboot,就可以使用save命令保存环境变量了.
接着我们烧写内核:
tftp 30000000 uImage
nand erase 60000 200000
nand write 30000000 60000 200000 //保存在内核分区里
bootm 30000000 //启动内核
从这里,看出烧个内核还需要记录这些分区空间地址,非常麻烦
4.6 设置mtdparts命令(在旧版uboot里,是mtd命令)
其实,我们可以使用mtdparts命令,通过分区名字来代替这些地址,比如以前的uboot,直接输入:
nand erase kernel //这个kernel名字就等于: 60000 200000
nand write 30000000 kernel //这个kernel名字就等于: 60000 200000
由于smdk2440板卡里没有配置mtdparts命令,所以步骤如下所示:
1)搜索mtdparts,发现位于common/cmd_mtdparts.c
2) 在common/Makefile搜索,找到cmd_mtdparts.c文件依赖CONFIG_CMD_MTDPARTS宏

3)在其它板卡里搜索CONFIG_CMD_MTDPARTS,看看别人是怎么通过宏配置nand的,别人写的配置如下所示:

"-":表示剩余空间都是文件系统。
(PS:当执行mtdparts default命令时,uboot就会检测是否有CONFIG_CMD_MTDPARTS宏,然后再根据上面的MTDPARTS_DEFAULT宏保存的mtd分区信息,来将nand和nor分区)
4)设置mtdparts相关宏
接下来,便复制上面的宏到smdk2440.h中,改为:
/*-----------------------------------------------------------------------
* mtdparts
*/
#define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_DEVICE
#define MTDIDS_DEFAULT "nand0=smdk2440-0"
#define MTDPARTS_DEFAULT "mtdparts=smdk2440-0:256k(u-boot),"
"128k(params),"
"2m(kernel),"
"-(rootfs)"
然后重新修改,之前设置的环境参数bootcmd(位于smdk2440.h):
将
#define CONFIG_BOOTCOMMAND "nand read 0x30000000 0x60000 0x200000; bootm 0x30000000" //bootcmd
改为:
#define CONFIG_BOOTCOMMAND "nand read 0x30000000 kernel; bootm 0x30000000" //bootcmd
5)修改好后,我们还需要在board_init_r()函数里的for(;;)前面添加(位于arch/arm/lib/board.c):
run_command("mtdparts default", 0); //添加此处代码
for (;;) {
main_loop();
}
这样uboot每次启动时,都会执行一次mtdparts default命令,使它根据默认参数来自动分区.
mtdparts命令就此设置好了
接下来,便重新烧写uboot,来测试
5.测试mtdparts分区
输入mtdparts,查看默认分区名称:

如上图所示,接下来我们便可以直接使用kernel名字来擦除kernel分区,并烧写内核了
步骤如下:
tftp 30000000 uImage
nand erase.part kernel //等于nand erase 200000 60000
nand write 30000000 kernel //从sdram拷贝到nand
史海拾趣
|
本人想知道 nokia 内置camera的生产厂商,比如 型号为nokia 3220的内置camera型号是什么?生产厂商,以及如何获得这些成熟产品零部件的详细datasheet,除了拆装,还有什么其它方法, 还有一款是索爱的外置camera,MCA_25,我在网上找它的camera型号及资 ...… 查看全部问答> |
|
通过制成的实物验证CPLD 与单片机接口设计完全正确。单片机和 CPLD 具有很强的互补性:在逻辑运算、智能控制方面,单片机具有不可替代的优越性;而在高速稳定等方面,CPLD 无疑是首选。因此,在目前的电子设计中,充分利用单片机+CPLD 结构将起到 ...… 查看全部问答> |
|
如果用单片机上电配置FPGA~~1,我用Quartus II 8.1 (32-Bit)编译生成.POF文件,接下来怎样转换为可用于单片机配置的文件A,用什么工具转换? 2,转换后的文件A是不是直接烧进单片机就可以? 本人初学FPGA,关于单片机怎样配置FPGA文件,在网上找 ...… 查看全部问答> |
|
我想请问。当我点击F1 返回上一个窗口。或者是销毁现在的窗口。去显示别的窗口。这样的代码应该怎么写啊。 if(pMsg->message == WM_KEYDOWN) { &n ...… 查看全部问答> |
|
1.关于驱动分层与过滤驱动的关系。我一直搞不清驱动分层与过滤驱动的分别,我现在自己的理解是:对于过滤驱动来说,它处理完截获的IRP后直接调用IoCallDriver发送给下一层设备,而对于分层驱动来说某一层的驱动完成IRP后使用IoCompleteRequest向IO ...… 查看全部问答> |
|
小弟想学嵌入式,大牛能不能推荐几本书啊?(模拟电子,数电方面) 小弟想学嵌入式,大牛能不能推荐几本书啊? 小弟想学嵌入式,大牛能不能推荐几本书啊? 主要是做ARM方向的,也可能搞SOC 用VERILOG 硬件描述语言 模电,数电基础不是很好,(不是学这个专业的),大牛能不能推荐几本比较好的书啊? 另外还要看什么相 ...… 查看全部问答> |
|
MSP430学习小记~~~~关于在IAR环境下使用MSP的中断。 前段时间一直用CCS,但是机器太差(06 年的笔记本),启动一次CCS的调试需要近2分钟。。。。。:funk: 于是换IAR5.10,速度确实提升不少。。。。。 今天使用IAR新建的工程调试MSP430的IO中断程序。整个中断程序如下: ...… 查看全部问答> |
|
ST微控制器,真的很不错,不仅仅是因为他的产品性能,还有它的后续服务;至今为止,可以说没有任何一家芯片厂商能做到像ST这样将芯片推广得如此深入人心。 完善的程序库,让客户在很短的时间内就能做产品开发; 丰富的应用案例,让不同的客 ...… 查看全部问答> |




