495 lines
17 KiB
C
495 lines
17 KiB
C
|
||
/*----------------------------------------------*
|
||
* 包含头文件 *
|
||
*----------------------------------------------*/
|
||
|
||
|
||
#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
|
||
};
|
||
|
||
|