固件升级接口,实现固件的接收、解密、校验和烧录 更多...

Update 的协作图:

class  Emx::UpdateClient
 
class  Emx::UpdateEvent
 
class  Emx::UpdateServerLib
 

详细描述

  update模块提供UpdateServer以及libUpdate.so供客户使用,update模块负责固件的升级,固件升级功能会涉及到uboot环境变量的改写以及分区信息的提取,还有打包方式,Emx提供相应的打包脚本,除了用于工厂烧片使用的flash.bin文件之外,所有的固件包在打包的时候都会进行加密处理。目前update模块支持两种备份分区类型的选择,一个是spare类型,这个类型的分区是使用一个小系统来保证升级过程中断电不会使得设备变砖,上电后可以自行连接服务器进行升级。另一个是doubleSystem类型,也就是双系统。两种类型适用的场合不同,spare类型适用于flash比较小的设备,可以升级正常的应用程序分区,但是升级kernel和rootfs会存在变砖的风险。doubleSystem类型可以安全的升级除boot分区外的所有分区,但是需要比较大的flash空间。update模块目前支持spiNor和spiNand以及emmc类型的flash升级。update模块依赖的配置文件是update.json,内容如下:

{
"mode": "spare",
"flashType": "spiNor",
"dev": "/dev/mtd",
"firstPart": 0,
"rebootAfterComplete": true,
"rebootDelayS": 3,
"updateWay": 0,
"blockSize": 131072,
"indicatorType": 1,
"indicatorConfig": {
"gpio": {
"dir": 1,
"active": true,
"default": false,
"num": 381
}
}
}
Key Type Description
mode string 备份模式spare/doubleSystem
flashType string flash类型spiNor/spiNand/emmc
dev string 设备节点类型
firstPart int 设备节点第一个分区索引号
rebootAfterComplete bool 升级完成后是否自动启设备
rebootDelayS int 重启延迟,单位秒
updateWay int 升级方式: 0 全量下载至内存后再进行烧写; 1 边下载边进行烧写; 2 全量下载到文件后再进行烧写
blockSize int flash擦除块大小
indicatorType int 升级指示类型:1:单Gpio闪烁类型
indicatorConfig obj 针对指示类型的详细配置

  升级模块在接收数据进行升级的过程中会判断固件是否可以被升级,判断的依据是设备内部型号一致,设备内部固件版本号不一致,并且MD5校验通过,型号和版本的定义参考4.2.1.DevInfo

固件升级示例
// 固件升级示例
class DemoUpdate {
public:
void Update() {
// 打开固件文件
FILE *fp = fopen("rom.bin", "rb");
if (!fp) {
printf("open failed\n");
return;
}
UpdateClient update; // 定义升级对象
update.Create(12345678); // 创建升级任务,在此之前可以创建升级进度监听,详细参考UpdateEvent部分
uint8_t buffer[4096];
int n;
while ((n = (int) fread(buffer, 1, sizeof(buffer), fp)) > 0) {
e = update.Push(buffer, n); // 向UpdateServer发送固件
printf("update failed\n");
break;
}
}
update.Destroy();
fclose(fp);
if (n < 0 || (e != Emx::ErrCodeE::Success && e != Emx::ErrCodeE::ReachTheEof)) {
printf("rom send failed\n");
} else {
printf("rom send done\n");
}
}
};
@ Success
成功
@ ReachTheEof
达到文件尾
@ Failure
失败

固件升级状态监听示例
// 固件升级状态监听示例
class DemoUpdateListen {
public:
void Create(EuvLoop &loop, char *buffer, int bufferSize) {
// 注册监听事件
m_event.Create(&loop, buffer, bufferSize, std::bind(&DemoUpdateListen::OnUpdateEvent, this, ph_1));
}
void Destroy() {
// 销毁监听
m_event.Destroy();
}
private:
// 当SD卡状态发生变化的时候触发此回调
void OnUpdateEvent(UpdateEvent::Event &e) {
emxlogi("stat=%d,session=%d,download[%d/%d],burn=[%d/%d]\n",
(int) e.stat, e.session, e.download.current, e.download.total, e.burn.current, e.burn.total);
}
private:
UpdateEvent m_event; // 用于注册监听升级事件
};