Linux应用之OTA升级

Linux应用之OTA升级

OTA简单理解就是在线升级固件,将固件下载之后,相应的写入对应的分区,只是在这个过程,需要注意分区保护,避免升级过程出现断电导致设备变砖,所以需要做好断电保护。

OTA升级在Linux中,可以使用swupdate进行升级,升级可以分AB系统和recovery系统,下面主要介绍AB系统的升级。

AB系统升级

AB系统的意思就是设备的存储空间存在两份系统,两份系统是一样的,所以AB系统的操作如下:

  1. 先确认当前的分区表中是否有两份系统的分区表并增加downfile,两份系统应该包括内核以及rootfs;
  2. 了解清楚当前系统的是如何判断使用哪份内核和rootfs进行加载的,因为这个到切换AB系统的时候需要使用到;
  3. 完成上述准备之后,可以使用swupdate进行AB系统升级;

swupdate AB系统配置

准备 sw-description

内容如下,中文部分是注释,实际使用去掉。

/* 固定格式,最外层为software = { } */
software =
{
	/* 版本号和描述 */
	version = "0.1.0";
	description = "Firmware update for Linux Project";
    
	/*
	 * 外层tag,stable,
	 * 没有特殊含义,就理解为一个字符串标志即可。
	 * 可以修改,调用的时候传入匹配的字符串即可。
	 */
	stable = {
		/*
		 * 内层tag,now_A_next_B,
		 * 当调用swupdate xxx -e stable,now_A_next_B时,就会匹配到这部分,执行{}内的动作,
		 * 可以修改,调用的时候传入匹配的字符串即可。
		 */

		/* now in systemA, we need to upgrade systemB(bootB, rootfsB) */
		now_A_next_B = {
		/* 这部分是描述,当前处于A系统,需要更新B系统,该执行的动作。执行完后下次启动为B系统 */
		images: ( /* 处理各个image */
			{
				filename = "kernel"; /* 源文件是OTA包中的kernel文件 */
				volume = "bootB"; /* 要写到/dev/by-name/bootB节点中, 这个节点对应bootB分区 */
				installed-directly = true; /* 流式升级,即从网络升级时边下载边写入, 而不是先完整下载到本地再写入,避免占用额外的RAM或ROM */
			},
			{
				filename = "rootfs"; /* 同上,但处理rootfs,不赘述 */
				volume = "rootfsB";
				installed-directly = true;
			},
			{
				filename = "uboot"; /* 源文件是OTA包中的uboot文件 */
				type = "awuboot"; /* type为awuboot,则swupdate会调用对应的handler做处理 */
			},
			{
				filename = "boot0"; /* 源文件是OTA包中的boot0文件 */
				type = "awboot0"; /* type为awuboot,则swupdate会调用对应的handler做处理 */
			}
		);

		/* image处理完之后,需要设置一些标志,切换状态 */
		bootenv: ( /* 处理bootenv,会修改uboot的env分区 */
			{
				/* 设置env:swu_mode=upgrade_kernel, 这是为了记录OTA进度, 对于AB系统来说,此时已经升级完成,置空 */
				name = "swu_mode";
				value = "";
			},
			{
				/* 设置env:boot_partition=bootB, 这是为了切换系统,下次uboot就会启动B系统(kernel位于bootB分区) */
				name = "boot_partition";
				value = "bootB";
			},
			{
				/* 设置env:root_partition=rootfsB, 这是为了切换系统,下次uboot就会通过cmdline指示挂载B系统的rootfs */
				name = "root_partition";
				value = "rootfsB";
			},
			{
				/* 兼容另外的切换方式,可以先不管 */
				name = "systemAB_next";
				value = "B";
			},
			{
				/* 设置env:swu_next=reboot, 这是为了跟外部脚本配合,指示外部脚本做reboot动作 */
				name = "swu_next";
				value = "reboot";
			}
		);
	};

        /*
         * 内层tag,now_B_next_A,
         * 当调用swupdate xxx -e stable,now_B_next_A时,就会匹配到这部分,执行{}内的动作,
         * 可以修改,调用的时候传入匹配的字符串即可
         */
        /* now in systemB, we need to upgrade systemA(bootA, rootfsA) */
        now_B_next_A = {
            /* 这里面就不赘述了, 跟上面基本一致,只是AB互换了 */
            images: (
                {
                    filename = "kernel";
                    volume = "bootA";
                    installed-directly = true;
                },
                {
                    filename = "rootfs";
                    volume = "rootfsA";
                    installed-directly = true;
                },
                {
                    filename = "uboot";
                    type = "awuboot";
                },
                {
                    filename = "boot0";
                    type = "awboot0";
                }
            );
            bootenv: (
                {
                    name = "swu_mode";
                    value = "";
                },
                {
                    name = "boot_partition";
                    value = "bootA";
                },
                {
                    name = "root_partition";
                    value = "rootfsA";
                },
                {
                    name = "systemAB_next";
                    value = "A";
                },
                {
                    name = "swu_next";
                    value = "reboot";
                }
            );
        };
    };

    /* 当没有匹配上面的tag,进入对应的处理流程时,则运行到此处。我们默认清除掉一些状态 */
    /* when not call with -e xxx,xxx just clean */
    bootenv: (
        {
            name = "swu_param";
            value = "";
        },
        {
            name = "swu_software";
            value = "";
        },
        {
            name = "swu_mode";
            value = "";
        },
        {
            name = "swu_version";
            value = "";
        }
    );
}

说明: 升级过程会进行一次重启。具体的:

  1. 升级 kernel 和 rootfs 到另一个系统所在分区,升级 uboot(uboot),boot0(boot0) ,设 置 boot_partition 为切换系统;
  2. 重启,进入新系统。
准备 sw-subimgs.cfg

内容如下,中文部分是注释。

swota_file_list=(
	#取得sw-description-ab, 重命名成sw-description, 放到OTA包中。
	#注意第一行必须为sw-description
	target/allwinner/d1-nezha/swupdate/sw-description-ab:sw-description
	#取得uboot.img,重命名为uboot,放到OTA包中。以下雷同
	#uboot.img和boot0.img是执行swupdate_pack_swu时自动拷贝得到的,需配置sys_config.fex中的storage_type
	out/${TARGET_BOARD}/uboot.img:uboot
	#注:boot0没有修改的话,以下这行可去除,其他雷同,可按需升级
	out/${TARGET_BOARD}/boot0.img:boot0
	out/${TARGET_BOARD}/boot.img:kernel
	out/${TARGET_BOARD}/rootfs.img:rootfs
)

说明: 指明打包 swupdate 升级包所需的各个文件的位置。这些文件会被拷贝到 out 目录下,再生成 swupdate OTA 包。

执行OTA

调用 swupdate,

当前处于A系统:
swupdate -i /mnt/UDISK/tina-d1-nezha-ab.swu -e stable,now_A_next_B
当前处于B系统:
swupdate -i /mnt/UDISK/tina-d1-nezha-ab.swu -e stable,now_B_next_A
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chengwei_peng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值