mcu_hi3321_watch/tjd/ble/protocol/ble_ota_server.c
2025-05-26 20:15:20 +08:00

495 lines
17 KiB
C
Raw Permalink 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 "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "am_util_debug.h"
#include "amotas_api.h"
#include "sys_config.h"
#include "ble_ota_execute.h"
#include "ble_data_transmission.h"
#include "ble_ota_server.h"
#include "ble_management_server.h"
#include "task_ble.h"
//#include "task_ui.h"
#define ENABLE_STATIC_PRINT false
extern uint32_t am_util_stdio_printf(const char *pcFmt, ...);
#define static_print_remind(...) am_util_stdio_printf(__VA_ARGS__)
#if ENABLE_STATIC_PRINT
#define static_print_info(...) am_util_stdio_printf(__VA_ARGS__)
#else
#define static_print_info(...)
#endif
#define VERIFY_SUCCESS 0
#define VERIFY_FAIL 1
#define APP_STARTOTA 0
#define DEVICE_STARTOTA 1
/*----------------------------------------------*
* 模块级变量 *
*----------------------------------------------*/
ota_fw_info_t g_ota_fw_info; // 固件实时信息
extern void close_low_power_conn_timer(void);
extern void amotas_send_data(uint8_t *buf, uint16_t len);
extern void user_update_percent_show(uint8_t percent);
void DeviceRequestOTAFileData(uint32_t offset,uint16_t DataLen,uint32_t TotalFileSise,uint32_t ReceivedFileSize);
void DeviceNoticeOTAFileReceivedSuccess(void);
void DeviceNoticeOTAProcessUpdate(uint8_t FileVerifyResult,uint8_t OTAStartMode);
void DeviceOTAErrReport(uint16_t OtaErrorResult);
/*****************************************************************************
4.12.1 询问是否可以进入OTA 模式
*****************************************************************************/
void UserCheckIFOtaMode(uint8_t *in_data,uint16_t in_len,uint8_t *out_data,uint16_t *out_len)
{
uint16_t CurrentMTUSize;
uint16_t write_idx = 0;
uint8_t otaStatus = 1;
protocol_data_info_t data_info = {0};
if(OtaIsStarted())
return;
data_info.error = FENDA_SUCCESS;
do
{
user_get_data_info(&data_info,&in_data,&in_len);
switch((data_info.type & 0x7F))
{
case PackageVersionType:
if(data_info.len <= FILE_NAME_LENGTH_MAX)
{
memcpy(g_ota_fw_info.OtaFileName, data_info.p_data, data_info.len);
static_print_remind("OTA Received PackageFileName:%s.\r\n",g_ota_fw_info.OtaFileName);
}
else
{
data_info.error = DEVICE_FW_OTA_ERROR;
}
break;
case FileLenghtType:
if(data_info.len==4)
{
g_ota_fw_info.OtaFlieLenFromAPP |= (*data_info.p_data++)<<24; // APP下发的固件数据长度
g_ota_fw_info.OtaFlieLenFromAPP |= (*data_info.p_data++)<<16;
g_ota_fw_info.OtaFlieLenFromAPP |= (*data_info.p_data++)<<8;
g_ota_fw_info.OtaFlieLenFromAPP |= *data_info.p_data++;
static_print_remind("OTA Received File Length:%x.\r\n",g_ota_fw_info.OtaFlieLenFromAPP);
}
break;
case OtaModelType:
if(data_info.len==1)
{
g_ota_fw_info.OtaWorkMode = *data_info.p_data++;
if(g_ota_fw_info.OtaWorkMode)
{//只支持前台模式
data_info.error = DEVICE_FORBIT_OTA_ERROR;
}
}
break;
default:
// data_info.error=PARAM_ERROR;
// in_len=0;
break;
}
in_data+=(data_info.len);
in_len-=(2+data_info.len);
if(in_len>FRAM_MAX_SIZ)
{
in_len=0;
}
}
while(in_len);
otaStatus = OtaRequest(g_ota_fw_info.OtaFlieLenFromAPP);
if(data_info.error)
{
write_idx=user_set_protocol_error(out_data,OTA_SERVER,data_info.error);
}
else
{
out_data[write_idx++]=3;
out_data[write_idx++]=OtaStatusType;
out_data[write_idx++]=otaStatus;
out_data[write_idx++]=3;
out_data[write_idx++]=BatteryThresholdType;
out_data[write_idx++]=OTA_BATT_THRESHOLD;
out_data[write_idx++]=4;
out_data[write_idx++]=AppWaitTimeOutType;
out_data[write_idx++]=APP_WAIT_TIME_MAX/0x100;
out_data[write_idx++]=APP_WAIT_TIME_MAX%0x100;
out_data[write_idx++]=4;
out_data[write_idx++]=OtaMTUSizeType;
CurrentMTUSize = user_app_mtu_get();
out_data[write_idx++]=CurrentMTUSize/0x100;
out_data[write_idx++]=CurrentMTUSize%0x100;
}
*out_len=write_idx;
}
/*****************************************************************************
4.12.2 APP 通知设备升级状态
*****************************************************************************/
void UserNoticOtaStatus(uint8_t *in_data,uint16_t in_len,uint8_t *out_data,uint16_t *out_len)
{
uint16_t write_idx=0;
protocol_data_info_t data_info = {0};
OtaTimeoutReset();
if(in_len)
{
do
{
user_get_data_info(&data_info,&in_data,&in_len);
switch((data_info.type & 0x7F))
{
case AppOtaStatusType:
g_ota_fw_info.AppOtaStatus = *data_info.p_data;
break;
default:
// data_info.error=PARAM_ERROR;
// in_len=0;
break;
}
in_data= data_info.p_data;
in_data+=(data_info.len);
in_len-=(2+data_info.len);
if(in_len>FRAM_MAX_SIZ)
{
in_len=0;
}
}
while(in_len);
}
if((g_ota_fw_info.AppOtaStatus==0) && (g_ota_fw_info.DeviceOtaStatus==0))
{
//开始正式升级
static_print_remind("OTA start\n");
OtaStart();
close_low_power_conn_timer();
change_ble_task_priority();
amota_conn_param_update(CONN_PARAM_OTA); // 使用OTA连接参数
/* 由于此时还未申请固件信息使用APP下发的固件数据长度 */
DeviceRequestOTAFileData(0, FW_HEAD_INFO_IEN, g_ota_fw_info.OtaFlieLenFromAPP, 0);
}
*out_len=write_idx;
}
/*****************************************************************************
4.12.3 设备根据文件信息分帧请求文件内容
*****************************************************************************/
void DeviceRequestOTAFileData(uint32_t offset,uint16_t DataLen,uint32_t TotalFileSise,uint32_t ReceivedFileSize)
{
Ltv_t ltvArray[4] = {0};
FrameInfo_t frameInfo;
ltvArray[0].len = 6;
ltvArray[0].type = OtaFileOffsetType;
ltvArray[0].value = offset;
ltvArray[1].len = 4;
ltvArray[1].type = OtaRequestDataLenType;
ltvArray[1].value = DataLen;
ltvArray[2].len = 6;
ltvArray[2].type = OtaTotalFileSizeType;
ltvArray[2].value = TotalFileSise;
ltvArray[3].len = 6;
ltvArray[3].type = OtaReceivedFileLenType;
ltvArray[3].value = ReceivedFileSize;
frameInfo.serviceId = OTA_SERVER;
frameInfo.commandId = RequestOTAFileDataID;
frameInfo.frameType.value = 0;
BLE_SendLtvArray(&frameInfo, ltvArray, 4);
// uint16_t write_idx = 0;
// uint8_t buf_temp[30] = {0};
// uint32_t Value32;
// buf_temp[write_idx++] = 0x06;
// buf_temp[write_idx++] = OtaFileOffsetType;
// buf_temp[write_idx++] = offset/0x1000000;
// Value32 =offset%0x1000000;
// buf_temp[write_idx++] = Value32/0x10000;
// Value32 =offset%0x10000;
// buf_temp[write_idx++] = Value32/0x100;
// buf_temp[write_idx++] = offset%0x100;
// buf_temp[write_idx++] = 0x04;
// buf_temp[write_idx++] = OtaRequestDataLenType;
// buf_temp[write_idx++] = DataLen/0x100;
// buf_temp[write_idx++] = DataLen%0x100;
// buf_temp[write_idx++] = 0x06;
// buf_temp[write_idx++] = OtaTotalFileSizeType;
// buf_temp[write_idx++] = TotalFileSise/0x1000000;
// Value32 =TotalFileSise%0x1000000;
// buf_temp[write_idx++] = Value32/0x10000;
// Value32 =TotalFileSise%0x10000;
// buf_temp[write_idx++] = Value32/0x100;
// buf_temp[write_idx++] = TotalFileSise%0x100;
// buf_temp[write_idx++] = 0x06;
// buf_temp[write_idx++] = OtaReceivedFileLenType;
// buf_temp[write_idx++] = ReceivedFileSize/0x1000000;
// Value32 =ReceivedFileSize%0x1000000;
// buf_temp[write_idx++] = Value32/0x10000;
// Value32 =ReceivedFileSize%0x10000;
// buf_temp[write_idx++] = Value32/0x100;
// buf_temp[write_idx++] = ReceivedFileSize%0x100;
// BLE_SendFrameById(OTA_SERVER,RequestOTAFileDataID,buf_temp,write_idx);
}
/*****************************************************************************
4.12.4 APP 根据设备的分帧请求返回文件内容
*****************************************************************************/
void UserReceiveOTAFileData(uint8_t *in_data,uint16_t in_len,uint8_t *out_data,uint16_t *out_len)
{
uint16_t write_idx=0;
protocol_data_info_t data_info = {0};
OtaCtrlBlock_t ctrlBlock;
uint32_t rcvFileOffset;
uint16_t dataLen = in_len;
static uint8_t otaProtocolVersion = 0;
if(!OtaIsStarted())
return;
OtaTimeoutReset();
rcvFileOffset = ((uint32_t)in_data[0] << 24) + \
((uint32_t)in_data[1] << 16) + \
((uint32_t)in_data[2] << 8) + \
((uint32_t)in_data[3]);
static_print_info("in_len=%d,rcvFileOffset=%d,pkt.offset=%d,pkt.FileSize=%d\n",in_len,rcvFileOffset,ctrlBlock.pkt.offset,ctrlBlock.pkt.FileSize);
GetOtaCtrlBlock(&ctrlBlock);
if(ctrlBlock.pkt.offset== 0) {
if(in_len == 4 + FW_HEAD_INFO_IEN) {
otaProtocolVersion = 1; //V0.0.2.9协议,新增文件偏移
} else {
otaProtocolVersion = 0; //老协议,纯数据
}
static_print_info("otaProtocolVersion=%d\r\n", otaProtocolVersion);
}
if(otaProtocolVersion > 0) {
// OtaFrameResendTimerLoad(); // 目前不使用超时未收到数据再次请求机制
if(rcvFileOffset != ctrlBlock.pkt.offset) {
static_print_remind("rcvFileOffset=0x%x,ctrlBlock.offset=0x%x\r\n", rcvFileOffset, ctrlBlock.pkt.offset);
return;
}
in_data += 4;
dataLen = in_len - 4;
}
// 为提高OTA速度提前申请固件数据再将数据写入Flash
if(ctrlBlock.ota_status == OTA_STATE_FW_DATA)
{
ctrlBlock.pkt.offset += dataLen;
if(ctrlBlock.pkt.FileSize > ctrlBlock.pkt.offset)
{
ctrlBlock.pkt.ApplyLen = ctrlBlock.pkt.FileSize - ctrlBlock.pkt.offset;
ctrlBlock.pkt.ApplyLen = ctrlBlock.pkt.ApplyLen > APPLY_FW_DATA_LEN ? APPLY_FW_DATA_LEN : ctrlBlock.pkt.ApplyLen;
DeviceRequestOTAFileData(ctrlBlock.pkt.offset, ctrlBlock.pkt.ApplyLen,
ctrlBlock.pkt.FileSize, ctrlBlock.pkt.offset);
}
}
data_info.error = OtaPacketHandler(dataLen, in_data);
if(data_info.error != FENDA_SUCCESS)
{
DeviceOTAErrReport(data_info.error);
OtaFailed(data_info.error);
}
else
{
GetOtaCtrlBlock(&ctrlBlock);
// if(ctrlBlock.ota_status == OTA_STATE_FW_DATA)
// {
// if(otaProtocolVersion > 0)
// {
// //OtaFrameResendTimerLoad();
// }
// //static_print_info("\n ApplyLen = %x, offset = %x, FileSize = %x \n",
// // ctrlBlock.pkt.ApplyLen,ctrlBlock.pkt.offset, ctrlBlock.pkt.FileSize);
// DeviceRequestOTAFileData(ctrlBlock.pkt.offset, ctrlBlock.pkt.ApplyLen,
// ctrlBlock.pkt.FileSize, ctrlBlock.pkt.offset);
// }
// else if(ctrlBlock.ota_status == OTA_STATE_FW_RESET)
if(ctrlBlock.ota_status == OTA_STATE_FW_RESET)
{// 收完最后一包数据
DeviceNoticeOTAFileReceivedSuccess();
if(ctrlBlock.crc_verify)
{
static_print_remind("\n***** Verification succeeded. *****\n ");
DeviceNoticeOTAProcessUpdate(VERIFY_SUCCESS, DEVICE_STARTOTA);
OtaSucceed();
}
else
{
static_print_remind("\n***** Verification fail. *****\n ");
DeviceNoticeOTAProcessUpdate(VERIFY_FAIL, DEVICE_STARTOTA);
OtaFailed(DATA_CRC_OTA_ERROR);
}
}
}
*out_len=write_idx;
}
/*****************************************************************************
4.12.5 设备通知APP 升级包接收完
*****************************************************************************/
void DeviceNoticeOTAFileReceivedSuccess(void)
{
uint16_t write_idx = 0;
uint8_t buf_temp[2] = {0};
buf_temp[write_idx++] = 0x02;
buf_temp[write_idx++] = PkgValidityType;
BLE_SendFrameById(OTA_SERVER,NoticeReceiveOTAFileSuccessID,buf_temp,write_idx);
}
/*****************************************************************************
4.12.6 设备回复手机文件接收完毕校验并指定由谁开启OTA 流程
*****************************************************************************/
void DeviceNoticeOTAProcessUpdate(uint8_t FileVerifyResult,uint8_t OTAStartMode)
{
uint16_t write_idx = 0;
uint8_t buf_temp[6] = {0};
buf_temp[write_idx++] = 0x03;
buf_temp[write_idx++] = PkgValidityType;
buf_temp[write_idx++] = FileVerifyResult;
buf_temp[write_idx++] = 0x03;
buf_temp[write_idx++] = WhichStartOtaType;
buf_temp[write_idx++] = OTAStartMode;
BLE_SendFrameById(OTA_SERVER,NoticeOTAUpdateTypeID,buf_temp,write_idx);
}
/*****************************************************************************
4.12.6 APP回复设备升级完成。
事实上FD186 APP没有这一步操作我们是在4.12.4开启定时器重启)
*****************************************************************************/
void NoticeOTAUpdateResultACK(uint8_t *in_data,uint16_t in_len,uint8_t *out_data,uint16_t *out_len)
{
protocol_data_info_t data_info = {0};
do
{
user_get_data_info(&data_info,&in_data,&in_len);
switch((data_info.type & 0x7F))
{
case AppStartOtaType:
if(data_info.len==1)
{
if(*data_info.p_data)
{
static_print_remind("\n***** Verification succeeded. Device Reset*****\n ");
}
}
break;
default:
// data_info.error=PARAM_ERROR;
// in_len=0;
break;
}
in_data+=(data_info.len);
in_len-=(2+data_info.len);
if(in_len>FRAM_MAX_SIZ)
{
in_len=0;
}
}
while(in_len);
}
/*****************************************************************************
4.12.7 设备端OTA状态上报
*****************************************************************************/
void DeviceOTAErrReport(uint16_t OtaErrorResult)
{
uint16_t write_idx = 0;
uint8_t buf_temp[TEMP_NUM_MAX] = {0};
buf_temp[write_idx++] = 0x04;
buf_temp[write_idx++] = 0xff;
buf_temp[write_idx++] = OtaErrorResult / 0x100;
buf_temp[write_idx++] = OtaErrorResult % 0x100;
BLE_SendFrameById(OTA_SERVER, DeviceOTAErrReportID, buf_temp, write_idx);
}
void UserCancleOta(uint8_t *in_data,uint16_t in_len,uint8_t *out_data,uint16_t *out_len)
{
protocol_data_info_t data_info = {0};
if(!OtaIsStarted())
return;
static_print_info("UserCancleOta\n");
do
{
user_get_data_info(&data_info,&in_data,&in_len);
switch((data_info.type & 0x7F))
{
case CancelOtaType:
OtaFailed(USER_CANCEL_OTA);
break;
default:
// data_info.error=PARAM_ERROR;
// in_len=0;
break;
}
in_data+=(data_info.len);
in_len-=(2+data_info.len);
if(in_len>FRAM_MAX_SIZ)
{
in_len=0;
}
}
while(in_len);
}
const p_func_t user_Ota_server_func[Ota_server_max_ID]=
{
user_null_func,
UserCheckIFOtaMode, //4.12.1
UserNoticOtaStatus, //4.12.2
user_null_func, //4.12.3
UserReceiveOTAFileData, //4.12.4
user_null_func,
NoticeOTAUpdateResultACK, //5.9.6
user_null_func,//user_notify_ota_status, //5.9.7
UserCancleOta, //5.9.8
};