first
This commit is contained in:
@ -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 */
|
||||
|
||||
@ -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) */
|
||||
|
||||
482
apps/common/device/gx8002_npu/gx8002_upgrade/gx_uart_upgrade.c
Normal file
482
apps/common/device/gx8002_npu/gx8002_upgrade/gx_uart_upgrade.c
Normal 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 */
|
||||
@ -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
|
||||
@ -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 */
|
||||
@ -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_ */
|
||||
@ -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
|
||||
@ -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 */
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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 */
|
||||
Reference in New Issue
Block a user