mcu_ab568x/app/platform/bsp/bsp_ble/bt_fota.c
2025-05-30 18:03:10 +08:00

570 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "include.h"
#include "bt_fota.h"
#if FOT_EN
#define FOT_DEBUG_EN 0
#if FOT_DEBUG_EN
#define FOT_DEBUG(...) printf(__VA_ARGS__)
#define FOT_DEBUG_R(...) print_r(__VA_ARGS__)
#else
#define FOT_DEBUG(...)
#define FOT_DEBUG_R(...)
#endif
/**********************************************/
#define FOT_STA_INIT BIT(0)
#define FOT_STA_START BIT(1)
#define FOT_STA_PAUSE BIT(2)
/**********************************************/
#define FOT_FLAG_UPDATE_OK BIT(0)
#define FOT_FLAG_SYS_RESET BIT(1)
#define FOT_FLAG_ROLE_SWITCH BIT(2)
#define FOT_FLAG_APP_CONNECT BIT(3)
#define FOT_FLAG_CLK_SET BIT(4)
#define FOT_FLAG_UPDATE_EXIT BIT(5)
/**********************************************/
#define FOT_NOTIFY_STA 0x90
#define FOT_GET_INFO 0x91
#define FOT_GET_INFO_TLV 0x92
#define FOT_OUT_DATA_START 0xA0
#define FOT_OUT_DATA_CONTINUE 0x20
/**********************************************/
#define FOT_CMD_POS 0
#define FOT_SEQ_POS 1
#define FOT_ADDR_POS 2
#define FOT_DATA_LEN_POS 6
#define DATA_START_POS 10
#define DATA_CONTINUE_POS 2
/**********************************************/
#define FOT_BLOCK_LEN 1024 //压缩升级必须是512的倍数目前只做了512倍数的处理
extern bool ble_fot_send_packet(u8 *buf, u16 len);
extern u16 get_spp_mtu_size(void);
u16 dev_version = 0x0001; //设备版本号
AT(.com_text.const)
static const u8 fot_auth_data[] = {0xCC, 0xAA, 0x55, 0xEE, 0x12, 0x19, 0xE4};
typedef enum{
INFO_DEV_VER = 1,
INFO_UPDATE_REQ,
INFO_DEV_FEATURE,
INFO_DEV_CONNECT_STA,
INFO_EDR_ADDR,
INFO_DEV_CHANNEL,
}DEV_INFO_E;
typedef struct __attribute__((packed)){
u16 remote_ver;
u32 total_len;
u32 remain_len;
u32 hash;
u16 data_pos;
u8 fot_recv_ok;
u32 addr;
u32 tick;
u8 type;
u8 sys_clk;
}fot_s;
fot_s fot_var;
static u8 fot_data[FOT_BLOCK_LEN] AT(.fot_data.buf);
static u8 fot_seq = 0;
static u8 fot_remote_seq = 0;
static u8 fot_sta = 0;
static u8 fot_flag = 0;
static u16 fot_connect_sta = 0;
u8 is_fot_update_en(void)
{
return 1;
}
void app_fota_pack_write(void *buf, u32 len)
{
u32 total_use_len = 0;
while (len && (ota_pack_get_err() == FOT_ERR_OK)) {
ota_pack_write(buf + total_use_len);
len -= 512;
total_use_len += 512;
}
}
AT(.text.fot.cache)
void app_fota_write(void *buf, u32 addr, u32 len)
{
app_fota_pack_write(buf, len);
}
AT(.text.fot.cache)
u8 app_fota_get_err(void)
{
return ota_pack_get_err();
}
AT(.text.fot.cache)
void app_fota_verify(void)
{
ota_pack_verify();
}
bool app_fota_breakpoint_info_read(void)
{
return ota_pack_breakpoint_info_read();
}
void app_fota_init(void)
{
ota_pack_init();
load_code_fota();
}
u32 app_fota_get_curaddr(void)
{
return ota_pack_get_curaddr();
}
void app_fota_update_done(void)
{
ota_pack_done();
}
bool app_fota_is_write_done(void)
{
return ota_pack_is_write_done();
}
AT(.text.fot.cache)
static void fot_sent_proc(u8 *buf,u8 len)
{
if((fot_flag & FOT_FLAG_APP_CONNECT) == 0){
return;
}
FOT_DEBUG("fot tx:");
FOT_DEBUG_R(buf,len);
#if FOT_EN
if(ble_is_connect()){
ble_fot_send_packet(buf,len);
}
#endif
}
AT(.text.fot.update)
static void fot_reply_info_tlv(u8 *buf,u8 len)
{
u8 read_offset = 0;
u8 write_offset = 0;
u8 rsp[32];
u8 val_len = 0;
if((buf == NULL) || (len == 0)){
return;
}
rsp[write_offset++] = FOT_GET_INFO_TLV;
rsp[write_offset++] = fot_seq++;
while(read_offset < len){
switch(buf[read_offset]){
case INFO_DEV_VER:
FOT_DEBUG("INFO_DEV_VER\n");
val_len = buf[read_offset + 1];
rsp[write_offset++] = INFO_DEV_VER;
rsp[write_offset++] = 2;
rsp[write_offset++] = dev_version & 0xff;
rsp[write_offset++] = (dev_version >> 8) & 0xff;
break;
case INFO_DEV_FEATURE:
FOT_DEBUG("INFO_DEV_FEATURE\n");
{
u16 dev_ability = 0;
val_len = buf[read_offset + 1];
rsp[write_offset++] = INFO_DEV_FEATURE;
rsp[write_offset++] = 2;
rsp[write_offset++] = dev_ability & 0xff;
rsp[write_offset++] = (dev_ability >> 8) & 0xff;
}
break;
case INFO_DEV_CONNECT_STA:
FOT_DEBUG("INFO_DEV_CONNECT_STA\n");
val_len = buf[read_offset + 1];
rsp[write_offset++] = INFO_DEV_CONNECT_STA;
rsp[write_offset++] = 2;
rsp[write_offset++] = fot_connect_sta & 0xff;
rsp[write_offset++] = (fot_connect_sta >> 8) & 0xff;
break;
default:
val_len = buf[read_offset + 1];
break;
}
read_offset += (2 + val_len);
}
if(write_offset > sizeof(rsp)){
FOT_DEBUG("fot:rsp buf overflow!!!\n");
while(1);
}
fot_sent_proc(rsp,write_offset);
}
AT(.text.fot.update)
static void fot_reply_dev_version(void)
{
u8 data[5];
data[0] = FOT_GET_INFO;
data[1] = fot_seq++;
data[2] = INFO_DEV_VER;
memcpy(&data[3],&dev_version,2);
fot_sent_proc(data,5);
}
AT(.text.fot.cache)
static void fot_dev_notify_sta(u8 sta)
{
u8 buf[3];
buf[0] = FOT_NOTIFY_STA;
buf[1] = fot_seq++;
buf[2] = sta;
fot_sent_proc(buf,3);
}
AT(.text.fot.update)
u8 is_fot_start(void)
{
return (fot_sta & FOT_STA_START) ? 1:0;
}
AT(.text.fot.update)
void bsp_fot_init(void)
{
u8 dev_version_str[] = SW_VERSION;
u16 version_temp = 0;
memset(&fot_var,0,sizeof(fot_var));
dev_version = 0x00;
version_temp = dev_version_str[1]-'0';
version_temp <<= 12;
dev_version |= version_temp;
version_temp = dev_version_str[3]-'0';
version_temp <<= 8;
dev_version |= version_temp;
version_temp = dev_version_str[5]-'0';
version_temp <<= 4;
dev_version |= version_temp;
fot_sta = FOT_STA_INIT;
}
void bsp_fot_exit(void)
{
fot_sta = 0;
fot_seq = 0;
fot_remote_seq = 0;
fot_flag &= ~FOT_FLAG_APP_CONNECT;
if(fot_var.sys_clk){
sys_clk_set(fot_var.sys_clk);
}
unlock_code_fota();
}
void fot_update_pause(void)
{
if(fot_sta & FOT_STA_START){
fot_sta = FOT_STA_PAUSE;
fot_dev_notify_sta(FOT_UPDATE_PAUSE);
}
}
void fot_update_continue(void)
{
if(fot_sta & FOT_STA_PAUSE){
bsp_fot_init();
fot_dev_notify_sta(FOT_UPDATE_CONTINUE);
}
}
u16 bsp_fot_mtu_get(void)
{
u16 packet_len = 0;
#if FOT_EN
if(ble_is_connect()){
packet_len = ble_get_gatt_mtu();
}
#endif
return packet_len;
}
AT(.text.fot.update)
static void fot_reply_update_request(void)
{
u16 flash_remote_ver;
u32 hash;
u32 addr = 0;
u32 block_len = FOT_BLOCK_LEN;
u16 packet_len = 0;
u8 data[14];
u8 need_update = 1;
if(bt_get_status() >= BT_STA_INCOMING){
need_update = 0;
fot_flag |= FOT_FLAG_UPDATE_EXIT;
goto fot_req_reply;
}
#if FOT_EN
if(ble_is_connect()){
ble_update_conn_param(16,0,400);
}
#endif
packet_len = bsp_fot_mtu_get();
FOT_DEBUG("fot_packet_len:%d\n",packet_len);
app_fota_init();
fot_flag |= FOT_FLAG_CLK_SET;
fot_sta |= FOT_STA_START;
FOT_DEBUG("hash_val:0x%x\n",fot_var.hash);
param_fot_remote_ver_read((u8*)&flash_remote_ver);
param_fot_hash_read((u8*)&hash);
FOT_DEBUG("flash hash val:0x%x\n",hash);
if((fot_var.hash != 0xFFFFFFFF) && (flash_remote_ver == fot_var.remote_ver) && (hash == fot_var.hash)){
param_fot_type_read(&fot_var.type);
if(app_fota_breakpoint_info_read() == true){
addr = app_fota_get_curaddr();
}
}
fot_req_reply:
data[0] = FOT_GET_INFO;
data[1] = fot_seq++;
data[2] = INFO_UPDATE_REQ;
memcpy(&data[3],&addr,4);
memcpy(&data[7],&block_len,4);
memcpy(&data[11],&packet_len,2);
data[13] = need_update;
fot_sent_proc(data,14);
}
#if FOT_EN
void fot_ble_disconnect_callback(void)
{
FOT_DEBUG("--->fot_ble_disconnect_callback\n");
bsp_fot_exit();
}
void fot_ble_connect_callback(void)
{
FOT_DEBUG("--->fot_ble_connect_callback\n");
}
#endif
void fot_spp_connect_callback(void)
{
FOT_DEBUG("--->fot_spp_connect_callback\n");
}
void fot_spp_disconnect_callback(void)
{
FOT_DEBUG("--->fot_spp_disconnect_callback\n");
bsp_fot_exit();
}
AT(.text.fot.cache)
void fot_recv_proc(u8 *buf, u16 len)
{
u32 addr;
u32 recv_data_len;
u8 cmd;
if(fot_remote_seq != buf[FOT_SEQ_POS]){
if(memcmp(fot_auth_data, buf, 7)){ //接入码先过掉
FOT_DEBUG("remote seq err:%d,%d\n",fot_remote_seq,buf[FOT_SEQ_POS]);
fot_dev_notify_sta(FOT_ERR_SEQ);
fot_flag |= FOT_FLAG_UPDATE_EXIT;
}
return;
}
fot_remote_seq++;
if((fot_sta & FOT_STA_INIT) == 0){
return;
}
cmd = buf[FOT_CMD_POS];
switch(cmd){
case FOT_GET_INFO_TLV:
fot_reply_info_tlv(&buf[2],len-2);
break;
case FOT_GET_INFO:
if(buf[2] == INFO_DEV_VER){
fot_reply_dev_version();
}else if(buf[2] == INFO_UPDATE_REQ){
memcpy(&fot_var.remote_ver,&buf[3],2);
memcpy(&fot_var.hash,&buf[5],4);
fot_reply_update_request();
}
break;
case FOT_OUT_DATA_START:
if(fot_var.remain_len){
FOT_DEBUG("--->len err:%d\n",fot_var.remain_len);
fot_dev_notify_sta(FOT_ERR_DATA_LEN);
fot_flag |= FOT_FLAG_UPDATE_EXIT;
return;
}
recv_data_len = len-DATA_START_POS;
memcpy(&fot_var.total_len,&buf[FOT_DATA_LEN_POS],4);
fot_var.remain_len = fot_var.total_len - recv_data_len;
memcpy(&addr,&buf[FOT_ADDR_POS],4);
memcpy(&fot_data[fot_var.data_pos],&buf[DATA_START_POS],recv_data_len);
fot_var.data_pos += recv_data_len;
if(fot_var.remain_len == 0){
fot_var.fot_recv_ok = 1;
fot_var.data_pos = 0;
}
break;
case FOT_OUT_DATA_CONTINUE:
recv_data_len = len-DATA_CONTINUE_POS;
if(fot_var.remain_len < recv_data_len){
recv_data_len = fot_var.remain_len;
}
fot_var.remain_len -= recv_data_len;
memcpy(&fot_data[fot_var.data_pos],&buf[DATA_CONTINUE_POS],recv_data_len);
fot_var.data_pos += recv_data_len;
if(fot_var.remain_len == 0){
fot_var.fot_recv_ok = 1;
fot_var.data_pos = 0;
}
break;
}
}
AT(.text.fot.cache)
void bsp_fot_process(void)
{
if(fot_sta & FOT_STA_START){
if(fot_var.fot_recv_ok){
fot_var.fot_recv_ok = 0;
app_fota_write(fot_data, app_fota_get_curaddr(), fot_var.total_len);
if(app_fota_is_write_done()){
app_fota_verify();
if(app_fota_get_err()){
fot_dev_notify_sta(app_fota_get_err());
fot_flag |= FOT_FLAG_UPDATE_EXIT;
}else{
FOT_DEBUG("--->fot update success\n");
app_fota_update_done();
fot_flag |= (FOT_FLAG_UPDATE_OK | FOT_FLAG_SYS_RESET);
fot_var.tick = tick_get();
fot_dev_notify_sta(FOT_UPDATE_DONE);
}
}else{
fot_dev_notify_sta(app_fota_get_err());
if(app_fota_get_err()){
fot_flag |= FOT_FLAG_UPDATE_EXIT;
}
}
}
}
if(fot_flag & FOT_FLAG_SYS_RESET){
if(tick_check_expire(fot_var.tick,3000)){
fot_flag &= ~FOT_FLAG_SYS_RESET;
FOT_DEBUG("-->fota update ok,sys reset\n");
WDT_RST();
}
}
if(fot_flag & FOT_FLAG_CLK_SET){
FOT_DEBUG("--->FOT_FLAG_CLK_SET\n");
fot_var.sys_clk = sys_clk_get_cur();
//主时钟192M切换132M会复位
if (fot_var.sys_clk < SYS_192M) {
sys_clk_set(SYS_132M);
}
fot_flag &= ~FOT_FLAG_CLK_SET;
}
if(fot_flag & FOT_FLAG_UPDATE_EXIT){
FOT_DEBUG("-->FOT_FLAG_UPDATE_EXIT");
bsp_fot_exit();
fot_flag &= ~FOT_FLAG_UPDATE_EXIT;
}
}
AT(.com_text.fot)
u8 fot_app_connect_auth(uint8_t *packet, uint16_t size)
{
if(!fot_sta){
if(size == 7 && !memcmp(fot_auth_data, packet, 7)){ //sizeof(fot_auth_data)
fot_flag |= FOT_FLAG_APP_CONNECT;
bsp_fot_init();
}
}
return fot_sta;
}
AT(.com_text.fot)
bool bsp_fot_is_connect(void)
{
return (fot_sta>0);
}
#else
WEAK void fot_update_pause(void)
{
}
WEAK void fot_update_continue(void)
{
}
#endif //FOT_EN