漫谈LiteOS-Huawei_IoT_Link_SDK_OTA 开发指导
1概述
在应用升级过程中,无线下载更新(OTA)是一种常用,且方便的升级方式。Liteos采用的OTA升级方案基于LwM2M协议,实现了固件升级(FOTA)和软件升级(SOTA)两种升级方案。用户可根据自己的开发环境选择合适的升级方式。 OTA功能代码结构如下图:
2升级文件二进制文件结构
如图所示,升级压缩包中二进制文件如下图所示,FOTA与SOTA采用相同的固件格式。
签名校验值:长度256字节,对剩余文件进行hash计算后,并进行sha256加密后得到的签名密文。
二进制信息:预留长度32字节,升级文件是全量升级文件或增量升级文件等信息。
升级文件内容:经压缩后的升级文件,升级文件使用hdiffpatch算法对新、旧镜像进行运算生成的差分包,并使用lzma算法进行压缩。
3 存储器接口
存储器结构代码位于iot_link/sotrage目录下。存储器结构被划分为两部分,分别定义为存储设备(storage.c)与设备分区(partition.c)。 存储设备定义的是系统中使用的不同类型存储器及接口,如内部flash,spi flash 或 nandflash等,所使用结构体如下:
typedef struct {
int id;
char *name;
uint32_t size;
void (*init)();
int (*read)(void *buf, int32_t len, uint32_t offset);
int (*write)(const uint8_t *buf, int32_t len, uint32_t offset);
int (*erase)(uint32_t offset, int32_t len);
int (*erase_write)(const void *buf, int32_t len, uint32_t offset);
}storage_device;
设备分区定义了用户划分的分区信息,如下所示:
typedef struct _partition {
uint8_t dev_id;
char *name;
uint32_t start_addr;
uint32_t size;
}storage_partition;
设备分区定义了一组外部使用的接口,系统中可以使用这组接口进行相应的读写等操作。
int ota_storage_bin_read(int offset, void *buf, int len);
int ota_storage_bin_write(int offset, void *msg, int len);
int ota_storage_flag_read(ota_flag_t *flag);
int ota_storage_flag_write(ota_flag_t *flag);
4 OTA管理接口
系统中的OTA接口分为三个部分,OTA镜像接口、OTA包管理接口,OTA签名校验接口。
4.1 OTA镜像接口
OTA镜像接口包括了OTA标志镜像和OTA二进制镜像。其中OTA标志存储了升级版本号、升级文件大小、当前OTA状态及OTA升级结果等信息,其结构如下:
#pragma pack(1)
typedef struct
{
uint8_t ver[CN_OTA_VERSION_LEN];
uint32_t ver_code;
uint32_t file_size; ///< the new bin file size
uint32_t blk_size; ///< the new bin block size
uint32_t blk_num; ///< the new bin block num
uint32_t blk_cur;
uint32_t file_off; ///< the current offet to write
uint32_t cur_state; ///< defined by en_ota_status_t
uint32_t ret_upgrade; ///< the upgrade,filled by the loader
uint32_t updater; ///< fota or sota
uint32_t crc; ///< all the ota information computed
}ota_flag_t;
#pragma pack()
在loader和app中维护的同一份OTA标志,APP中会根据下载进度更改cur_state值,在loader中完成升级后会重置cur_state值并填充升级结果到ret_upgrade中,在进入app后将该结果上报至服务器。 外部可调用以下接口进行OTA镜像读写操作:
int storage_partition_read(int part_id, uint8_t *buf, uint32_t len, uint32_t offset);
int storage_partition_write(int part_id, uint8_t *buf, uint32_t len, uint32_t offset);
int storage_partition_erase_write(int part_id, uint8_t *buf, uint32_t len, uint32_t offset);
int storage_partition_erase(int part_id, uint32_t offset, uint32_t len);
4.2 OTA包管理接口
ota_pack实现对接FOTA功能的接口封装。该文件内实现了以下接口:
struct pack_storage_device_api_tag_s {
int (*write_software)(pack_storage_device_api_s *thi, uint32_t offset, const uint8_t *buffer, uint32_t len);
int (*write_software_end)(pack_storage_device_api_s *thi, pack_download_result_e result, uint32_t total_len);
int (*active_software)(pack_storage_device_api_s *thi);
};
4.3 OTA签名校验接口
Ota_checksum实现了升级包签名验证接口。系统中可调用下面接口获取签名校验结果:
int ota_pack_get_signature_verify_result(int sign_len, int file_len);
若用户使用自己的公私钥对,可在此处更改prv_public_key为对应的公钥key值。
5 签名验证
OTA升级包签名验证在下载完成后,发送执行升级命令阶段时执行。
收到执行命令后,系统首先将调用签名校验接口进行二进制文件签名校验,只有在验签通过后,才会执行后续的升级流程,否则会退出升级流程并上报升级失败到服务器。
SOTA在接收到EN_PCP_MSG_EXCUTEUPDATE命令后,位于pcp.c文件中pcp_handle_msg函数。 FOTA流程的签名校验放在了ota_pack_man_software_write_end函数中。
6 Loader
进入Loader后会在ota_detection函数中读取OTA标志,检测当前OTA状态。若为UPDATING状态,则执行升级,否则跳转至APP。
增量升级过程首先会读取升级文件内容并解析出新、旧镜像大小及所使用的压缩插件等信息。
随后调用以下接口:
hpatch_BOOL patch_decompress_with_cache(const hpatch_TStreamOutput* out_newData,
const hpatch_TStreamInput* oldData,const hpatch_TStreamInput* compressedDiff,
hpatch_TDecompress* decompressPlugin,TByte* temp_cache,TByte* temp_cache_end)
执行还原差分镜像。 其中接口参数out_newData、oldData、compressedDiff,需要由用户定义并实现对应的镜像读写接口。
7 FOTA / SOTA
FOTA和SOTA都是基于LwM2M协议实现的升级方案,区别是基于不同的对象。
FOTA使用的是协议中定义的固件对象升级方案,基于对象5实现。
SOTA使用自定义对象19,并使用了PCP协议作为数据传输协议。因此,在使用SOTA时需要将config.mk中的CONFIG_PCP_ENABLE选项使能并使用oc_lwm2m_ota_demo。
8 编译
实现OTA功能需要编译Loader镜像和App镜像。需要对编译选项进行修改:
Loader和App镜像大小定义在链接脚本中,当定义的镜像空间不足以容纳生成的镜像时,需要适当的调整其大小。Loader和app的链接脚本分别是os_loader.ld和os_loader.ld,在其中更改MEMORY中的FLASH大小,即可调节对应镜像空间。
在Makefile文件中,将cfg_seperate_load_mode值改为yes,使编译系统通过链接脚本构建目标文件。
Config.mk中,需要修改以下值:
CONFIG_MQTT_ENABLE := n // config中默认使用的时mqtt,需将其关闭
CONFIG_LWM2M_ENABLE := y // 使能lwm2m
CONFIG_LWM2M_TYPE := "wakaama_raw" //选择使用的lwm2m实现类型
CONFIG_OC_LWM2M_ENABLE := y // 使能lwm2m的oc接口
CONFIG_OC_LWM2M_TYPE := "atiny_lwm2m_raw" CONFIG_OTA_ENABLE := y
CONFIG_PCP_ENABLE := y // 若使用SOTA,需使能该选项
CONFIG_DEMO_TYPE := "oc_lwm2m_ota_demo" // 并使用该DEMO进行SOTA功能验证
编译loader:在GCC目录下的config.mk文件中,将CONFIG_LOADER_ENABLE和CONFIG_OTA_ENABLE的值改为y,进行loader镜像编译。
编译APP:在config.mk文件中,将CONFIG_LOADER_ENABLE值改为n,同时需要使能CONFIG_PCP_ENABLE和CONFIG_OTA_ENABLE选项,进行App镜像编译。
9 新平台适配
若用户需要在新平台上使用OTA升级功能,需要完成以下工作:
完成存储器的定义。
用户需定义所使用的存储器类型接口及分区信息,并使用以下接口将其注册到系统中:
int storage_dev_install(storage_device *dev, uint32_t max_num);
int storage_partition_init(storage_partition *part, int32_t max_num);
完成OTA镜像接口的定义。
用户需定义ota_storage_t中flag镜像与bin镜像的读写接口,并通过下面接口进行注册:
int ota_storage_install(const ota_storage_t *device);
对于FOTA系统,需要同时适配hal_get_ota_opt函数,填充并返回ota_opt_s的read_flash和write_flash接口。
对于loader,需完成ota_detection函数,实现ota状态检查及镜像的升级功能。
在config.mk中定义CONFIG_LOADER_ENABLE值为y,进行Loader镜像的编译。将改值改为n,进行APP镜像的编译。
在Makefile文件中将cfg_seperate_load_mode赋值为yes,以使用对应的链接脚本来构建对应的执行文件。
漫谈LiteOS-Huawei_IoT_Link_SDK_OTA 开发指导的更多相关文章
- 漫谈LiteOS之开发板-串口(基于GD32450i-EVAL)
[摘要] 主要讲解物联网的技术积累,本期我们先带领大家学习漫谈LiteOS之漫谈开发板第一集-串口,本文基于GD32450i-EVAL对串口以及其通信做了一个简要的分析,以及开发过程中遇到的一些技术 ...
- 漫谈LiteOS之开发板-LiteOS移植(基于GD32450i-EVAL)
1 为什么移植? 嵌入式设备的芯片型号和外设的差异较大,资源有限.而RTOS无法适配集成所有的驱动,因此会先适配部分开发板,然后通过移植使得适配更多的开发板. 可移植性是嵌入式操作系统与普通操作系统的 ...
- 漫谈LiteOS之开发板-GPIO(基于GD32450i-EVAL)
[摘要] 本文主要从GPIO的定义.工作模式.特色.工作场合.以及GD32450i-EVAL开发板的引脚.对应的寄存器以及GPIO的流水灯示例对GPIO加以介绍,希望对你有所帮助. 1定义 GPIO( ...
- 乘风破浪,Windows11设计和开发指导,全新图标字体和云母材质
Windows11全新的布局设计 Windows 11全新的布局设计已设计为支持现代应用体验.渐进的圆角.嵌套元素和一致的排水沟相结合,营造出柔和.平静.平易近人的效果,强调目的的统一和易用性. ht ...
- QtQuick桌面应用程序开发指导 3)达到UI而功能_B 4)动态管理Note物_A
3.2 把Page Item和Marker Item绑定 之前我们实现了PagePanel组件, 使用了三个state来切换Page组件的opacity属性; 这一步我们会使用Marker和Marke ...
- QtQuick桌面应用开发指导 1)关于教程 2)原型和设计 3)实现UI和功能_A
Release1.0 http://qt-project.org/wiki/developer-guides Qt Quick Application Developer Guide for Desk ...
- 如何进行Hadoop二次开发指导视频下载
本视频适合对Java有一定了解,熟悉java se的Hadoop爱好者,想对Hadoop进行二次开发.下面是以伪分布为例: 想对Hadoop二次开发:一.首先需要Hadoop和Java之间搭建Ecli ...
- 架构漫谈:自己开发一个Log框架
前言 在日常开发中我们常常都会用到写日志的功能,现在网上的写Log的框架有很多,但是对于我个人而言,过于庞大:我们往往只为了使用框架中的某一个功能就不得不引用整个框架. 所以,我们今天就来自己动手开发 ...
- DHTMLX Tree中文开发指导
专业版1.6下载地址(CSDN) http://download.csdn.net/source/1388340 版本号:dhtmlxTree v.1.6 Professional edition b ...
随机推荐
- Android初级控件
Android初级控件 从今天开始就对Android进行正式的学习,首先先来学习一下初级的控件 1.TextView 文本框,用于显示文字,不可编辑. 常用属性 android:autoLink ...
- 使用Keras进行深度学习:(一)Keras 入门
欢迎大家关注我们的网站和系列教程:http://www.tensorflownews.com/,学习更多的机器学习.深度学习的知识! Keras是Python中以CNTK.Tensorflow或者Th ...
- 使用Keras进行深度学习:(六)LSTM和双向LSTM讲解及实践
欢迎大家关注我们的网站和系列教程:http://www.tensorflownews.com/,学习更多的机器学习.深度学习的知识! 介绍 长短期记忆(Long Short Term Memory, ...
- 一文总结数据科学家常用的Python库(上)
概述 这篇文章中,我们挑选了24个用于数据科学的Python库. 这些库有着不同的数据科学功能,例如数据收集,数据清理,数据探索,建模等,接下来我们会分类介绍. 您觉得我们还应该包含哪些Python库 ...
- arcgis发布服务后显示证书不安全,将https改为http
arcgis server发布服务后显示证书不安全,无法浏览. 要通过https://localhost:port/arcgis/admin作如下修改 update之后地图服务会重启,耐心等待一会儿就 ...
- springboot项目启动-自动创建数据表
很多时候,我们部署一个项目的时候,需要创建大量的数据表.例如mysql,一般的方法就是通过source命令完成数据表的移植,如:source /root/test.sql.如果我们需要一个项目启动后, ...
- NKOJ4241 蚯蚓 (【NOIP2016 DAY2】)
问题描述 输入格式 第一行包含六个整数n,m,q,u,v,t,其中:n,m,q的意义见问题描述: u,v,t均为正整数:你需要自己计算p=u/v(保证0<u<v)t是输出参数,其含义将会在 ...
- C - 啥~ 渣渣也想找玩数字 HDU - 2141(有序序列枚举 + 二分优化查找)
题目描述 可爱的演演又来了,这次他想问渣渣一题... 如果给你三个数列 A[],B[],C[],请问对于给定的数字 X,能否从这三个数列中各选一个,使得A[i]+B[j]+C[k]=X? 输入 多组数 ...
- 从 Socket 编程谈谈 IO 模型(三)
快过年啦,估计很多朋友已在摸鱼的路上.而我为了兄弟们年后的追逐,却在苦苦寻觅.规划,导致文章更新晚了些,各位猿粉谅解. 上期分享,我们结合新春送祝福的场景,通过一坨坨的代码让 BIO.NIO 编程过程 ...
- Redis对象——列表(List)
列表(list)类型是用来存储多个有序的字符串,列表中的每个字符串称为元素(element),一个列表最多可以存储232-1个元素.在Redis中,可以对列表两端插入(push)和弹出(pop),还可 ...