dev about fota - XradioTech/xradiotech-wiki GitHub Wiki
中文 | EN
主页 | 产品 | 下载 | 开发指南 | FAQ | 联系我们 | 购买样品
开发指南 > FOTA
目录
FOTA简介
FOTA(Firmware Over The Air,空中固件升级,以下简称OTA)是从服务器上下载软件到本地,由本地完成软件版本的升级。SDK中的OTA方案通过对两个Image区域进行乒乓操作实现对固件的升级,两个Image区域如下图所示
两个Image区域大小相同,均为Image size。Image size应该大于或等于实际固件的大小。此外,Image区域应该与Flash可擦除块对齐。Image区域一的数据与实际固件数据相同,前Boot size大小的区域为Bootloader。Image区域二的前Boot size大小的区域为Boot config。Boot size之后区域的数据与实际固件数据相同(即Image区域二中没有Bootloader,对应位置为Boot config)。因此OTA升级时,Bootloader不变,始终加载Image区域一的Bootloader。Bootloader之后的数据将会在每次OTA升级成功后交替加载两个区域的固件数据。
系统启动时,加载Image区域一的Bootloader,Bootloader根据Boot config的记录,判断后续加载哪个Image区域的固件数据。 OTA升级固件时,系统根据Boot config的记录,判断本次更新哪个Image区域的固件。固件更新成功并校验通过后,更新Boot config,并重启系统。系统重启后会根据更新后的Boot config加载最新的固件数据。如果固件更新或校验失败,则不修改Boot config,系统下次启动仍然加载OTA升级前的固件数据。
-
Boot config
系统启动时,从Boot config获取加载哪个Image区域固件的信息。Boot config中主要存储结构体类型ota_cfg_t的数据,结构体类型ota_cfg_t的两个成员类型分别为ota_image_t和ota_state_t。上述3个类型数据在image.h中定义如下:typedef enum ota_image { OTA_IMAGE_1ST = 1, OTA_IMAGE_2ND = 2, } ota_image_t; typedef enum ota_state { OTA_STATE_UNVERIFIED = 0, OTA_STATE_VERIFIED = 1, } ota_state_t; typedef struct ota_cfg { ota_image_t image; ota_state_t state; } ota_cfg_t;
-
ota_image_t是Image区域的序号,OTA_IMAGE_1ST表示Image区域一,OTA_IMAGE_2ND表示Image区域二
-
ota_state_t是固件校验状态,OTA_STATE_UNVERIFIED表示固件校验失败,OTA_STATE_VERIFIED表示固件校验成功。
-
从Boot config读取到ota_cfg_t类型数据后,其两个成员ota_image_t和ota_state_t的值组合如下:
- OTA_IMAGE_1ST和OTA_STATE_VERIFIED:最新已校验通过的固件位于Image区域一,则系统启动从Image区域一加载固件,OTA升级更新Image区域二的固件。
- OTA_IMAGE_1ST和OTA_STATE_UNVERIFIED:Image区域一的固件未校验通过,则系统启动从Image区域二加载固件,OTA升级更新Image区域一的固件。
- OTA_IMAGE_2ND和OTA_STATE_VERIFIED:最新已校验通过的固件位于Image区域二,则系统启动从Image区域二加载固件,OTA升级更新Image区域一的固件。
- OTA_IMAGE_2ND和OTA_STATE_UNVERIFIED:Image区域二的固件未校验通过,则系统启动从Image区域一加载固件,OTA升级更新Image区域二的固件。
-
OTA protocol
OTA protocol表示OTA升级时下载固件的协议。 当前SDK中支持通过Http和File两种协议下载固件。 其在image.h中定义如下:typedef enum ota_protocol { OTA_PROTOCOL_FILE = 0, OTA_PROTOCOL_HTTP = 1, } ota_protocol_t;
-
OTA verify
OTA verify表示对下载完固件的校验算法。为保证固件在OTA下载和烧写Flash过程中不出错,可采用CRC32、MD5、SHA1或SHA256算法对固件进行校验。typedef enum ota_verify { OTA_VERIFY_NONE = 0, OTA_VERIFY_CRC32 = 1, OTA_VERIFY_MD5 = 2, OTA_VERIFY_SHA1 = 3, OTA_VERIFY_SHA256 = 4, } ota_verify_t;
API说明
下面对OTA模块提供的接口进行简要说明:
-
初始化OTA模块。 输入参数param为初始化参数结构体指针,初始化参数可通过Image模块提供的接口image_get_ota_param()获得。 参数主要包括两个Image区域的位置、大小以及Bootloader区域大小等信息。 执行成功,返回OTA_STATUS_OK; 执行失败,返回OTA_STATUS_ERROR。
ota_status_t ota_init(image_ota_param_t *param);
-
反初始化OTA模块。
void ota_deinit(void);
-
读取Boot config信息,系统启动时和固件升级时根据Boot config信息选择Image区域。 输入参数为config的指针。 执行成功,返回OTA_STATUS_OK; 执行失败,返回OTA_STATUS_ERROR。
ota_status_t ota_read_cfg(ota_cfg_t *cfg);
-
写入Boot config信息,完成对下载固件的校验后更新Boot config信息。 输入参数为config的指针。 执行成功,返回OTA_STATUS_OK; 执行失败,返回OTA_STATUS_ERROR。
ota_status_t ota_write_cfg(ota_cfg_t *cfg);
-
通过指定协议下载固件。 输入参数protocol为所选择的下载固件的协议。 输入参数url为固件统一资源定位符。 下载成功,返回OTA_STATUS_OK; 下载失败,返回OTA_STATUS_ERROR。
ota_status_t ota_get_image(ota_protocol_t protocol, void *url);
-
通过指定算法校验下载的固件,并根据校验结果更新Boot config信息。 即使不采用其他校验算法也应该调用该接口来更新Boot config信息(详情参见示例)。 输入参数verify为指定的校验算法。 输入参数value为正确固件通过指定校验算法得到的校验值。 执行成功(指函数执行成功,不等价于校验通过),返回OTA_STATUS_OK; 执行失败(指函数执行失败,不等价于校验不通过),返回OTA_STATUS_ERROR。
ota_status_t ota_verify_image(ota_verify_t verify, uint32_t *value);
-
重启系统。
void ota_reboot(void);
Usage Example
- 系统启动 下面是系统启动时Bootloader中调用OTA模块接口的例子:
//初始化OTA模块,参数param通过接口image_get_ota_param()获得
ota_init(¶m);
//读Boot config信息
if (ota_read_cfg(&cfg) != OTA_STATUS_OK) {
…… //出错处理
}
//根据Boot config信息选择Image区域
if (((cfg.image == OTA_IMAGE_1ST) && (cfg.state == OTA_STATE_VERIFIED))
|| ((cfg.image == OTA_IMAGE_2ND) && (cfg.state == OTA_STATE_UNVERIFIED))) {
*image_seq = IMAGE_SEQ_1ST; //选择Image区域一
} else if (((cfg.image == OTA_IMAGE_2ND) && (cfg.state == OTA_STATE_VERIFIED))
||((cfg.image == OTA_IMAGE_1ST) && (cfg.state == OTA_STATE_UNVERIFIED))) {
*image_seq = IMAGE_SEQ_2ND; //选择Image区域二
} else {
…… //出错处理
}
- 升级固件 以Http协议下载固件为例,假设固件的url为http://192.168.1.100/OTA/xr_system.img,升级固件的示例如下:
char url[] = "http://192.168.1.100/OTA/xr_system.img";
//通过Http协议下载固件
if (ota_get_image(OTA_PROTOCOL_HTTP, url) != OTA_STATUS_OK) {
…… //出错处理
}
//校验固件,此处选择不进行其他校验算法校验,调用该接口将更新Boot config信息
if (ota_verify_image(OTA_VERIFY_NONE, NULL) != OTA_STATUS_OK) {
…… //出错处理
}
//重启系统
ota_reboot();
- 协议扩展 OTA模块已提供Http和File两种协议下载固件,此外还支持扩展其他协议。扩展协议的方式为:
-
在文件ota.h中将扩展的协议补充到数据类型ota_protocol_t。
typedef enum ota_protocol { OTA_PROTOCOL_FILE = 0, OTA_PROTOCOL_HTTP = 1, OTA_PROTOCOL_XXXX = 2, } ota_protocol_t;
-
实现扩展协议下载固件的两个回调函数,回调函数类型在文件ota_i.h中定义如下。可参考Http协议和File协议对两个回调函数的实现(ota_http.h、ota_http.c、ota_file.h、ota_file.c)。
typedef ota_status_t (*ota_update_init_t)(void *url); typedef ota_status_t (*ota_update_get_t)(uint8_t *buf, uint32_t buf_size, uint32_t *recv_size, uint8_t *eof_flag);
-
将扩展协议的两个回调函数注册到文件ota.c的函数ota_get_image()中。
case OTA_PROTOCOL_FILE: return ota_update_image(url, ota_update_file_init, ota_update_file_get); case OTA_PROTOCOL_HTTP: return ota_update_image(url, ota_update_http_init, ota_update_http_get); case OTA_PROTOCOL_XXXX: return ota_update_image(url, ota_update_xxxx_init, ota_update_xxxx_get);