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);
uint8_t buffer[4096];
int n;
auto e = ErrCodeE::Failure;
while ((n = (int) fread(buffer, 1, sizeof(buffer), fp)) > 0) {
e = update.Push(buffer, n);
printf("update failed\n");
break;
}
}
update.Destroy();
fclose(fp);
printf("rom send failed\n");
} else {
printf("rom send done\n");
}
}
};
固件升级状态监听示例
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:
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;
};