本内容的验证使用的盈鹏飞嵌入式CoM-335x核心模块及评估板EAC-335X,简要介绍如下:
产品特性
采用TI公司Cortex-A8 AM335X处理器,运行最高速度为1GHZ;
支持128M-512M DDR3 SDRAM;
支持128-1G字节 SLC电子盘或者EMMC 4G-32G大容量电子盘,可启动;
最多可支持两路千兆以太网,支持IEEE1588;
支持两路高速USB OTG;
支持最多六路串口,双路CAN BUS;
支持分辨率最高的1360*768显示接口,可支持SGX530 3D引擎;
板载DS1339的RTC时钟,国内独家设计,保证系统时钟同步;
支持GPMC扩展总线,可扩展FPGA或者 DSP应用;
稳定的操作系统的支持,可预装Ubuntu 16.04或者Preempt Linux 4.14;ANDROID 4.2可根据项目定制;
超小体积,邮票孔设计,160pins, 尺寸为:45*45MM
EAC-335X产品功能图:
1 概述
本手册主要介绍AM335x系列核心模块的衍生产品——包括EVB-335x(Linux 3.2.0)与HMI-T335(Linux 4.14.67)基于UBIFS的使用,旨在解决防止用户文件(数据)丢失问题。
早前,用户文件与根文件系统保存在同一MTD分区,若文件系统发生不可修复的损坏,用户文件也可能随之丢失。分离根文件系统与用户文件,使得二者拥有不同分区,可有效规避此问题。这好比PC有系统分区专用于安装系统,还有其他分区用于存储用户文件(例如:文档、相片、音乐等),当系统发生不可修复的故障时,重新安装系统只会丢失系统分区的文件并不会导致其他分区的文件丢失。
内容梗概:
第2章:介绍nand分区表,这些分区是典型的应用——即用户文件与根文件系统存储在同一分区。
第3章:介绍在u-boot源码中添加新分区,包括两个版本:u-boot 201404与u-boot 2018.01,其中u-boot 201404用于引导Linux 3.2.0、u-boot 2018.01引导Linux 4.14.67。
第4章:介绍在Linux源码中添加新分区。 Linux 3.2.0在mach-xxx文件中添加分区,Linux 4.14.67则在dts中添加,注意两者的区别。
第5章:提出一些注意事项,包括:u-boot与Linux内核分区大小应保持一致;注意区别烧录镜像文件不同;验证新分区是否生效。
第6章:介绍在用户空间如何挂载ubi分区;如何制作UBI镜像以及烧录;如何实现自动挂载ubi分区。
附录1 :简单介绍ubi工具
基于以下条件,贯穿手册中的每一章节,最终实现UBI分区挂载(user spacemount或automaticmount)。其流程参考本章的流程图:
① 主板:EVB-335x,其中Nand flash page size 为2048 byte(mkfs.ubifs工具需要传递正确的page size 参数,否则导致UBI镜像挂在失败),容量512MB;
软件:u-boot 2014.04,Linux 3.2.0;
UBI分区:新添加373MB的userdata分区。
② 主板:HMI-335,其中Nand flash page size 为4096 byte,容量512MB;
软件:u-boot 2018.01,Linux 4.14.67;
UBI分区:添加“ubi_volume”分区,容量100MB;添加“userdata”分区,使用剩余容量。
对于分区,u-boot与内核的容量是固定的。如果您需要添加新分区用于保存用户文件,保留足够的rootfs空间,剩余的则可划分为新分区。
2nand 分区介绍
nand 分区是将某个设备的存储空间切割成段,根据地址规划一定大小空间。在u-boot命令行执行:mtdparts,查看当前分区,如下图所示:
图中的“parts = 9”,表示共有9个分区,各分区的起始地址及大小在列。需要注意的是,rootfs分区使用nand的剩余空间,对于不同容量的nand,rootfs分区的大小不同。在u-boot 2014.04-rc2(引导Linux 3.2.0)分区表中,出厂默认划分如下:
添加userdata后的分区表如下:
在u-boot 2018.01(引导Linux 4.14.67)分区表,由于Linux4.14.67内核的板级代码采用dtb,所以会看到u-boot包括dtb分区,出厂默认划分如下:
添加ubi_volume与userdata后的分区表如下:
说明:
① 分区表中的容量是计算得来的理论值,由于nand坏块原因,实际可使用空间比理论值小。特别是格式化成UBIFS的分区,某些block或page用于存储UBI的属性标记,实际容量比分区小。
② 对于不同容量的nand,rootfs或用户分区大小不同,表中列出3种不同容量的分区示例。
3 U-Boot 修改nand 分区
EVB-335x(内核版本Linux 3.2.0),配套u-boot 2014.04-rc2;HMI-T335(内核版本 Linux 4.14.67),配套u-boot 2018.01。两个版本u-boot修改分区的方式不一样,分别介绍:
3.1 EVB-335x修改nand分区
[if !supportLists]1、 [endif]输入命令:tar -jxvf u-boot-2014.04-rc2-00037-gbaecd31.tar.bz2,将光盘linux\bootloader中
u-boot-2014.04-rc2-00037-gbaecd31.tar.bz2解压到PC机 linux下,如下图所示:
进入u-boot-2014.04-rc2-00037-gbaecd31目录,如下图所示:
2、输入命令:vi include/configs/com335x.h,打开com335x.h文件
3、定位到#define MTDPARTS_DEFAULT宏定义,这个宏定义决定u-boot对nand的分区,如将rootfs
分区改为128M,再在rootfs分区后添加一个userdata分区,则修改如下图所示:
注意:修改分区大小时,不要忘记单位(m), 如128m(rootfs)。另要使用逗号将每个分区分开,最后一个分区后没有逗号。
4、保存退出,编译u-boot,编译过程请参考Linux CoM335X 开发指南。
3.2 HMI-T335修改nand分区
新版本的u-boot在defconfig修改分区。假设,需要在hmi-t335-nand-800x480_defconfig添加ubi_volume与userdata分区,操作如下:
1、使用文档编辑工具(例如vim、gedit等)打开configs/hmi-t335-nand-800x480_defconfig文件;
2、找到配置项“CONFIG_MTDPARTS_DEFAULT”,添加ubi_volume与userdata,分区之间用“,”间隔,如下:
注:
① 分区格式为:容量(分区名),如100m(ubi_volume)表示ubi_volume分区的容量为100m。最后一个分区的容量用“-”,表示分配全部的剩余容量。
② 未添加新分区前,nand的剩余容量都分配给rootfs,添加ubi_volume与userdata分区,同时修改rootfs分区的容量,示例中改为128m。
3、修改nand分区完成后,保存退出,重新编译u-boot,可参考以下操作:
host# make distclean
host# make ARCH=arm hmi-t335-nand-800x480_defconfig
host# make ARCH=arm CROSS_COMPILE=/opt/hmi-t335-linux-sdk/bin/arm-linux-gnueabihf- -j32
4、正常编译结束后,在u-boot源码顶级目录生成MLO、u-boot.img,这两个文件最终要烧录到nand中。
4、Linux内核修改nand分区
EVB-335x使用Linux 3.2.0,HMI-T335使用Linux 4.14.67。Linux 3.2.0无device tree,有关板级的代码在mach-xxx中添加;Linux 4.14.67板级代码在dts中添加。以下分别介绍:
4.1、EVB-335x 修改nand分区
1、输入命令:tar -jxvf linux-3.2-evb335x.tar.bz2,将光盘linux\kernel\ linux-3.2-evb335x.tar.bz2解压到PC机linux系统下,如下图所示
红色框内linux-3.2-evb335x为解压生成的目录。
进入linux-3.2-evb335x目录,如下图所示:
2、输入命令:vi arch/arm/mach-omap2/board-com335x.c,打开板级初始化文件,如下图所示:
3、定位到static struct mtd_partition com335x_nand_partitions[],此结构数组为内核对nand 分区,
如将文件系统分区划分128M,添加分区userdata,userdata分区占用剩余空间,如下图所示:
其中:
name :为分区的名字
offset :为分区开始的偏移地址
MTDPART_OFS_APPEND:表示紧接着上一个分区,MTD Core会自动计算和处理分区地址
Size:为分区的大小,在最后一个分区我们设为MTDPART_SIZ_FULL,表示这个NADN剩下的所有部分。
SZ_128K:代表128k,nand flash以block为单位擦除,而K9F2G08U0B 或K9F4G08U0B每个block大小为128K,所以在内核分区计算中以SZ_128为最小单位。
4、保存退出后,编译内核,编译过程请参考CoM335X Linux 开发指南。
4.2、HMI-T335修改nand分区
说明:HMI-T335的Linux内核集成到buildroot当中,所有修改均在“buildroot-2018.02.12”目录下进行。
以在board/hmi-t335/hmi-t335-nand-800x480.dts中添加“ubi_volume”与“userdata”分区为例,步骤如下:
1、使用文本编辑工具打开,找到“&gpmc”node,修改“partition@10”的容量,在此改为128MB;
2、添加“ubi_volume”分区,容量100MB;添加“userdata”分区,使用剩余容量。
3、保存退出,重新编译内核。
host# make linux-rebuild
注:partition的“label”属性为分区名称;“reg”属性为容量,其格式为<offset size>,reg的size为0表示使用剩余容量。
5 nand分区注意事项
1、u-boot分区应与内核分区大小保持一致;
2、修改分区后,重新编译u-boot与Linux内核,并更新到目标板。通常使用TF卡更新,EVB-335x与HMI-T335的 系统镜像区分如下:
3、更新系统镜像前,先执行擦除操作,以确保清除nand中的旧数据,再更新。擦除整个nand,执行:nand erase.chip如下图:
网络烧写系统可参考CoM335X更新linux系统手册。
4.4、验证分区是否生效,在u-boot命令行执行mtdpats,在shell中执行cat /proc/mtd,如下列图片所示:
从以上两图中看出u-boot与Linux内核修改后的分区,调整后的rootfs为128MB(0x08000000 byte),新增的userdata分区为373MB(0x17580000 byte)。
从以上两图中看出u-boot与Linux内核修改后的分区,调整后的rootfs为128MB(0x08000000 byte),新增的分区ubi_volume为100MB(0x6400000 byte)、userdata为373MB(0x17580000 byte)。
6 MTD设备用户空间操作
创建分区参考前文所述,以下内容将阐述:
1、如何挂载MTD分区;
2、如何将用户文件压制成UBI镜像;
3、应用举例。
应用举例,涉及两个不同版本的Linux kernel以及u-boot,应当注意当前所使用的版本。
6.1 如何挂载MTD分区
MTD设备分区后,还不能直接用作存储空间,需要经过格式化、关联UBI、挂载操作。以userdata分区(/dev/mtd9)挂载到/mnt目录为例,步骤如下:
① 格式化MTD分区,如下图所示:
EVB-335x# ubiformat /dev/mtd9
② 关联UBI设备,如下图所示:
EVB-335x# ubiattach /dev/ubi_ctrl -m 9
注:正常关联设备,打印设备相关信息,如:物理擦除快、逻辑擦除块、容量等。留意console中的信息“UBI: attached mtd9 to ubi1”,创建UBI卷时会用到。
③ 创建一个UBI卷,使用部分容量或全部容量。如下图所示:
使用部分,例如创建10MB的卷、卷标为ubifs_volume
EVB-335x# ubimkvol /dev/ubi1 -N ubifs_volume -s 10MiB
使用全部容量,例如使用全部容量、卷标为userdata
EVB-335x# ubimkvol /dev/ubi1 -N userdata -m
④ 挂载MTD分区,挂载时可指定设备节点或者卷标
设备节点挂载的方式,例如挂载/dev/ubi1_0到/mnt
EVB-335x# mount -t ubifs /dev/ubi1_0 /mnt/
卷标挂载的方式,例如ubi1的卷标为userdata,将其挂载/mnt
EVB-335x# mount -t ubifs ubi1:userdata /mnt/
注:正常挂载,console中输出卷标、容量等信息。亦可通过df指令查看,如下图所示:
6.2 制作UBI镜像
Linux应用程序或数据库等可能时常需要升级,传统的办法是直接拷贝到运行的系统或者重新制作根文件系统再烧录。拷贝的工作量与设备数量成正比,当有很多设备时,显然这不是高效的方法。重新制作根文件系统,再烧录,需要停止运行Linux且烧写时间较长。如果不是生产烧录,不建议直接烧录根文件系统,直接烧录讲求的是一步到位。
针对以上两个问题,将用户文件压制成UBI镜像并烧录在一定程度上解决升级的问题。大致流程为:制作UBI镜像、基于用户空间烧录或u-boot烧录UBI镜像。
6.2.1 制作UBI镜像
假设,以userdata目录为UBI镜像的源,userdata目录下包含一个test.txt文件,步骤如下:
1、host# mkfs.ubifs -F -q -r userdata -m 2048 -e 126976 -c 2987 -o userdata_ubifs.img
2、host# ubinize -o userdata.ubi -m 2048 -p 128KiB -s 512 -O 2048 userdata_ubinize.cfg
userdata_ubinize.cfg内容如下:
host# cat userdata_ubinize.cfg
注:制作容量为373MB、page size为2048 byte的UBI镜像。
1、host# mkfs.ubifs -F -q -r ubi_volume -m 4096 -e 253952 -c 399 -o ubivolume_ubifs.img
2、host# ubinize -o ubi_volume.ubi -m 4096 -p 256KiB -s 1024 -O 4096 ubivolume.cfg
host # cat ubivolume.cfg
注:制作容量为100MB、page size为4096 byte的UBI镜像。
6.2.2 烧录UBI镜像
将UBI镜像烧录指定分区,可在Linux shell中完成,或者在u-boot中单独烧录UBI镜像以及u-boot源码中添加自动烧写的指令。当应用程序升级,而根文件系统与内核不升级时,可选择单独烧录UBI镜像。
1、Linux shell使用指令烧录;
① 烧写UBI镜像,如下图所示:
EVB-335x# ubiformat /dev/mtd9 -f userdata.ubi
② 挂载分区镜像,挂载完成后,查看UBI 镜像的文件,如下图所示:
EVB-335x # ubiattach /dev/ubi_ctrl -m 9
EVB-335x # mount -t ubifs /dev/ubi1_1 /mnt/
UBI镜像中文件的文件内容与制作UBI镜像的源文件一致,镜像烧写成功。
注意:4096 byte page size的nand烧写UBI image时,提示offsets不符的warning,如下图所示。
当选择y,继续格式化。然后关联UBI设备,报错如下图所示:
此时,需要指定sub-page与VID header(volume identifier header),指令如下:
HMI-T335# ubiformat /dev/mtd11 -s 1024 -O 4096 -f ubi_volume.ubi
如果由于VID与指定的不一样,提示“libscan: warning!: inconsistent VID header offset: was 4096, but is 1024 in eraseblock 399”,选择y继续。如下图所示:
关联设备,也需要指定VID header执行:
HMI-335# ubiattach /dev/ubi_ctrl -m 11 -O 4096
2、在u-boot命令行中烧写UBI镜像,首先将镜像文件(userdata.ubi)保存到TF卡根目录,然后通过fatload指令读到RAM的某个地址,再写入Nand Flash的userdata分区。
U-Boot# mw.b 0x82000000 0xFF
U-Boot# mmc rescan
U-Boot# fatload mmc 0 0x82000000 userdata.ubi
U-Boot# nand erase.part userdata
U-Boot# nand write 0x82000000 userdata ${filesize}
3、u-boot自动烧录,其原理与u-boot命令行烧录一样。自动烧录,少了人工干预,烧录工作交由u-boot完成。要想完成自动烧录,需在board/eac/com335x/board.c文件中,添加如下代码:
将UBI镜像(usedata.ubi)保存到TF卡根目录,连同其他系统镜像一并烧录。待系统启动后,执行以下指令挂载UBI分区,同时可以看到分区中文件,如下图所示:
EVB-335x # ubiattach /dev/ubi_ctrl -m 9
EVB-335x # mount -t ubifs ubi1:userdata /mnt
注:步骤3自动烧录的代码,EVB-335x在文件中添加 u-boot-2014.04-rc2-00037-gbaecd31/board/eac/com335x/board.c;HMI-T335在u-boot-2018.01/board/embfly/hmi-t335/board.c文件中添加。
6.3 自动挂载UBI分区
本节介绍基于Linux 3.2.0以及4.14.67版本的内核,分别实现自动挂载UBI分区方法。
6.3.1 Linux 3.2.0 应用举例
假设,要实现UBI device 1、volume 0、userdata卷标的UBI分区挂载到/mnt目录。使用前文中分区,UBI最大的可用容量为373MB。
1、在include/configs/com335x.h文件中#define CONFIG_EXTRA_ENV_SETTINGS 定义处,添加黑体字部分的变量,该变量传递给Linux kernel,但不会自动挂载,这样做可减少UBI设备关联。如下图所示:
注意:Nand Flash的page size为 2048 byte。
2、在内核中打开arch/arm/mach-omap2/board-com335x.c文件,找到 “static struct mtd_partition com335x_nand_partitions[]”函数,添加”user data”分区。注意同时修改rootfs分区的容量。如下:
3、重新编译u-boot、Linux 内核,并烧写到EVB-335x主板。
4、将以下指令写入脚本:
注:按照/etc/init.d/rcS的命名规则(S??),保存到/etc/init.d目录(例如:/etc/init.d/S81mountubi.sh),每次都会自动运行挂载userdata分区。
5、分区正常挂载、容量接近UBI镜像所指定的、且分区内的文件与源一致,则表明UBI镜像挂载成功。如下图所:
6.3.2 Linux 4.14.67 应用举例
512MB、page size为4096 byte的Nand Flash新建2个分区,其中一个为空分区(卷标为userdata),另一个(卷标为ubi_volume)用于烧写UBI镜像。假设userdata挂载到/mnt,ubi_volume挂载到/opt。
1、在include/configs/hmi-t335.h文件的#define CONFIG_EXTRA_ENV_SETTINGS 处添加以下环境变量,该变量传递给Linux kernel,但不会自动挂载,这样做可减少UBI设备关联。
注意:Nand Flash的page size为4096 byte。
2、在configs/hmi-t335-nand-800x480_defconfig文件中添加新分区及指定容量(黑体字部分):
3、在board/hmi-t335/hmi-t335-nand-800x480.dts文件中添加新分区:
注:原rootfs分区的容量改为128MB。
4、重新编译u-boot、Linux内核,并烧录到目标设备。启动日志信息中打印关联(attach)过程,如下图。
将挂载指令写成脚本,并保存到目标板的/etc/init.d/目录,系统每次运行都会执行这些脚本。脚本的内容如下:
HMI-T335# cat /etc/init.d/S82mountubivolume.sh
HMI-T335 # cat /etc/init.d/S81mountuserdata.sh