This commit is contained in:
lmx
2025-10-29 13:10:02 +08:00
commit 49a07fa419
2284 changed files with 642060 additions and 0 deletions

View File

@ -0,0 +1,736 @@
#include "includes.h"
#include "../gx_uart_upgrade.h"
#include "../../gx8002_npu_api.h"
#include "../gx_uart_upgrade_porting.h"
//#include "../utils/gx_fifo.h"
#if GX8002_UPGRADE_APP_TOGGLE
typedef struct _gx8002_file_head_t {
u16 head_crc;
u16 data_crc;
u32 addr;
u32 len;
u8 attr;
u8 res;
u16 index;
char name[16];
} gx8002_file_head_t;
struct app_ota_info {
int update_result;
u32 ufw_addr;
u8 cur_seek_file;
u8 update_role;
OS_SEM ota_sem;
OS_SEM rx_sem;
cbuffer_t *cbuf_handle;
update_op_api_t *file_ops;
gx8002_file_head_t file_boot_head;
gx8002_file_head_t file_bin_head;
int packet_buf[UPGRADE_PACKET_SIZE / sizeof(int)];
};
enum GX_APP_UPDATE_ERR {
GX_APP_UPDATE_ERR_NONE = 0,
GX_APP_UPDATE_ERR_NOMEM = -100,
GX_APP_UPDATE_ERR_FILE_READ,
GX_APP_UPDATE_ERR_FILE_DIR_VERIFY,
GX_APP_UPDATE_ERR_FILE_HEAD_VERIFY,
GX_APP_UPDATE_ERR_FILE_DATA_VERIFY,
GX_APP_UPDATE_ERR_UPDATE_LOOP,
GX_APP_UPDATE_ERR_UPDATE_STATE,
};
enum GX8002_UPDATE_ROLE {
GX8002_UPDATE_ROLE_NORMAL = 0,
GX8002_UPDATE_ROLE_TWS_MASTER,
GX8002_UPDATE_ROLE_TWS_SLAVE,
};
static struct app_ota_info *ota_upgrade = NULL;
#define __this ota_upgrade
#define GX8002_UFW_VERIFY_BUF_LEN 512
#define GX8002_UFW_FILE_DATA_VERIFY_ENABLE 0
#define GX8002_OTA_UPGRADE_DEBUG_ENABLE 1
#define ota_upgrade_info printf
#if GX8002_OTA_UPGRADE_DEBUG_ENABLE
#define ota_upgrade_debug printf
#define ota_upgrade_put_buf put_buf
#else
#define ota_upgrade_debug(...)
#define ota_upgrade_put_buf(...)
#endif /* #if GX8002_DEBUG_ENABLE */
//=================================================================//
// tws同步升级接口 //
//=================================================================//
extern void gx8002_uart_app_ota_tws_update_register_handle(void);
extern int gx8002_uart_app_ota_tws_update_init(void *priv);
extern int gx8002_uart_app_ota_tws_update_sync_start(u8 *buf, u16 len);
extern int gx8002_uart_app_ota_tws_update_sync_pend(void);
extern int gx8002_uart_app_ota_tws_update_sync_post(void);
extern int gx8002_uart_app_ota_tws_update_sync_data(u8 *buf, u16 len);
extern int gx8002_uart_app_ota_tws_update_sync_respond(void);
extern int gx8002_uart_app_ota_tws_update_close(void);
extern int gx8002_uart_app_ota_tws_update_sync_result(int result);
extern int gx8002_uart_app_ota_tws_update_sync_result_get(void);
//=================================================================//
// 使用fifo作数据缓存 //
//=================================================================//
////////////// FW Stream Porting //////////////////
static u32 fw_stream_get_file_addr(u32 addr)
{
return __this->ufw_addr + addr;
}
#define STREAM_FIFO_BLOCK_TOTAL 16
#define STREAM_FIFO_TIMEOUT_MS (5000)
static int fw_stream_open(FW_IMAGE_TYPE img_type)
{
if (__this->cbuf_handle == NULL) {
return -1;
}
return 0;
}
static int fw_stream_close(FW_IMAGE_TYPE img_type)
{
return 0;
}
//gx8002线程同步数据
static int fw_stream_read(FW_IMAGE_TYPE img_type, unsigned char *buf, unsigned int len)
{
int ret = 0;
static u32 read_cnt = 0;
if (__this->cbuf_handle) {
if (cbuf_get_data_len(__this->cbuf_handle) < len) {
os_sem_set(&(__this->rx_sem), 0);
os_sem_pend(&(__this->rx_sem), msecs_to_jiffies(STREAM_FIFO_TIMEOUT_MS));
}
ret = cbuf_read(__this->cbuf_handle, buf, len);
if (ret < len) {
ota_upgrade_info("read errm ret = 0x%x, len = 0x%x", ret, len);
return -1;
}
if (__this->update_role == GX8002_UPDATE_ROLE_TWS_MASTER) {
//TODO: tws sync data
gx8002_uart_app_ota_tws_update_sync_data(buf, (u16)len);
if (gx8002_uart_app_ota_tws_update_sync_pend()) {
ota_upgrade_info("read timeout");
ret = -1;
}
} else if (__this->update_role == GX8002_UPDATE_ROLE_TWS_SLAVE) {
//TODO: tws respond
gx8002_uart_app_ota_tws_update_sync_respond();
}
}
return ret;
}
static int fw_stream_get_flash_img_info(flash_img_info_t *info)
{
if (info == NULL) {
return -1;
}
info->img_size = __this->file_bin_head.len;
ota_upgrade_debug("%s, img_size = 0x%x", __func__, info->img_size);
return 0;
}
static int gx8002_ota_data_receive(u8 *data, u32 size)
{
gx8002_file_head_t *file_receive_table[] = {
&(__this->file_boot_head),
&(__this->file_bin_head)
};
u32 file_addr = 0;
u32 remain_len = 0;
u32 rlen = 0;
u16 ret = 0;
for (u32 i = 0; i < ARRAY_SIZE(file_receive_table); i++) {
file_addr = fw_stream_get_file_addr((file_receive_table[i])->addr);
__this->file_ops->f_seek(NULL, SEEK_SET, file_addr);
remain_len = (file_receive_table[i])->len;
ota_upgrade_debug("receive %s data, len = 0x%x", (file_receive_table[i])->name, remain_len);
while (remain_len) {
if (__this->update_result != GX_APP_UPDATE_ERR_NONE) {
return __this->update_result;
}
rlen = (remain_len > size) ? size : remain_len;
ret = __this->file_ops->f_read(NULL, data, rlen);
if ((u16) - 1 == ret) {
ota_upgrade_debug("f_read %s err", (file_receive_table[i])->name);
return GX_APP_UPDATE_ERR_FILE_READ;
}
//TODO: TWS send data sync
while (cbuf_is_write_able(__this->cbuf_handle, rlen) < rlen) {
/* ota_upgrade_debug("aaa"); */
os_time_dly(2);
/* ota_upgrade_debug("bbb"); */
if (__this->update_result != GX_APP_UPDATE_ERR_NONE) {
return __this->update_result;
}
}
if (cbuf_write(__this->cbuf_handle, data, rlen) != rlen) {
ota_upgrade_debug("cbuf full !!!");
}
os_sem_post(&(__this->rx_sem));
remain_len -= rlen;
}
}
return 0;
}
int gx8002_ota_data_passive_receive(u8 *data, u32 size)
{
int ret = 0;
if ((__this == NULL) || (__this->cbuf_handle == NULL)) {
return -1;
}
if (__this->update_role != GX8002_UPDATE_ROLE_TWS_SLAVE) {
return -1;
}
if (cbuf_is_write_able(__this->cbuf_handle, size) < size) {
ota_upgrade_info("passive receive cbuf full !!!");
return -1;
}
ret = cbuf_write(__this->cbuf_handle, data, size);
os_sem_post(&(__this->rx_sem));
return ret;
}
static int __gx8002_ufw_file_data_verify(u32 file_addr, u32 file_len, u16 target_crc, u16(*func_read)(void *fp, u8 *buff, u16 len))
{
u8 *rbuf = malloc(GX8002_UFW_VERIFY_BUF_LEN);
u16 crc_interval = 0;
u16 r_len = 0;
int ret = GX_APP_UPDATE_ERR_NONE;
if (rbuf == NULL) {
return GX_APP_UPDATE_ERR_NOMEM;
}
while (file_len) {
r_len = (file_len > GX8002_UFW_VERIFY_BUF_LEN) ? GX8002_UFW_VERIFY_BUF_LEN : file_len;
if (func_read) {
func_read(NULL, rbuf, r_len);
}
crc_interval = CRC16_with_initval(rbuf, r_len, crc_interval);
file_addr += r_len;
file_len -= r_len;
}
if (crc_interval != target_crc) {
ret = GX_APP_UPDATE_ERR_FILE_DATA_VERIFY;
}
_file_data_verify_end:
if (rbuf) {
free(rbuf);
}
return ret;
}
static int __gx8002_ufw_file_head_verify(gx8002_file_head_t *file_head)
{
int ret = GX_APP_UPDATE_ERR_NONE;
u16 calc_crc = CRC16(&(file_head->data_crc), sizeof(gx8002_file_head_t) - 2);
if (calc_crc != file_head->head_crc) {
ret = GX_APP_UPDATE_ERR_FILE_DATA_VERIFY;
}
return ret;
}
static int gx8002_ufw_file_verify(u32 ufw_addr, update_op_api_t *file_ops)
{
int ret = 0;
u16 r_len = 0;
u8 file_cnt = 0;
gx8002_file_head_t *file_head;
u8 *rbuf = (u8 *)malloc(GX8002_UFW_VERIFY_BUF_LEN);
if (rbuf == NULL) {
ret = GX_APP_UPDATE_ERR_NOMEM;
goto _verify_end;
}
file_ops->f_seek(NULL, SEEK_SET, ufw_addr);
r_len = file_ops->f_read(NULL, rbuf, GX8002_UFW_VERIFY_BUF_LEN);
if ((u16) - 1 == r_len) {
ret = GX_APP_UPDATE_ERR_FILE_READ;
ota_upgrade_debug("f_read err");
goto _verify_end;
}
file_head = (gx8002_file_head_t *)rbuf;
ret = __gx8002_ufw_file_head_verify(file_head);
if (ret != GX_APP_UPDATE_ERR_NONE) {
ota_upgrade_debug("gx8002 ufw file head verify err");
goto _verify_end;
}
if (strcmp(file_head->name, "gx8002")) {
ret = GX_APP_UPDATE_ERR_FILE_HEAD_VERIFY;
ota_upgrade_debug("gx8002 ufw file head name err");
goto _verify_end;
}
ota_upgrade_info("find: %s", file_head->name);
do {
file_head++;
ret = __gx8002_ufw_file_head_verify(file_head);
if (ret != GX_APP_UPDATE_ERR_NONE) {
break;
}
if (strcmp(file_head->name, "gx8002.boot") == 0) {
ota_upgrade_info("find: %s", file_head->name);
memcpy(&(__this->file_boot_head), file_head, sizeof(gx8002_file_head_t));
#if GX8002_UFW_FILE_DATA_VERIFY_ENABLE
file_ops->f_seek(NULL, SEEK_SET, __this->ufw_addr + file_head->addr);
ret = __gx8002_ufw_file_data_verify(__this->ufw_addr + file_head->addr, file_head->len, file_head->data_crc, file_ops->f_read);
if (ret == GX_APP_UPDATE_ERR_NONE) {
file_cnt++;
} else {
ota_upgrade_debug("gx8002.boot file head verify err");
break;
}
#else
file_cnt++;
#endif /* #if GX8002_UFW_FILE_DATA_VERIFY_ENABLE */
}
if (strcmp(file_head->name, "mcu_nor.bin") == 0) {
ota_upgrade_info("find: %s", file_head->name);
memcpy(&(__this->file_bin_head), file_head, sizeof(gx8002_file_head_t));
#if GX8002_UFW_FILE_DATA_VERIFY_ENABLE
file_ops->f_seek(NULL, SEEK_SET, __this->ufw_addr + file_head->addr);
ret = __gx8002_ufw_file_data_verify(__this->ufw_addr + file_head->addr, file_head->len, file_head->data_crc, file_ops->f_read);
if (ret == GX_APP_UPDATE_ERR_NONE) {
file_cnt++;
} else {
ota_upgrade_debug("mcu_nor.bin file head verify err");
break;
}
#else
file_cnt++;
#endif /* #if GX8002_UFW_FILE_DATA_VERIFY_ENABLE */
}
} while (file_head->index == 0);
if ((ret != GX_APP_UPDATE_ERR_NONE) && (file_cnt != 2)) {
ret = GX_APP_UPDATE_ERR_FILE_DATA_VERIFY;
ota_upgrade_debug("file_cnt: %d err", file_cnt);
goto _verify_end;
}
ota_upgrade_info("find file_cnt: %d, verify ok", file_cnt);
_verify_end:
if (rbuf) {
free(rbuf);
}
return ret;
}
///////// status info /////////////
static const char *status_info_str[UPGRADE_STAGE_NONE][UPGRADE_STATUS_NONE] = {
// UPGRADE_STAGE_HANDSHAKE
{"handshake start\n", NULL, "handshake ok\n", "handshake err\n"},
// UPGRADE_STAGE_BOOT_HEADER
{"boot header start\n", NULL, "boot header ok\n", "boot header err\n"},
// UPGRADE_STAGE_BOOT_S1
{"boot stage1 start\n", "boot stage1 downloading\n", "boot stage1 ok\n", "boot stage1 err\n"},
// UPGRADE_STAGE_BOOT_S2
{"boot stage2 start\n", "boot stage2 downloading\n", "boot stage2 ok\n", "boot stage2 err\n"},
// UPGRADE_STAGE_FLASH_IMG
{"flash img start\n", "flash img downloading\n", "flash img ok\n", "flash img err\n"},
};
static void gx8002_upgrade_status_cb(upgrade_stage_e stage, upgrade_status_e status)
{
const char *reply_str = status_info_str[stage][status];
if (reply_str != NULL) {
ota_upgrade_info("status info: %s\n", reply_str);
}
}
static int gx8002_upgrade_task(void *param)
{
int ret = 0;
ota_upgrade_info("---- gx8002 ota start ----");
gx8002_upgrade_cold_reset();
ret = gx_uart_upgrade_proc();
gx8002_normal_cold_reset();
ota_upgrade_info("---- gx8002 ota over ----");
if (ret < 0) {
gx8002_update_end_post_msg(0);
} else {
gx8002_update_end_post_msg(1);
}
return ret;
}
//===================================================================//
/*
@breif: ota流程回调: 初始化函数, 公共流程
@parma: addr: 访问外置芯片固件地址
@parma: file_ops: 访问外置芯片固件文件操作接口
@return: 1) GX_APP_UPDATE_ERR_NONE = 0: 初始化成功
2) < 0: 初始化失败
*/
//===================================================================//
int gx8002_app_ota_start(int (*complete_callback)(void))
{
int ret = GX_APP_UPDATE_ERR_NONE;
ota_upgrade_debug("%s", __func__);
if (__this->cbuf_handle == NULL) {
__this->cbuf_handle = (cbuffer_t *)malloc(sizeof(cbuffer_t) + (UPGRADE_PACKET_SIZE * STREAM_FIFO_BLOCK_TOTAL));
if (__this->cbuf_handle == NULL) {
ret = GX_APP_UPDATE_ERR_NOMEM;
return ret;
}
cbuf_init(__this->cbuf_handle, __this->cbuf_handle + 1, (UPGRADE_PACKET_SIZE * STREAM_FIFO_BLOCK_TOTAL));
}
os_sem_create(&(__this->rx_sem), 0);
os_taskq_post_msg("gx8002", 2, GX8002_MSG_UPDATE, GX8002_UPDATE_TYPE_APP);
if (complete_callback) {
if (complete_callback()) {
return GX_APP_UPDATE_ERR_UPDATE_LOOP;
}
}
return ret;
}
//===================================================================//
/*
@breif: ota流程回调: 释放资源
@parma: void
@return: 1) GX_APP_UPDATE_ERR_NONE = 0: 初始化成功
2) < 0: 初始化失败
*/
//===================================================================//
static int gx8002_app_ota_close(void)
{
if (__this->update_role == GX8002_UPDATE_ROLE_TWS_SLAVE) {
//从机出口
gx8002_uart_app_ota_tws_update_sync_result(__this->update_result);
if (__this->cbuf_handle) {
free(__this->cbuf_handle);
__this->cbuf_handle = NULL;
}
if (__this) {
free(__this);
__this = NULL;
}
gx8002_uart_app_ota_tws_update_close();
} else {
os_sem_post(&(__this->ota_sem));
}
return 0;
}
//===================================================================//
/*
@breif: 从机升级开始
@parma: void
@return: 1) GX_APP_UPDATE_ERR_NONE = 0: 初始化成功
2) < 0: 初始化失败
*/
//===================================================================//
int gx8002_app_ota_passive_start(int (*complete_callback)(void), u8 *ota_data, u16 len)
{
int ret = GX_APP_UPDATE_ERR_NONE;
ota_upgrade_debug("%s", __func__);
if (__this) {
return GX_APP_UPDATE_ERR_UPDATE_STATE;
}
__this = zalloc(sizeof(struct app_ota_info));
if (__this == NULL) {
return GX_APP_UPDATE_ERR_NOMEM;
}
ASSERT(len == sizeof(gx8002_file_head_t));
memcpy((u8 *) & (__this->file_bin_head), ota_data, sizeof(gx8002_file_head_t));
__this->update_role = GX8002_UPDATE_ROLE_TWS_SLAVE;
ret = gx8002_app_ota_start(complete_callback);
if (ret) {
gx8002_app_ota_close();
}
return ret;
}
//===================================================================//
/*
@breif: ota流程回调: 初始化函数, 主机流程
@parma: priv: 访问外置芯片固件地址
@parma: file_ops: 访问外置芯片固件文件操作接口
@return: 1) GX_APP_UPDATE_ERR_NONE = 0: 初始化成功
2) < 0: 初始化失败
*/
//===================================================================//
static int gx8002_chip_update_init(void *priv, update_op_api_t *file_ops)
{
int ret = GX_APP_UPDATE_ERR_NONE;
if (__this) {
return GX_APP_UPDATE_ERR_UPDATE_STATE;
}
user_chip_update_info_t *update_info = (user_chip_update_info_t *)priv;
__this = zalloc(sizeof(struct app_ota_info));
if (__this == NULL) {
return GX_APP_UPDATE_ERR_NOMEM;
}
__this->ufw_addr = update_info->addr;
__this->file_ops = file_ops;
__this->update_role = GX8002_UPDATE_ROLE_NORMAL;
__this->update_result = GX_APP_UPDATE_ERR_NONE;
__this->cur_seek_file = FW_FLASH_MAX;
ota_upgrade_info("%s: ufw_addr = 0x%x", __func__, __this->ufw_addr);
ret = gx8002_ufw_file_verify(__this->ufw_addr, file_ops);
ota_upgrade_info("%s, ret = %d", __func__, ret);
return ret;
}
//===================================================================//
/*
@breif: ota流程回调: 获取升级问文件长度, 用于计算升级进度, 主机调用
@parma: void
@return: 1) 升级长度(int)
2) = 0: 升级状态出错
*/
//===================================================================//
static int gx8002_chip_update_get_len(void)
{
int update_len = 0;
if (__this == NULL) {
return 0;
}
update_len = __this->file_boot_head.len + __this->file_bin_head.len;
ota_upgrade_info("%s: boot_len = 0x%x, bin_len = 0x%x, update_len = 0x%x", __func__, __this->file_boot_head.len, __this->file_bin_head.len, update_len);
return update_len;
}
//===================================================================//
/*
@breif: ota流程回调: 升级主流程, 主机调用
@parma: void *priv 用于tws同步升级接口(update_op_tws_api_t), 非tws同步升级设置未NULL即可
@return: 1) = 0: 升级成功
2) < 0: 升级失败
*/
//===================================================================//
static int gx8002_chip_update_loop(void *priv)
{
int ret = 0;
if (__this == NULL) {
return 0;
}
ota_upgrade_debug("%s", __func__);
int (*start_callback)(void) = NULL;
if (priv) {
__this->update_role = GX8002_UPDATE_ROLE_TWS_MASTER;
ret = gx8002_uart_app_ota_tws_update_init(priv);
if (ret) {
goto __update_end;
}
gx8002_uart_app_ota_tws_update_sync_start((u8 *) & (__this->file_bin_head), sizeof(gx8002_file_head_t));
start_callback = gx8002_uart_app_ota_tws_update_sync_pend;
}
os_sem_create(&(__this->ota_sem), 0);
ret = gx8002_app_ota_start(start_callback);
if (ret != GX_APP_UPDATE_ERR_NONE) {
goto __update_end;
}
//update 线程接收数据
ret = gx8002_ota_data_receive((u8 *)(__this->packet_buf), sizeof(__this->packet_buf));
if (ret != GX_APP_UPDATE_ERR_NONE) {
goto __update_end;
}
//等待升级完成
os_sem_pend(&(__this->ota_sem), 0);
if (__this->update_result != GX_APP_UPDATE_ERR_NONE) {
ota_upgrade_info("gx8002 update failed.");
} else {
ota_upgrade_info("gx8002 update succ.");
}
ret = __this->update_result;
__update_end:
if (priv) {
ret |= gx8002_uart_app_ota_tws_update_sync_result_get();
gx8002_uart_app_ota_tws_update_close();
}
if (__this->cbuf_handle) {
free(__this->cbuf_handle);
__this->cbuf_handle = NULL;
}
if (__this) {
free(__this);
__this = NULL;
}
return ret;
}
//===================================================================//
/*
@breif: 需要升级流程提供注册接口
@parma: user_chip_update_file_name: 外置芯片升级文件名, 包含在update.ufw文件中
@parma: user_update_handle: 当update.ufw存在升级文件时回调该函数升级外置芯片固件
@parma: addr: 外置芯片固件在update.ufw升级文件中地址
@parma: file_ops: 访问外置芯片固件文件操作接口
*/
//===================================================================//
static const user_chip_update_t gx8002_user_chip_update_instance = {
.file_name = "gx8002.bin",
.update_init = gx8002_chip_update_init,
.update_get_len = gx8002_chip_update_get_len,
.update_loop = gx8002_chip_update_loop,
};
//===================================================================//
/*
@breif: 注册ota流程回调, 提供给gx8002线程调用
@parma: void
@return: void
*/
//===================================================================//
void gx8002_uart_app_ota_update_register_handle(void)
{
register_user_chip_update_handle(&gx8002_user_chip_update_instance);
#if GX8002_UPGRADE_APP_TWS_TOGGLE
gx8002_uart_app_ota_tws_update_register_handle();
#endif /* #if GX8002_UPGRADE_APP_TWS_TOGGLE */
}
//===================================================================//
/*
@breif: 外置芯片启动升级流程, 提供给gx8002线程调用
@parma: void
@return: 1) 0: 升级成功
2) -1: 升级失败
*/
//===================================================================//
int gx8002_uart_app_ota_init(void)
{
int ret = 0;
upgrade_uart_t uart_ops;
ota_upgrade_info("gx8002_uart_app_ota start >>>>");
uart_ops.open = gx_upgrade_uart_porting_open;
uart_ops.close = gx_upgrade_uart_porting_close;
uart_ops.send = gx_upgrade_uart_porting_write;
uart_ops.wait_reply = gx_uart_upgrade_porting_wait_reply;
fw_stream_t fw_stream_ops;
fw_stream_ops.open = fw_stream_open;
fw_stream_ops.close = fw_stream_close;
fw_stream_ops.read = fw_stream_read;
fw_stream_ops.get_flash_img_info = fw_stream_get_flash_img_info;
gx_uart_upgrade_init(&uart_ops, &fw_stream_ops, gx8002_upgrade_status_cb);
ret = gx8002_upgrade_task(NULL);
if (ret < 0) {
__this->update_result = GX_APP_UPDATE_ERR_UPDATE_LOOP;
} else {
__this->update_result = GX_APP_UPDATE_ERR_NONE;
}
gx8002_app_ota_close();
return ret;
}
#else /* #if GX8002_UPGRADE_APP_TOGGLE */
int gx8002_uart_app_ota_init(void)
{
return 0;
}
#endif /* #if GX8002_UPGRADE_APP_TOGGLE */

View File

@ -0,0 +1,265 @@
#include "includes.h"
#include "../gx_uart_upgrade.h"
#include "../../gx8002_npu_api.h"
#include "../gx_uart_upgrade_porting.h"
//#include "../utils/gx_fifo.h"
#if (GX8002_UPGRADE_APP_TWS_TOGGLE && OTA_TWS_SAME_TIME_ENABLE)
struct gx8002_tws_update {
update_op_tws_api_t *tws_handle;
OS_SEM tws_sync_sem;
u8 slave_result;
};
enum GX8002_TWS_UPDATE_CMD {
GX8002_TWS_UPDATE_CMD_START = 'G',
GX8002_TWS_UPDATE_CMD_UFW_DATA,
GX8002_TWS_UPDATE_CMD_RESPOND,
GX8002_TWS_UPDATE_CMD_RESULT,
};
static struct gx8002_tws_update *tws_update = NULL;
#define GX8002_OTA_UPGRADE_DEBUG_ENABLE 0
#define ota_upgrade_info printf
#if GX8002_OTA_UPGRADE_DEBUG_ENABLE
#define ota_upgrade_debug printf
#define ota_upgrade_put_buf put_buf
#else
#define ota_upgrade_debug(...)
#define ota_upgrade_put_buf(...)
#endif /* #if GX8002_DEBUG_ENABLE */
#define GX8002_TWS_SYNC_TIMEOUT 300
extern int gx8002_ota_data_passive_receive(u8 *data, u32 size);
extern int gx8002_app_ota_passive_start(int (*complete_callback)(void), u8 *ota_data, u16 len);
extern update_op_tws_api_t *get_tws_update_api(void);
extern void tws_update_register_user_chip_update_handle(void (*update_handle)(void *data, u32 len));
int gx8002_uart_app_ota_tws_update_sync_pend(void)
{
ota_upgrade_debug("%s", __func__);
if (tws_update) {
if (os_sem_pend(&(tws_update->tws_sync_sem), GX8002_TWS_SYNC_TIMEOUT) == OS_TIMEOUT) {
return -1;
}
}
return 0;
}
int gx8002_uart_app_ota_tws_update_sync_post(void)
{
ota_upgrade_debug("%s", __func__);
if (tws_update) {
os_sem_post(&(tws_update->tws_sync_sem));
}
return 0;
}
int gx8002_uart_app_ota_tws_update_sync_result(int result)
{
ota_upgrade_info("%s: result: 0x%x", __func__, result);
if (tws_update) {
if (result) {
tws_update->slave_result = 'N';
} else {
tws_update->slave_result = 'O';
}
if (tws_update->tws_handle) {
tws_update->tws_handle->tws_ota_user_chip_update_send(GX8002_TWS_UPDATE_CMD_RESULT, &(tws_update->slave_result), 1);
}
}
return 0;
}
int gx8002_uart_app_ota_tws_update_sync_result_get(void)
{
if (tws_update) {
if (gx8002_uart_app_ota_tws_update_sync_pend()) {
ota_upgrade_info("%s timeout", __func__);
return -1;
}
if (tws_update->slave_result == 'O') {
ota_upgrade_info("%s, get: O", __func__);
return 0;
}
}
ota_upgrade_info("%s state err", __func__);
return -1;
}
int gx8002_uart_app_ota_tws_update_sync_respond(void)
{
ota_upgrade_debug("%s", __func__);
if (tws_update) {
if (tws_update->tws_handle) {
tws_update->tws_handle->tws_ota_user_chip_update_send(GX8002_TWS_UPDATE_CMD_RESPOND, NULL, 0);
}
}
return 0;
}
int gx8002_uart_app_ota_tws_update_sync_start(u8 *buf, u16 len)
{
if (tws_update) {
if (tws_update->tws_handle) {
tws_update->tws_handle->tws_ota_user_chip_update_send(GX8002_TWS_UPDATE_CMD_START, buf, len);
}
}
return 0;
}
int gx8002_uart_app_ota_tws_update_sync_data(u8 *buf, u16 len)
{
if (tws_update) {
if (tws_update->tws_handle) {
tws_update->tws_handle->tws_ota_user_chip_update_send(GX8002_TWS_UPDATE_CMD_UFW_DATA, buf, len);
}
}
return 0;
}
int gx8002_uart_app_ota_tws_update_init(void *priv)
{
ota_upgrade_info("%s", __func__);
if (tws_update) {
free(tws_update);
}
if (priv == NULL) {
return -1;
}
tws_update = zalloc(sizeof(struct gx8002_tws_update));
if (tws_update == NULL) {
return -1;
}
tws_update->tws_handle = priv;
os_sem_create(&(tws_update->tws_sync_sem), 0);
return 0;
}
int gx8002_uart_app_ota_tws_update_close(void)
{
if (tws_update) {
free(tws_update);
tws_update = NULL;
}
return 0;
}
static void gx8002_uart_app_ota_tws_update_handle(void *data, u32 len)
{
u8 *rx_packet = (u8 *)data;
int ret = 0;
ota_upgrade_debug("receive cmd 0x%x, data len = 0x%x", rx_packet[0], len - 1);
switch (rx_packet[0]) {
case GX8002_TWS_UPDATE_CMD_START:
gx8002_uart_app_ota_tws_update_init(get_tws_update_api());
ret = gx8002_app_ota_passive_start(gx8002_uart_app_ota_tws_update_sync_respond, rx_packet + 1, len - 1);
if (ret) {
gx8002_uart_app_ota_tws_update_close();
}
break;
case GX8002_TWS_UPDATE_CMD_UFW_DATA:
gx8002_ota_data_passive_receive(rx_packet + 1, len - 1);
break;
case GX8002_TWS_UPDATE_CMD_RESPOND:
gx8002_uart_app_ota_tws_update_sync_post();
break;
case GX8002_TWS_UPDATE_CMD_RESULT:
ota_upgrade_info("result: 0x%x", rx_packet[1]);
if (tws_update) {
tws_update->slave_result = rx_packet[1];
}
gx8002_uart_app_ota_tws_update_sync_post();
break;
default:
break;
}
}
void gx8002_uart_app_ota_tws_update_register_handle(void)
{
tws_update_register_user_chip_update_handle(gx8002_uart_app_ota_tws_update_handle);
}
#else /* #if (GX8002_UPGRADE_APP_TWS_TOGGLE && OTA_TWS_SAME_TIME_ENABLE) */
void gx8002_uart_app_ota_tws_update_register_handle(void)
{
return;
}
int gx8002_uart_app_ota_tws_update_init(void *priv)
{
return 0;
}
int gx8002_uart_app_ota_tws_update_sync_pend(void)
{
return 0;
}
int gx8002_uart_app_ota_tws_update_sync_post(void)
{
return 0;
}
int gx8002_uart_app_ota_tws_update_sync_data(u8 *buf, u16 len)
{
return 0;
}
int gx8002_uart_app_ota_tws_update_sync_respond(void)
{
return 0;
}
int gx8002_uart_app_ota_tws_update_close(void)
{
return 0;
}
int gx8002_uart_app_ota_tws_update_sync_start(u8 *buf, u16 len)
{
return 0;
}
int gx8002_uart_app_ota_tws_update_sync_result(int result)
{
return 0;
}
int gx8002_uart_app_ota_tws_update_sync_result_get(void)
{
return 0;
}
#endif /* #if (GX8002_UPGRADE_APP_TWS_TOGGLE && OTA_TWS_SAME_TIME_ENABLE) */

View File

@ -0,0 +1,482 @@
#include "includes.h"
#include "gx_uart_upgrade.h"
#include "../gx8002_npu_api.h"
#if GX8002_UPGRADE_TOGGLE
#define GX_UPGRADE_DEBUG 0
#if GX_UPGRADE_DEBUG
//#define upgrade_debug(fmt, ...) y_printf("[gx_uart_upgrade]: " fmt, ##__VA_ARGS__)
#define upgrade_debug printf
#else
#define upgrade_debug(fmt, ...)
#endif
#define HANDSHAKE_BAUDRATE 576000
#define UART_REPLY_TIMEOUT_MS 5000
static upgrade_uart_t uart_ops;
static fw_stream_t fw_stream_ops;
static upgrade_status_cb status_callback;
typedef struct {
unsigned short chip_id;
unsigned char chip_type;
unsigned char chip_version;
unsigned short boot_delay;
unsigned char baud_rate;
unsigned char reserved_1;
unsigned int stage1_size;
unsigned int stage2_baud_rate;
unsigned int stage2_size;
unsigned int stage2_checksum;
unsigned char reserved[8];
} __attribute__((packed)) boot_header_t;
static boot_header_t boot_header;
static unsigned char data_buf[UPGRADE_PACKET_SIZE];
static upgrade_stage_e current_stage;
static int upgrade_initialized = 0;
static inline void set_upgrade_stage(upgrade_stage_e stage)
{
current_stage = stage;
}
static inline upgrade_stage_e get_upgrade_stage(void)
{
return current_stage;
}
static void status_report(upgrade_status_e status)
{
if (status_callback) {
status_callback(get_upgrade_stage(), status);
}
}
static int upgrade_handshake(unsigned int timeout_ms, unsigned int retry_times)
{
int ret = -1;
upgrade_debug("start upgrade_handshake, timeout_ms: %d, retry_times: %d\n", timeout_ms, retry_times);
set_upgrade_stage(UPGRADE_STAGE_HANDSHAKE);
status_report(UPGRADE_STATUS_START);
upgrade_debug("waiting 'M' ...\n");
while (retry_times--) {
upgrade_debug("handshake retry_times: %d", retry_times);
unsigned char c = 0xef;
uart_ops.send(&c, 1);
if (!uart_ops.wait_reply((const unsigned char *)"M", 1, timeout_ms)) {
ret = 0;
break;
}
}
if (ret == 0) {
upgrade_debug("get 'M' !\n");
status_report(UPGRADE_STATUS_OK);
} else {
upgrade_debug("wait 'M' err !\n");
status_report(UPGRADE_STATUS_ERR);
}
upgrade_debug("upgrade_handshake over, ret: %d\n ", ret);
return ret;
}
static int is_little_endian(void)
{
int a = 0x11223344;
unsigned char *p = (unsigned char *)&a;
return (*p == 0x44) ? 1 : 0;
}
static unsigned int switch_endian(unsigned int v)
{
return (((v >> 0) & 0xff) << 24) | (((v >> 8) & 0xff) << 16) | (((v >> 16) & 0xff) << 8) | (((v >> 24) & 0xff) << 0);
}
static unsigned int be32_to_cpu(unsigned int v)
{
if (is_little_endian()) {
return switch_endian(v);
} else {
return v;
}
}
static int boot_info_baudrate[] = {300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200};
static void print_bootheader(const boot_header_t *header)
{
upgrade_debug("chip_id %x\n", header->chip_id);
upgrade_debug("chip_type %x\n", header->chip_type);
upgrade_debug("chip_version %x\n", header->chip_version);
upgrade_debug("boot_delay %x\n", header->boot_delay);
upgrade_debug("baud_rate %d\n", boot_info_baudrate[header->baud_rate]);
upgrade_debug("stage1_size %d\n", header->stage1_size);
upgrade_debug("stage2_baud_rate %d\n", header->stage2_baud_rate);
upgrade_debug("stage2_size %d\n", header->stage2_size);
upgrade_debug("stage2_checksum %d\n", header->stage2_checksum);
}
int parse_bootimg_header(void)
{
upgrade_debug("reading boot header ...\n");
set_upgrade_stage(UPGRADE_STAGE_BOOT_HEADER);
status_report(UPGRADE_STATUS_START);
int ret = fw_stream_ops.read(FW_BOOT_IMAGE, (unsigned char *)&boot_header, sizeof(boot_header));
if (ret < sizeof(boot_header)) {
upgrade_debug("read boot header err !\n");
goto header_err;
}
boot_header.stage1_size = be32_to_cpu(boot_header.stage1_size);
boot_header.stage2_baud_rate = be32_to_cpu(boot_header.stage2_baud_rate);
boot_header.stage2_size = be32_to_cpu(boot_header.stage2_size);
boot_header.stage2_checksum = be32_to_cpu(boot_header.stage2_checksum);
print_bootheader(&boot_header);
status_report(UPGRADE_STATUS_OK);
return 0;
header_err:
status_report(UPGRADE_STATUS_ERR);
return -1;
}
int download_bootimg_stage1(void)
{
int wsize = 0;
int len = 0;
int size = 0;
upgrade_debug("start boot stage1 ...\n");
set_upgrade_stage(UPGRADE_STAGE_BOOT_S1);
status_report(UPGRADE_STATUS_START);
size = boot_header.stage1_size;
size = size / 4;
data_buf[0] = 'Y';
data_buf[1] = (size >> 0) & 0xFF;
data_buf[2] = (size >> 8) & 0xFF;
data_buf[3] = (size >> 16) & 0xFF;
data_buf[4] = (size >> 24) & 0xFF;
uart_ops.send(data_buf, 5);
if (boot_header.chip_type == 0x01) {
size = size * 4;
}
upgrade_debug("download boot stage1 ...\n");
while (wsize < size) {
if (wsize % UPGRADE_BLOCK_SIZE == 0) {
status_report(UPGRADE_STATUS_DOWNLOADING);
}
len = (boot_header.stage1_size - wsize >= UPGRADE_PACKET_SIZE) ? UPGRADE_PACKET_SIZE : (boot_header.stage1_size - wsize);
len = fw_stream_ops.read(FW_BOOT_IMAGE, data_buf, len);
if (len <= 0) {
upgrade_debug("read data err !\n");
goto stage1_err;
}
len = uart_ops.send(data_buf, len);
if (len <= 0) {
upgrade_debug("send data err !\n");
goto stage1_err;
}
wsize += len;
}
upgrade_debug("download size: %d, waiting 'F' ...\n", wsize);
if (uart_ops.wait_reply((const unsigned char *)"F", 1, UART_REPLY_TIMEOUT_MS)) {
upgrade_debug("wait 'F' err !\n");
goto stage1_err;
}
upgrade_debug("get 'F' !\n");
///// stage1 running, change baudrate /////
upgrade_debug("change baudrate: %d\n", boot_header.stage2_baud_rate);
uart_ops.close();
uart_ops.open(boot_header.stage2_baud_rate, 8, 1, 0);
upgrade_debug("wait \"GET\" ...\n");
if (uart_ops.wait_reply((const unsigned char *)"GET", 3, UART_REPLY_TIMEOUT_MS)) {
upgrade_debug("wait 'GET' err !\n");
goto stage1_err;
}
upgrade_debug("get \"GET\" !\n");
data_buf[0] = 'O';
data_buf[1] = 'K';
uart_ops.send(data_buf, 2);
status_report(UPGRADE_STATUS_OK);
upgrade_debug("boot stage1 ok !\n");
return 0;
stage1_err:
status_report(UPGRADE_STATUS_ERR);
upgrade_debug("boot stage1 err !\n");
return -1;
}
int download_bootimg_stage2(void)
{
unsigned int checksum = 0;
unsigned int stage2_size = 0;
int len = 0;
int wsize = 0;
upgrade_debug("start boot stage2 ...\n");
set_upgrade_stage(UPGRADE_STAGE_BOOT_S2);
status_report(UPGRADE_STATUS_START);
stage2_size = boot_header.stage2_size;
checksum = boot_header.stage2_checksum;
upgrade_debug("stage2_size = %u, checksum = %u\n", stage2_size, checksum);
if (checksum == 0 || stage2_size == 0) {
upgrade_debug("stage2_size or checksum err !\n");
goto stage2_err;
}
data_buf[0] = 'S';
uart_ops.send(data_buf, 1);
uart_ops.send((const unsigned char *)&checksum, 4);
uart_ops.send((const unsigned char *)&stage2_size, 4);
upgrade_debug("waiting \"ready\" ...\n");
if (uart_ops.wait_reply((const unsigned char *)"ready", 5, UART_REPLY_TIMEOUT_MS)) {
upgrade_debug("wait ready error !\n");
goto stage2_err;
}
upgrade_debug("get \"ready\"\n");
upgrade_debug("download boot stage2 ...\n");
while (wsize < stage2_size) {
if (wsize % UPGRADE_BLOCK_SIZE == 0) {
status_report(UPGRADE_STATUS_DOWNLOADING);
}
len = (stage2_size - wsize >= UPGRADE_PACKET_SIZE) ? UPGRADE_PACKET_SIZE : (stage2_size - wsize);
len = fw_stream_ops.read(FW_BOOT_IMAGE, data_buf, len);
if (len <= 0) {
upgrade_debug("read data err !\n");
goto stage2_err;
}
len = uart_ops.send(data_buf, len);
if (len <= 0) {
upgrade_debug("send data err !\n");
goto stage2_err;
}
wsize += len;
}
upgrade_debug("download size: %d, waiting 'O' ...\n", wsize);
if (uart_ops.wait_reply((const unsigned char *)"O", 1, UART_REPLY_TIMEOUT_MS)) {
upgrade_debug("wait 'O' err !\n");
goto stage2_err;
}
upgrade_debug("get 'O' !\n");
upgrade_debug("waiting \"boot>\" ...\n");
if (uart_ops.wait_reply((const unsigned char *)"boot>", 5, UART_REPLY_TIMEOUT_MS)) {
upgrade_debug("wait \"boot>\" err !\n");
goto stage2_err;
}
upgrade_debug("get \"boot>\" !\n");
status_report(UPGRADE_STATUS_OK);
upgrade_debug("boot stage2 ok !\n");
return 0;
stage2_err:
status_report(UPGRADE_STATUS_ERR);
upgrade_debug("boot stage2 err !\n");
return -1;
}
static int download_bootimg(void)
{
if (parse_bootimg_header() != 0) {
return -1;
}
if (download_bootimg_stage1() != 0) {
return -1;
}
if (download_bootimg_stage2() != 0) {
return -1;
}
return 0;
}
static int download_flashimg(void)
{
int wsize = 0;
int len = 0;
flash_img_info_t info = {0};
upgrade_debug("start flash image ...\n");
set_upgrade_stage(UPGRADE_STAGE_FLASH_IMG);
status_report(UPGRADE_STATUS_START);
fw_stream_ops.get_flash_img_info(&info);
upgrade_debug("flash image size = %d\n", info.img_size);
if (info.img_size == 0) {
upgrade_debug("flash image size err !\n");
goto flash_err;
}
memset(data_buf, 0, UPGRADE_PACKET_SIZE);
len = sprintf((char *)data_buf, "serialdown %d %d %d\n", 0, info.img_size, UPGRADE_FLASH_BLOCK_SIZE);
uart_ops.send(data_buf, len);
upgrade_debug("waiting \"~sta~\" ...\n");
if (uart_ops.wait_reply((const unsigned char *)"~sta~", 5, UART_REPLY_TIMEOUT_MS)) {
upgrade_debug("wait ~sta~ err !\n");
goto flash_err;
}
upgrade_debug("get \"~sta~\" !\n");
upgrade_debug("download flash image ...\n");
while (wsize < info.img_size) {
if (wsize % UPGRADE_BLOCK_SIZE == 0) {
status_report(UPGRADE_STATUS_DOWNLOADING);
}
len = (info.img_size - wsize >= UPGRADE_PACKET_SIZE) ? UPGRADE_PACKET_SIZE : (info.img_size - wsize);
len = fw_stream_ops.read(FW_FLASH_IMAGE, data_buf, len);
if (len <= 0) {
upgrade_debug("read data err !\n");
goto flash_err;
}
len = uart_ops.send(data_buf, len);
if (len <= 0) {
upgrade_debug("send data err !\n");
goto flash_err;
}
wsize += len;
if ((wsize % UPGRADE_FLASH_BLOCK_SIZE) == 0) {
upgrade_debug("waiting \"~sta~\" ...\n");
if (uart_ops.wait_reply((const unsigned char *)"~sta~", 5, UART_REPLY_TIMEOUT_MS)) {
upgrade_debug("wait \"~sta~\" err !\n");
goto flash_err;
}
upgrade_debug("get \"~sta~\" !\n");
}
}
upgrade_debug("download size: %d, waiting \"~fin~\" ...\n", wsize);
if (uart_ops.wait_reply((const unsigned char *)"~fin~", 5, UART_REPLY_TIMEOUT_MS)) {
upgrade_debug("wait \"~fin~\" err !\n");
goto flash_err;
}
upgrade_debug("get \"~fin~\" !\n");
status_report(UPGRADE_STATUS_OK);
upgrade_debug("flash image ok !\n");
return 0;
flash_err:
status_report(UPGRADE_STATUS_ERR);
upgrade_debug("flash image err !\n");
return -1;
}
int gx_uart_upgrade_proc(void)
{
int ret = -1;
if (!upgrade_initialized) {
return -1;
}
set_upgrade_stage(UPGRADE_STAGE_NONE);
if (uart_ops.open(HANDSHAKE_BAUDRATE, 8, 1, 0) < 0) {
upgrade_debug("open uart err !\n");
goto upgrade_done;
}
if (fw_stream_ops.open(FW_BOOT_IMAGE) < 0) {
upgrade_debug("open boot img stream err !\n");
goto upgrade_done;
}
if (fw_stream_ops.open(FW_FLASH_IMAGE) < 0) {
upgrade_debug("open flash img stream err !\n");
goto upgrade_done;
}
/* JL_PORTA->DIR &= ~BIT(4); */
/* JL_PORTA->OUT |= BIT(4); */
if (upgrade_handshake(10, 100) < 0) {
goto upgrade_done;
}
if (download_bootimg() < 0) {
goto upgrade_done;
}
if (download_flashimg() < 0) {
goto upgrade_done;
}
ret = 0;
upgrade_done:
uart_ops.close();
fw_stream_ops.close(FW_BOOT_IMAGE);
fw_stream_ops.close(FW_FLASH_IMAGE);
set_upgrade_stage(UPGRADE_STAGE_NONE);
return ret;
}
int gx_uart_upgrade_init(upgrade_uart_t *uart, fw_stream_t *fw_stream, upgrade_status_cb status_cb)
{
if ((uart == NULL) || (fw_stream == NULL)) {
return -1;
}
memcpy(&uart_ops, uart, sizeof(upgrade_uart_t));
memcpy(&fw_stream_ops, fw_stream, sizeof(fw_stream_t));
status_callback = status_cb;
upgrade_initialized = 1;
return 0;
}
int gx_uart_upgrade_deinit(void)
{
upgrade_initialized = 0;
return 0;
}
#endif /* #if GX8002_UPGRADE_TOGGLE */

View File

@ -0,0 +1,17 @@
#ifndef __GX_URAT_UPGRADE_H__
#define __GX_URAT_UPGRADE_H__
#include "gx_upgrade_def.h"
typedef struct {
int (*open)(int baud, int databits, int stopbits, int parity);
int (*close)(void);
int (*wait_reply)(const unsigned char *buf, unsigned int len, unsigned int timeout);
int (*send)(const unsigned char *buf, unsigned int len);
} upgrade_uart_t;
int gx_uart_upgrade_init(upgrade_uart_t *uart, fw_stream_t *fw_stream, upgrade_status_cb status_cb);
int gx_uart_upgrade_deinit(void);
int gx_uart_upgrade_proc(void);
#endif

View File

@ -0,0 +1,136 @@
#include "includes.h"
#include "asm/uart_dev.h"
#include "gx_uart_upgrade_porting.h"
#include "../gx8002_npu_api.h"
#include "app_config.h"
#if GX8002_UPGRADE_TOGGLE
#define GX_UART_UPGRADE_PORT_DEBUG 1
#ifdef GX_UART_UPGRADE_PORT_DEBUG
//#define upgrade_debug(fmt, ...) y_printf("[gx_uart_upgrade]: " fmt, ##__VA_ARGS__)
#define gx_uart_upgrade_port_debug y_printf
#else
#define gx_uart_upgrade_port_debug(fmt, ...)
#endif
struct gx_upgrade_uart_port {
const uart_bus_t *uart_bus;
u32 cur_baud;
};
static u8 uart_upgrade_cbuf[512] __attribute__((aligned(4)));
static struct gx_upgrade_uart_port uart_port = {0};
#define __this (&uart_port)
static void gx8002_upgrade_uart_isr_hook(void *arg, u32 status)
{
if (status != UT_TX) {
//gx_uart_upgrade_port_debug("UT_RX_OT pending");
}
}
int gx_upgrade_uart_porting_open(int baud, int databits, int stopbits, int parity)
{
int ret = -1;
struct uart_platform_data_t u_arg = {0};
if (__this->uart_bus) {
gx_uart_upgrade_port_debug("gx8002 uart upgrade have open");
return 0;
}
u_arg.tx_pin = TCFG_GX8002_NPU_UART_TX_PORT;
u_arg.rx_pin = TCFG_GX8002_NPU_UART_RX_PORT;
u_arg.rx_cbuf = uart_upgrade_cbuf;
u_arg.rx_cbuf_size = sizeof(uart_upgrade_cbuf);
u_arg.frame_length = 0xFFFF;
u_arg.rx_timeout = 5;
u_arg.isr_cbfun = gx8002_upgrade_uart_isr_hook;
u_arg.baud = baud;
u_arg.is_9bit = 0;
__this->uart_bus = uart_dev_open(&u_arg);
if (__this->uart_bus != NULL) {
gx_uart_upgrade_port_debug("gx8002 uart upgrade open: baud: %d", baud);
ret = 0;
} else {
gx_uart_upgrade_port_debug("gx8002 uart upgrade open fail");
}
return ret;
}
int gx_upgrade_uart_porting_close(void)
{
if (__this->uart_bus) {
uart_dev_close(__this->uart_bus);
gpio_disable_fun_output_port(TCFG_GX8002_NPU_UART_TX_PORT);
__this->uart_bus = NULL;
}
return 0;
}
int gx_upgrade_uart_porting_read(unsigned char *buf, unsigned int len, unsigned int timeout_ms)
{
int ret = -1;
if (__this->uart_bus && __this->uart_bus->read) {
ret = __this->uart_bus->read(buf, len, timeout_ms);
}
return ret;
}
//int gx_upgrade_uart_porting_write(const unsigned char *buf, unsigned int len, unsigned int timeout_ms)
int gx_upgrade_uart_porting_write(const unsigned char *buf, unsigned int len)
{
int ret = len;
if (__this->uart_bus && __this->uart_bus->write) {
__this->uart_bus->write(buf, len);
}
return ret;
}
int gx_uart_upgrade_porting_wait_reply(const unsigned char *buf, unsigned int len, unsigned int timeout_ms)
{
int index = 0;
unsigned char ch;
while (gx_upgrade_uart_porting_read(&ch, 1, timeout_ms) > 0) {
//gx_uart_upgrade_port_debug("`0x%02x`\n", ch);
if (ch == (unsigned char)buf[index]) {
index++;
}
if (index == len) {
return 0;
}
}
return -1;
}
static void uart_clock_critical_enter(void)
{
}
static void uart_clock_critical_exit(void)
{
if (__this->uart_bus && __this->uart_bus->set_baud) {
gx_uart_upgrade_port_debug("clock critical uart set_baud: %d", __this->cur_baud);
__this->uart_bus->set_baud(__this->cur_baud);
}
}
CLOCK_CRITICAL_HANDLE_REG(gx8002, uart_clock_critical_enter, uart_clock_critical_exit)
#endif /* #if GX8002_UPGRADE_TOGGLE */

View File

@ -0,0 +1,16 @@
#ifndef _GX_UART_UPGRADE_UPGRADE_PORT_
#define _GX_UART_UPGRADE_UPGRADE_PORT_
int gx_upgrade_uart_porting_open(int baud, int databits, int stopbits, int parity);
int gx_upgrade_uart_porting_close(void);
int gx_upgrade_uart_porting_read(unsigned char *buf, unsigned int len, unsigned int timeout_ms);
//int gx_upgrade_uart_porting_write(const unsigned char *buf, unsigned int len, unsigned int timeout_ms);
int gx_upgrade_uart_porting_write(const unsigned char *buf, unsigned int len);
int gx_uart_upgrade_porting_wait_reply(const unsigned char *buf, unsigned int len, unsigned int timeout_ms);
#endif /* #ifndef _GX_UART_UPGRADE_UPGRADE_PORT_ */

View File

@ -0,0 +1,47 @@
#ifndef __GX_UPGRADE_DEF_H__
#define __GX_UPGRADE_DEF_H__
#define UPGRADE_DATA_BLOCK_SIZE 256
#define UPGRADE_PACKET_SIZE 256
#define UPGRADE_BLOCK_SIZE (1024 * 4)
#define UPGRADE_FLASH_BLOCK_SIZE (1024 * 56) //56K
typedef enum {
UPGRADE_STAGE_HANDSHAKE = 0,
UPGRADE_STAGE_BOOT_HEADER,
UPGRADE_STAGE_BOOT_S1,
UPGRADE_STAGE_BOOT_S2,
UPGRADE_STAGE_FLASH_IMG,
UPGRADE_STAGE_NONE
} upgrade_stage_e;
typedef enum {
UPGRADE_STATUS_START = 0,
UPGRADE_STATUS_DOWNLOADING,
UPGRADE_STATUS_OK,
UPGRADE_STATUS_ERR,
UPGRADE_STATUS_NONE
} upgrade_status_e;
typedef void (*upgrade_status_cb)(upgrade_stage_e stage, upgrade_status_e status);
typedef enum {
FW_BOOT_IMAGE = 0, //"gx8002.boot"
FW_FLASH_IMAGE, //"mcu_nor.bin"
FW_FLASH_MAX,
} FW_IMAGE_TYPE;
typedef struct {
unsigned int img_size;
} flash_img_info_t;
typedef struct {
int (*open)(FW_IMAGE_TYPE img_type);
int (*close)(FW_IMAGE_TYPE img_type);
int (*read)(FW_IMAGE_TYPE img_type, unsigned char *buf, unsigned int len);
int (*get_flash_img_info)(flash_img_info_t *info);
} fw_stream_t;
#endif

View File

@ -0,0 +1,189 @@
#include "includes.h"
#include "../gx_uart_upgrade.h"
#include "../../gx8002_npu_api.h"
#include "../gx_uart_upgrade_porting.h"
#if GX8002_UPGRADE_SDFILE_TOGGLE
#define STREAM_FIFO_BLOCK_TOTAL 20
#define STREAM_FIFO_TIMEOUT_MS 7000
typedef int (*reply)(unsigned char *data, int size);
static int ota_start = 0;
struct sdfile_fifo {
FILE *boot_fp;
FILE *bin_fp;
};
static struct sdfile_fifo sdfile_upgrade = {0};
#define __this (&sdfile_upgrade)
#define GX8002_SDFILE_UPGRADE_DEBUG_ENABLE 1
#define sdfile_upgrade_info g_printf
#if GX8002_SDFILE_UPGRADE_DEBUG_ENABLE
#define sdfile_upgrade_debug r_printf
#define sdfile_upgrade_put_buf put_buf
#else
#define sdfile_upgrade_debug(...)
#define sdfile_upgrade_put_buf(...)
#endif /* #if GX8002_DEBUG_ENABLE */
////////////// FW Stream Porting //////////////////
static int fw_stream_open(FW_IMAGE_TYPE img_type)
{
#define BOOT_IMAGE_PATH SDFILE_RES_ROOT_PATH"gx8002.boot"
#define BIN_IMAGE_PATH SDFILE_RES_ROOT_PATH"mcu_nor.bin"
FILE *fp = NULL;
if (img_type == FW_BOOT_IMAGE) {
fp = fopen(BOOT_IMAGE_PATH, "r");
if (fp) {
sdfile_upgrade_info("open %s succ", BOOT_IMAGE_PATH);
__this->boot_fp = fp;
} else {
sdfile_upgrade_info("open %s failed!", BOOT_IMAGE_PATH);
return -1;
}
} else if (img_type == FW_FLASH_IMAGE) {
fp = fopen(BIN_IMAGE_PATH, "r");
if (fp) {
sdfile_upgrade_info("open %s succ", BIN_IMAGE_PATH);
__this->bin_fp = fp;
} else {
sdfile_upgrade_info("open %s failed!", BIN_IMAGE_PATH);
return -1;
}
}
return 0;
}
static int fw_stream_close(FW_IMAGE_TYPE img_type)
{
int ret = 0;
if (img_type == FW_BOOT_IMAGE) {
if (__this->boot_fp) {
fclose(__this->boot_fp);
__this->boot_fp = NULL;
}
} else if (img_type == FW_FLASH_IMAGE) {
if (__this->bin_fp) {
fclose(__this->bin_fp);
__this->bin_fp = NULL;
}
}
return ret;
}
static int fw_stream_read(FW_IMAGE_TYPE img_type, unsigned char *buf, unsigned int len)
{
int ret = 0;
FILE *fp = NULL;
if (img_type == FW_BOOT_IMAGE) {
fp = __this->boot_fp;
} else if (img_type == FW_FLASH_IMAGE) {
fp = __this->bin_fp;
}
if (fp) {
ret = fread(fp, buf, len);
}
return ret;
}
static int fw_stream_get_flash_img_info(flash_img_info_t *info)
{
int ret = 0;
if (info == NULL) {
return -1;
}
if (__this->bin_fp) {
info->img_size = flen(__this->bin_fp);
}
return ret;
}
///////// status info /////////////
static const char *status_info_str[UPGRADE_STAGE_NONE][UPGRADE_STATUS_NONE] = {
// UPGRADE_STAGE_HANDSHAKE
{"handshake start\n", NULL, "handshake ok\n", "handshake err\n"},
// UPGRADE_STAGE_BOOT_HEADER
{"boot header start\n", NULL, "boot header ok\n", "boot header err\n"},
// UPGRADE_STAGE_BOOT_S1
{"boot stage1 start\n", "boot stage1 downloading\n", "boot stage1 ok\n", "boot stage1 err\n"},
// UPGRADE_STAGE_BOOT_S2
{"boot stage2 start\n", "boot stage2 downloading\n", "boot stage2 ok\n", "boot stage2 err\n"},
// UPGRADE_STAGE_FLASH_IMG
{"flash img start\n", "flash img downloading\n", "flash img ok\n", "flash img err\n"},
};
static void gx8002_upgrade_status_cb(upgrade_stage_e stage, upgrade_status_e status)
{
const char *reply_str = status_info_str[stage][status];
if (reply_str != NULL) {
sdfile_upgrade_info("status info: %s\n", reply_str);
}
}
static int gx8002_upgrade_task(void *param)
{
int ret = 0;
sdfile_upgrade_info("---- gx8002 ota start ----");
gx8002_upgrade_cold_reset();
ret = gx_uart_upgrade_proc();
gx8002_normal_cold_reset();
sdfile_upgrade_info("---- gx8002 ota over ----");
if (ret < 0) {
gx8002_update_end_post_msg(0);
} else {
gx8002_update_end_post_msg(1);
}
return ret;
}
int gx8002_uart_sdfile_ota_init(void)
{
upgrade_uart_t uart_ops;
uart_ops.open = gx_upgrade_uart_porting_open;
uart_ops.close = gx_upgrade_uart_porting_close;
uart_ops.send = gx_upgrade_uart_porting_write;
uart_ops.wait_reply = gx_uart_upgrade_porting_wait_reply;
fw_stream_t fw_stream_ops;
fw_stream_ops.open = fw_stream_open;
fw_stream_ops.close = fw_stream_close;
fw_stream_ops.read = fw_stream_read;
fw_stream_ops.get_flash_img_info = fw_stream_get_flash_img_info;
gx_uart_upgrade_init(&uart_ops, &fw_stream_ops, gx8002_upgrade_status_cb);
gx8002_upgrade_task(NULL);
return 0;
}
#else /* #if GX8002_UPGRADE_SDFILE_TOGGLE */
int gx8002_uart_sdfile_ota_init(void)
{
return 0;
}
#endif /* #if GX8002_UPGRADE_SDFILE_TOGGLE */

View File

@ -0,0 +1,239 @@
#include "includes.h"
#include "gx_fifo.h"
#define os_mutex_t OS_MUTEX *
#define gx_os_mutex_lock os_mutex_pend
#define gx_os_mutex_unlock os_mutex_post
#define os_sem_t OS_SEM *
#define gx_os_sem_post os_sem_post
#define gx_os_sem_wait os_sem_pend
typedef struct {
char *data;
unsigned int length;
} fifoBlock;
typedef struct {
int fifo_head;
int fifo_tail;
int block_num;
int block_total;
int block_size;
fifoBlock *fifo_block;
os_mutex_t fifo_mutex;
os_sem_t fifo_sem;
} GxFIFO;
//======================== OS porting ======================================//
static void *gx_os_calloc(u32 nmemb, u32 size)
{
return zalloc(nmemb * size);
}
static void gx_os_free(void *p)
{
if (p) {
free(p);
}
}
static os_mutex_t gx_os_mutex_create()
{
os_mutex_t mutex;
mutex = (os_mutex_t)gx_os_calloc((sizeof(*mutex)), 1);
ASSERT(mutex, "mutex alloc err");
os_mutex_create(mutex);
return mutex;
}
static void gx_os_mutex_destroy(os_mutex_t mutex)
{
if (mutex) {
os_mutex_del(mutex, 0);
gx_os_free(mutex);
}
}
static os_sem_t gx_os_sem_create(u32 cnt)
{
os_sem_t sem;
sem = (os_mutex_t)gx_os_calloc((sizeof(*sem)), 1);
ASSERT(sem, "sem alloc err");
os_sem_create(sem, cnt);
return sem;
}
static void gx_os_sem_destroy(os_sem_t sem)
{
if (sem) {
os_sem_del(sem, 0);
gx_os_free(sem);
}
}
//==============================================================//
int gx_fifo_destroy(fifo_handle_t fifo)
{
GxFIFO *temp_fifo = (GxFIFO *)fifo;
int i = 0;
if (temp_fifo == NULL) {
return -1;
}
gx_os_mutex_lock(temp_fifo->fifo_mutex, 0);
if (temp_fifo->fifo_block != NULL) {
for (i = 0; i < temp_fifo->block_total; i++) {
if (temp_fifo->fifo_block[i].data != NULL) {
gx_os_free(temp_fifo->fifo_block[i].data);
temp_fifo->fifo_block[i].data = NULL;
}
}
gx_os_free(temp_fifo->fifo_block);
temp_fifo->fifo_block = NULL;
}
gx_os_sem_destroy(temp_fifo->fifo_sem);
gx_os_mutex_destroy(temp_fifo->fifo_mutex);
gx_os_free(temp_fifo);
return 0;
}
fifo_handle_t gx_fifo_create(int block_size, int block_num)
{
GxFIFO *temp_fifo = NULL;
int i = 0;
if ((block_size == 0) || (block_num == 0)) {
goto fifo_failed;
}
if ((temp_fifo = (GxFIFO *)gx_os_calloc(sizeof(GxFIFO), 1)) == NULL) {
goto fifo_failed;
}
if ((temp_fifo->fifo_block = (fifoBlock *)gx_os_calloc(block_num * sizeof(fifoBlock), 1)) == NULL) {
goto fifo_failed;
}
temp_fifo->fifo_mutex = gx_os_mutex_create();
temp_fifo->fifo_sem = gx_os_sem_create(0);
for (i = 0; i < block_num; i++) {
if ((temp_fifo->fifo_block[i].data = (char *)gx_os_calloc(block_size, 1)) == NULL) {
goto fifo_failed;
}
}
temp_fifo->block_total = block_num;
temp_fifo->block_size = block_size;
temp_fifo->fifo_head = 0;
temp_fifo->fifo_tail = -1;
return (fifo_handle_t)temp_fifo;
fifo_failed:
gx_fifo_destroy((fifo_handle_t)temp_fifo);
return 0;
}
int gx_fifo_write(fifo_handle_t fifo, const char *write_data, int write_size)
{
GxFIFO *temp_fifo = (GxFIFO *)fifo;
int cp_size = 0;
if ((temp_fifo == NULL) || (write_data == NULL) || (write_size == 0)) {
return 0;
}
gx_os_mutex_lock(temp_fifo->fifo_mutex, 0);
if (temp_fifo->block_num >= temp_fifo->block_total) {
printf("[%s]%d: fifo full!!!\n", __func__, __LINE__);
gx_os_mutex_unlock(temp_fifo->fifo_mutex);
return 0;
}
temp_fifo->fifo_tail++;
if (temp_fifo->fifo_tail >= temp_fifo->block_total) {
temp_fifo->fifo_tail = 0;
}
(write_size >= temp_fifo->block_size)
? (cp_size = temp_fifo->block_size) : (cp_size = write_size);
memcpy(temp_fifo->fifo_block[temp_fifo->fifo_tail].data, write_data, cp_size);
temp_fifo->fifo_block[temp_fifo->fifo_tail].length = cp_size;
#if 1
if (temp_fifo->block_num == 0) {
//printf("[%s]%d new data: %d!!!\n", __func__, __LINE__, os_sem_query(temp_fifo->fifo_sem));
gx_os_sem_post(temp_fifo->fifo_sem);
}
#endif
temp_fifo->block_num++;
// gx_os_sem_post(temp_fifo->fifo_sem);
gx_os_mutex_unlock(temp_fifo->fifo_mutex);
return cp_size;
}
int gx_fifo_read(fifo_handle_t fifo, char *read_data, int read_size, int timeout)
{
GxFIFO *temp_fifo = (GxFIFO *)fifo;
int cp_size = 0;
if ((temp_fifo == NULL) || (read_data == NULL) || (read_size == 0)) {
return 0;
}
#if 0
int ret = gx_os_sem_wait(temp_fifo->fifo_sem, timeout);
if (ret != 0) {
printf("[%s]%d: wait data timeout: %d !!!!!!!\n", __func__, __LINE__, ret);
return 0;
}
#endif
gx_os_mutex_lock(temp_fifo->fifo_mutex, 0);
while (temp_fifo->block_num == 0) {
//printf("[%s]%d: fifo empty: %d!!!\n", __func__, __LINE__, gx_os_sem_query(temp_fifo->fifo_sem));
gx_os_mutex_unlock(temp_fifo->fifo_mutex);
if (gx_os_sem_wait(temp_fifo->fifo_sem, timeout) != 0) {
printf("[%s]%d: wait data timeout !!!!!!!\n", __func__, __LINE__);
return 0;
}
//os_sem_pend(&temp_fifo->fifo_sem, 0);
//os_mutex_pend(&temp_fifo->fifo_mutex, 0);
gx_os_mutex_lock(temp_fifo->fifo_mutex, 0);
//printf("[%s]%d, fifo has data: %d!!!\n", __func__, __LINE__, os_sem_query(&temp_fifo->fifo_sem));
//return 0;
}
(read_size >= temp_fifo->fifo_block[temp_fifo->fifo_head].length)
? (cp_size = temp_fifo->fifo_block[temp_fifo->fifo_head].length) : (cp_size = read_size);
memcpy(read_data, temp_fifo->fifo_block[temp_fifo->fifo_head].data, cp_size);
read_size = temp_fifo->fifo_block[temp_fifo->fifo_head].length;
temp_fifo->fifo_head++;
if (temp_fifo->fifo_head >= temp_fifo->block_total) {
temp_fifo->fifo_head = 0;
}
temp_fifo->block_num--;
gx_os_mutex_unlock(temp_fifo->fifo_mutex);
return cp_size;
}

View File

@ -0,0 +1,10 @@
#ifndef __GX_FIFO_H__
#define __GX_FIFO_H__
typedef int fifo_handle_t;
fifo_handle_t gx_fifo_create(int block_size, int block_num);
int gx_fifo_destroy(fifo_handle_t fifo);
int gx_fifo_write(fifo_handle_t fifo, const char *write_data, int write_size);
int gx_fifo_read(fifo_handle_t fifo, char *read_data, int read_size, int timeout);
#endif

View File

@ -0,0 +1,249 @@
#include "includes.h"
#include "../gx_uart_upgrade.h"
#include "../../gx8002_npu_api.h"
#include "../gx_uart_upgrade_porting.h"
#include "btstack/avctp_user.h"
#include "classic/hci_lmp.h"
#include "gx_fifo.h"
#if GX8002_UPGRADE_SPP_TOGGLE
#define spp_upgrade_info g_printf
//=============== SPP Porting ================//
int gx8002_ota_recv(unsigned char *data, int size);
static void gx8002_spp_data_handler(u8 packet_type, u16 ch, u8 *packet, u16 size)
{
switch (packet_type) {
case 1:
/* cbuf_init(&spp_buf_hdl, spp_buf, sizeof(spp_buf)); */
/* spp_timer = sys_timer_add(NULL, spp_send_data_timer, 50); */
/* spp_printf("spp connect\n"); */
spp_upgrade_info("gx8002 spp connect\n");
break;
case 2:
spp_upgrade_info("gx8002 spp disconnect\n");
/* if (spp_timer) { */
/* sys_timer_del(spp_timer); */
/* spp_timer = 0; */
/* } */
break;
case 7:
//spp_upgrade_info("gx8002 spp_rx: %d", size);
//put_buf(packet,size);
gx8002_ota_recv(packet, size);
break;
}
}
static void gx8002_spp_send_data(u8 *data, u32 size)
{
user_send_cmd_prepare(USER_CTRL_SPP_SEND_DATA, size, data);
}
void gx8002_spp_ota_init(void)
{
spp_data_deal_handle_register(gx8002_spp_data_handler);
}
////////////// FW Stream Porting //////////////////
#define STREAM_FIFO_BLOCK_TOTAL 16
#define STREAM_FIFO_TIMEOUT_MS (5000 / 10)
/* typedef int (*reply)(unsigned char *data, int size); */
static int ota_start = 0;
//static os_sem_t ota_sem;
static fifo_handle_t fw_fifo;
static int gx8002_ota_start(void)
{
if (!ota_start) {
os_taskq_post_msg("gx8002", 2, GX8002_MSG_UPDATE, GX8002_UPDATE_TYPE_SPP);
}
return 0;
}
int get_gx8002_ota_start(void)
{
return ota_start;
}
int gx8002_ota_recv(unsigned char *data, int size)
{
int i;
if ((data == NULL) || (size == 0)) {
return -1;
}
if (strncmp((char *)data, "startupgrade", strlen("startupgrade")) == 0) {
gx8002_ota_start();
} else {
if (ota_start) {
if (fw_fifo > 0) {
int cnt = size / UPGRADE_PACKET_SIZE;
int i;
for (i = 0; i < cnt; i++) {
gx_fifo_write(fw_fifo, (const char *)&data[UPGRADE_PACKET_SIZE * i], UPGRADE_PACKET_SIZE);
}
if (size % UPGRADE_PACKET_SIZE) {
gx_fifo_write(fw_fifo, (const char *)&data[UPGRADE_PACKET_SIZE * i], size % UPGRADE_PACKET_SIZE);
}
}
}
}
return 0;
}
static int fw_stream_open(FW_IMAGE_TYPE img_type)
{
if (fw_fifo == 0) {
if ((fw_fifo = gx_fifo_create(UPGRADE_PACKET_SIZE, STREAM_FIFO_BLOCK_TOTAL)) == 0) {
return -1;
}
}
return 0;
}
static int fw_stream_close(FW_IMAGE_TYPE img_type)
{
int ret = 0;
if (fw_fifo > 0) {
ret = gx_fifo_destroy(fw_fifo);
fw_fifo = 0;
}
return ret;
}
static int fw_stream_read(FW_IMAGE_TYPE img_type, unsigned char *buf, unsigned int len)
{
int ret = 0;
if (fw_fifo > 0) {
ret = gx_fifo_read(fw_fifo, (char *)buf, len, STREAM_FIFO_TIMEOUT_MS);
}
return ret;
}
static int fw_stream_get_flash_img_info(flash_img_info_t *info)
{
unsigned int size = 0;
if (info == NULL) {
return -1;
}
if (fw_fifo == 0) {
return -1;
}
int ret = gx_fifo_read(fw_fifo, (char *)info, sizeof(flash_img_info_t), STREAM_FIFO_TIMEOUT_MS);
return 0;
}
///////// status info /////////////
static const char *status_info_str[UPGRADE_STAGE_NONE][UPGRADE_STATUS_NONE] = {
// UPGRADE_STAGE_HANDSHAKE
{"handshake start\n", NULL, "handshake ok\n", "handshake err\n"},
// UPGRADE_STAGE_BOOT_HEADER
{"boot header start\n", NULL, "boot header ok\n", "boot header err\n"},
// UPGRADE_STAGE_BOOT_S1
{"boot stage1 start\n", "boot stage1 downloading\n", "boot stage1 ok\n", "boot stage1 err\n"},
// UPGRADE_STAGE_BOOT_S2
{"boot stage2 start\n", "boot stage2 downloading\n", "boot stage2 ok\n", "boot stage2 err\n"},
// UPGRADE_STAGE_FLASH_IMG
{"flash img start\n", "flash img downloading\n", "flash img ok\n", "flash img err\n"},
};
static void gx8002_upgrade_status_cb(upgrade_stage_e stage, upgrade_status_e status)
{
//printf("---- [%s]: stage: %d, status: %d ----\n", __func__, stage, status);
const char *reply_str = status_info_str[stage][status];
if (reply_str != NULL) {
spp_upgrade_info("status info: %s\n", reply_str);
//user_spp_send_data((unsigned char *)reply_str, strlen(reply_str));
gx8002_spp_send_data((u8 *)reply_str, strlen(reply_str));
}
}
static int gx8002_upgrade_task(void *param)
{
int ret = 0;
spp_upgrade_info("---- gx8002 ota start ----");
gx8002_upgrade_cold_reset();
ret = gx_uart_upgrade_proc();
gx8002_normal_cold_reset();
spp_upgrade_info("---- gx8002 ota over ----");
ota_start = 0;
if (ret < 0) {
gx8002_update_end_post_msg(0);
} else {
gx8002_update_end_post_msg(1);
}
return ret;
}
int gx8002_uart_spp_ota_init(void)
{
upgrade_uart_t uart_ops;
fw_stream_t fw_stream_ops;
uart_ops.open = gx_upgrade_uart_porting_open;
uart_ops.close = gx_upgrade_uart_porting_close;
uart_ops.send = gx_upgrade_uart_porting_write;
uart_ops.wait_reply = gx_uart_upgrade_porting_wait_reply;
fw_stream_ops.open = fw_stream_open;
fw_stream_ops.close = fw_stream_close;
fw_stream_ops.read = fw_stream_read;
fw_stream_ops.get_flash_img_info = fw_stream_get_flash_img_info;
gx_uart_upgrade_init(&uart_ops, &fw_stream_ops, gx8002_upgrade_status_cb);
ota_start = 1;
gx8002_upgrade_task(NULL);
return 0;
}
#else /* #if GX8002_UPGRADE_SPP_TOGGLE */
int gx8002_uart_spp_ota_init(void)
{
return 0;
}
int get_gx8002_ota_start(void)
{
return 0;
}
int gx8002_ota_recv(unsigned char *data, int size)
{
return 0;
}
#endif /* #if GX8002_UPGRADE_SPP_TOGGLE */