• 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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147

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

    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
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    说明: 指明打包 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
    
    • 1
    • 2
    • 3
    • 4
  • 相关阅读:
    亚马逊API电商接口测试
    ubuntu生成pem证书连接服务器(已验证)
    位图+布隆过滤器+海量数据问题(它们都是哈希的应用)
    python基础-运算符
    【MySQL进阶】单表访问方法
    工业外观设计成为产品核心竞争优势之一
    2023.10.18
    Kotlin基础入门 - 从Java快速过度Kotlin
    行人重识别项目 | 基于Pytorch实现ReID行人重识别算法
    云小课|MRS基础原理之MapReduce介绍
  • 原文地址:https://blog.csdn.net/weixin_41944449/article/details/133305957