Merge pull request 'merge code' (#56) from xidatong-arm32 into jerryscript

This commit is contained in:
wgzAIIT 2023-09-20 16:11:36 +08:00
commit 0b1489cfed
15 changed files with 699 additions and 265 deletions

View File

@ -167,7 +167,7 @@ static int Ec200tIoctl(struct Adapter *adapter, int cmd, void *args)
serial_cfg.serial_timeout = OTA_RX_TIMEOUT;
#else
//serial receive timeout 10s
serial_cfg.serial_timeout = 100000;
serial_cfg.serial_timeout = 10000;
#endif
serial_cfg.is_ext_uart = 0;
#ifdef ADAPTER_EC200T_DRIVER_EXT_PORT

View File

@ -355,7 +355,7 @@ static int GetCompleteATReply(ATAgentType agent)
PrivMutexObtain(&agent->lock);
if (agent->receive_mode == ENTM_MODE) {
if (agent->entm_recv_len < ENTM_RECV_MAX) {
#ifdef TOOL_USING_MQTT
#ifdef LIB_USING_MQTT
if((res == 1) && (agent->entm_recv_len < agent->read_len))
{
agent->entm_recv_buf[agent->entm_recv_len] = ch;

View File

@ -29,7 +29,7 @@
#define REPLY_TIME_OUT 10
#ifdef TOOL_USING_OTA
#define ENTM_RECV_MAX OTA_RX_BUFFERSIZE
#define ENTM_RECV_MAX (OTA_FRAME_SIZE + 512)
#else
#define ENTM_RECV_MAX 256
#endif

View File

@ -18,8 +18,8 @@ ifeq ($(CONFIG_LIB_USING_LORAWAN),y)
SRC_DIR += lorawan
endif
ifeq ($(CONFIG_TOOL_USING_MQTT),y)
SRC_DIR += mqtt
ifeq ($(CONFIG_LIB_USING_MQTT),y)
SRC_DIR += mqtt
endif
ifeq ($(CONFIG_LIB_USING_JERRYSCRIPT),y)

View File

@ -1,33 +1,78 @@
menu "lib using MQTT"
menuconfig TOOL_USING_MQTT
menuconfig LIB_USING_MQTT
bool "Enable support MQTT function"
default n
select SUPPORT_CONNECTION_FRAMEWORK
select CONNECTION_ADAPTER_4G
if TOOL_USING_MQTT
menu "MQTT connection parameter configuration."
config PLATFORM_PRODUCTKEY
string "Product Key, used to identify a product."
default "iv74vebCdJC"
config CLIENT_DEVICENAME
string "Device name, used to identify a client device."
default "D001"
if LIB_USING_MQTT
choice
prompt "Choose xiuos platform or Alibaba Cloud platform."
default XIUOS_PLATFORM
config CLIENT_DEVICESECRET
string "Device secret, used for device authentication and data encryption."
default "d2e613c4f714b6b0774bd7b68eeceae3"
config PLATFORM_SERVERIP
string "mqtt platform server ip."
default "101.133.196.127"
config XIUOS_PLATFORM
bool "xiuos platform."
config PLATFORM_SERVERPORT
string "mqtt platform server port."
default "1883"
endmenu
config ALIBABA_PLATFORM
bool "Alibaba cloud platform."
endchoice
if XIUOS_PLATFORM
menu "xiuos platform mqtt connection parameter configuration."
config CLIENTID
string "mqtt client id."
default "D001"
config USERNAME
string "mqtt client username."
default "xiuosiot"
config PASSWORD
string "mqtt client login passwd."
default "xiuosiot"
config PLATFORM_SERVERIP
string "xiuos platform server ip."
default "115.238.53.59"
config PLATFORM_SERVERPORT
string "xiuos platform server port."
default "1883"
endmenu
menuconfig USING_DOWNLOAD_JSON
bool "Enable support download json file function"
default n
select BSP_USING_SDIO
select MOUNT_SDCARD_FS
select LIB_USING_CJSON
endif
if ALIBABA_PLATFORM
menu "Alibaba Cloud platform mqtt connection parameter configuration."
config PLATFORM_PRODUCTKEY
string "Product Key, used to identify a product."
default "iv74vebCdJC"
config CLIENT_DEVICENAME
string "Device name, used to identify a client device."
default "D001"
config CLIENT_DEVICESECRET
string "Device secret, used for device authentication and data encryption."
default "d2e613c4f714b6b0774bd7b68eeceae3"
config PLATFORM_SERVERIP
string "Alibaba Cloud platform server ip."
default "101.133.196.127"
config PLATFORM_SERVERPORT
string "Alibaba Cloud platform server port."
default "1883"
endmenu
endif
endif
endmenu

View File

@ -1,3 +1,9 @@
SRC_FILES := platform_mqtt.c utils_hmacsha1.c
ifeq ($(CONFIG_XIUOS_PLATFORM),y)
SRC_FILES := platform_mqtt.c
endif
ifeq ($(CONFIG_ALIBABA_PLATFORM),y)
SRC_FILES := platform_mqtt.c utils_hmacsha1.c
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -24,6 +24,7 @@
#include <adapter.h>
#include <transform.h>
#include "platform_mqtt.h"
#include "utils_hmacsha1.h"
MQTT_TCB Platform_mqtt; //创建一个用于连接云平台mqtt的结构体
static struct Adapter *adapter;
@ -105,19 +106,26 @@ int MQTT_Recv(uint8_t* buf, int buflen)
* : MQTT_Connect
* : MQTT服务器
* :
* : 0,1
* : true表示成功,false表示失
*******************************************************************************/
int MQTT_Connect(void)
bool MQTT_Connect(void)
{
uint8_t TryConnect_time = 10; //尝试登录次数
uint8_t passwdtemp[PASSWARD_SIZE];
memset(&Platform_mqtt,0,sizeof(Platform_mqtt));
sprintf(Platform_mqtt.ClientID,"%s|securemode=3,signmethod=hmacsha1|",CLIENT_DEVICENAME); //构建客户端ID并存入缓冲区
sprintf(Platform_mqtt.Username,"%s&%s",CLIENT_DEVICENAME,PLATFORM_PRODUCTKEY); //构建用户名并存入缓冲区
memset(passwdtemp,0,sizeof(passwdtemp));
sprintf(passwdtemp,"clientId%sdeviceName%sproductKey%s",CLIENT_DEVICENAME,CLIENT_DEVICENAME,PLATFORM_PRODUCTKEY); //构建加密时的明文
utils_hmac_sha1(passwdtemp,strlen(passwdtemp),Platform_mqtt.Passward,(char *)CLIENT_DEVICESECRET,strlen(CLIENT_DEVICESECRET)); //以DeviceSecret为秘钥对temp中的明文进行hmacsha1加密即为密码
memset(&Platform_mqtt,0,sizeof(Platform_mqtt));
#ifdef XIUOS_PLATFORM
sprintf(Platform_mqtt.ClientID,"%s",CLIENTID); //客户端ID存入缓冲区
sprintf(Platform_mqtt.Username,"%s",USERNAME); //用户名存入缓冲区
sprintf(Platform_mqtt.Passward,"%s",PASSWORD); //用户名存入缓冲区
#endif
#ifdef ALIBABA_PLATFORM
uint8_t passwdtemp[PASSWARD_SIZE];
memset(passwdtemp,0,sizeof(passwdtemp));
sprintf(Platform_mqtt.ClientID,"%s|securemode=3,signmethod=hmacsha1|",CLIENT_DEVICENAME); //构建客户端ID并存入缓冲区
sprintf(Platform_mqtt.Username,"%s&%s",CLIENT_DEVICENAME,PLATFORM_PRODUCTKEY); //构建用户名并存入缓冲区
sprintf(passwdtemp,"clientId%sdeviceName%sproductKey%s",CLIENT_DEVICENAME,CLIENT_DEVICENAME,PLATFORM_PRODUCTKEY); //构建加密时的明文
utils_hmac_sha1(passwdtemp,strlen(passwdtemp),Platform_mqtt.Passward,(char *)CLIENT_DEVICESECRET,strlen(CLIENT_DEVICESECRET)); //以DeviceSecret为秘钥对temp中的明文进行hmacsha1加密即为密码
#endif
Platform_mqtt.MessageID = 0; //报文标识符清零,CONNECT报文虽然不需要添加报文标识符,但是CONNECT报文是第一个发送的报文,在此清零报文标识符为后续报文做准备
Platform_mqtt.Fixed_len = 1; //CONNECT报文固定报头长度暂定为1
@ -126,7 +134,7 @@ int MQTT_Connect(void)
Platform_mqtt.Remaining_len = Platform_mqtt.Variable_len + Platform_mqtt.Payload_len; //剩余长度=可变报头长度+负载长度
memset(Platform_mqtt.Pack_buff,0,sizeof(Platform_mqtt.Pack_buff));
Platform_mqtt.Pack_buff[0] = 0x10; //CONNECT报文 固定报头第1个字节0x10
Platform_mqtt.Pack_buff[0] = 0x10; //CONNECT报文,固定报头第1个字节0x10
do{
if((Platform_mqtt.Remaining_len/128) == 0)
{
@ -172,11 +180,11 @@ int MQTT_Connect(void)
MQTT_Recv(mqtt_rxbuf, 4);
if(mqtt_rxbuf[0] == parket_connetAck[0] && mqtt_rxbuf[1] == parket_connetAck[1]) //连接成功
{
return 0;
return true;
}
TryConnect_time--;
}
return 1;
return false;
}
@ -196,9 +204,9 @@ void MQTT_Disconnect(void)
* : MQTT_SubscribeTopic
* : MQTT订阅单个主题
* : topic_name:
* : 0,1
* : true表示订阅成功,false表示订阅失
*******************************************************************************/
int MQTT_SubscribeTopic(uint8_t *topic_name)
bool MQTT_SubscribeTopic(uint8_t *topic_name)
{
uint8_t TrySub_time = 10; //尝试订阅次数
@ -241,11 +249,11 @@ int MQTT_SubscribeTopic(uint8_t *topic_name)
MQTT_Recv(mqtt_rxbuf, 5);
if(mqtt_rxbuf[0] == parket_subAck[0] && mqtt_rxbuf[1] == parket_subAck[1]) //订阅成功
{
return 0;
return true;
}
TrySub_time--;
}
return 1;
return false;
}
@ -253,9 +261,9 @@ int MQTT_SubscribeTopic(uint8_t *topic_name)
* : MQTT_UnSubscribeTopic
* : MQTT取消订阅单个主题
* : topic_name:
* : 0,1
* : true表示取消订阅成功,false表示取消订阅失
*******************************************************************************/
int MQTT_UnSubscribeTopic(uint8_t *topic_name)
bool MQTT_UnSubscribeTopic(uint8_t *topic_name)
{
uint8_t TryUnSub_time = 10; //尝试取消订阅次数
@ -281,7 +289,7 @@ int MQTT_UnSubscribeTopic(uint8_t *topic_name)
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+0] = Platform_mqtt.MessageID/256; //报文标识符高字节
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+1] = Platform_mqtt.MessageID%256; //报文标识符低字节
Platform_mqtt.MessageID++; //每用一次MessageID加1
Platform_mqtt.MessageID++; //每用一次MessageID加1
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+2] = strlen(topic_name)/256; //主题长度高字节
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+3] = strlen(topic_name)%256; //主题长度低字节
@ -295,11 +303,11 @@ int MQTT_UnSubscribeTopic(uint8_t *topic_name)
MQTT_Recv(mqtt_rxbuf, 4);
if(mqtt_rxbuf[0] == parket_unsubAck[0] && mqtt_rxbuf[1] == parket_unsubAck[1]) //取消订阅成功
{
return 0;
return true;
}
TryUnSub_time--;
}
return 1;
return false;
}
@ -377,7 +385,7 @@ void MQTT_PublishDataQs1(uint8_t *topic_name,uint8_t *data, uint16_t data_len)
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+2+strlen(topic_name)] = Platform_mqtt.MessageID/256; //报文标识符高字节
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+3+strlen(topic_name)] = Platform_mqtt.MessageID%256; //报文标识符低字节
Platform_mqtt.MessageID++; //每用一次MessageID加1
Platform_mqtt.MessageID++; //每用一次MessageID加1
memcpy(&Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+4+strlen(topic_name)],data,strlen(data)); //复制data数据
@ -389,9 +397,9 @@ void MQTT_PublishDataQs1(uint8_t *topic_name,uint8_t *data, uint16_t data_len)
* : MQTT_SendHeart
* :
* :
* : 0,
* : true表示发送成功,false表示发送失
*******************************************************************************/
int MQTT_SendHeart(void)
bool MQTT_SendHeart(void)
{
uint8_t TrySentHeart_time = 10; //尝试发送心跳保活次数
while(TrySentHeart_time > 0)
@ -402,11 +410,11 @@ int MQTT_SendHeart(void)
MQTT_Recv(mqtt_rxbuf, 2);
if(mqtt_rxbuf[0] == 0xD0 && mqtt_rxbuf[1] == 0x00)
{
return 0;
return true;
}
TrySentHeart_time--;
}
return 1;
return false;
}
@ -414,20 +422,23 @@ int MQTT_SendHeart(void)
* : MQTT_DealPublishData
* : 0,topic信息
* : redata:,data_len:
* :
* : +
*******************************************************************************/
void MQTT_DealPublishData(uint8_t *data, uint16_t data_len)
uint16_t MQTT_DealPublishData(uint8_t *data, uint16_t data_len)
{
uint8_t i;
uint16_t cmdpos,cmdlen;
for(i = 1;i < 5;i++)
{
//查找可变报头的长度字段,如果最高位为0表示该字节是长度字段的最后一个字节
if((data[i] & 0x80) == 0)
break;
}
//1代表固定报头占一个字节,i代表可变报头长度字段所占用字节数,2代表主题长度字段占2字节,cmdpos代表报文里主题名称起始位置
cmdpos = 1+i+2;
//data_len减去1+i+2就是报文中主题部分+实际负载的长度
cmdlen = data_len-(1+i+2);
if(data_len <= CMD_SIZE)
@ -435,4 +446,6 @@ void MQTT_DealPublishData(uint8_t *data, uint16_t data_len)
memset(Platform_mqtt.cmdbuff, 0, CMD_SIZE);
memcpy(Platform_mqtt.cmdbuff, &data[cmdpos], cmdlen);
}
return cmdlen;
}

View File

@ -23,15 +23,16 @@
#define _PLATFORM_MQTT_H_
#include <stdint.h>
#include "utils_hmacsha1.h"
#include <stdbool.h>
#define KEEPALIVE_TIME 300 //保活时间(单位s),300s
#define HEART_TIME 120000 //空闲时发送心跳包的时间间隔(单位ms),120s
#define PACK_SIZE 512 //存放报文数据缓冲区大小
#define CMD_SIZE 3072 //保存推送的PUBLISH报文中的数据缓冲区大小
#define CLIENTID_SIZE 64 //存放客户端ID的缓冲区大小
#define USERNAME_SIZE 64 //存放用户名的缓冲区大小
#define PASSWARD_SIZE 64 //存放密码的缓冲区大小
#define KEEPALIVE_TIME 300 //保活时间(单位s),300s
#define HEART_TIME 200000 //空闲时发送心跳包的时间间隔(单位ms),200s
#define PACK_SIZE 512 //存放报文数据缓冲区大小
#define MQTT_FRAME_SIZE 3072 //保存推送的PUBLISH报文中的数据负载大小,最大3k
#define CMD_SIZE (MQTT_FRAME_SIZE + 512) //保存推送的PUBLISH报文中的数据缓冲区大小
#define CLIENTID_SIZE 64 //存放客户端ID的缓冲区大小
#define USERNAME_SIZE 64 //存放用户名的缓冲区大小
#define PASSWARD_SIZE 64 //存放密码的缓冲区大小
typedef struct{
uint8_t ClientID[CLIENTID_SIZE]; //存放客户端ID的缓冲区
@ -51,12 +52,12 @@ extern MQTT_TCB Platform_mqtt; //外部变量声明
int AdapterNetActive(void);
int MQTT_Send(const uint8_t* buf, int buflen);
int MQTT_Recv(uint8_t* buf, int buflen);
int MQTT_Connect(void);
bool MQTT_Connect(void);
void MQTT_Disconnect(void);
int MQTT_SubscribeTopic(uint8_t *topic_name);
int MQTT_UnSubscribeTopic(uint8_t *topic_name);
bool MQTT_SubscribeTopic(uint8_t *topic_name);
bool MQTT_UnSubscribeTopic(uint8_t *topic_name);
void MQTT_PublishDataQs0(uint8_t *topic_name,uint8_t *data, uint16_t data_len);
void MQTT_PublishDataQs1(uint8_t *topic_name,uint8_t *data, uint16_t data_len);
int MQTT_SendHeart(void);
void MQTT_DealPublishData(uint8_t *data, uint16_t data_len);
bool MQTT_SendHeart(void);
uint16_t MQTT_DealPublishData(uint8_t *data, uint16_t data_len);
#endif

View File

@ -626,7 +626,6 @@ uint8_t FLASH_WritePage(uint32_t addr, const uint32_t *buf, uint32_t len)
flexspi_xfer_t flashXfer;
addr &= 0x0FFFFFFF;
flashXfer.operation = kFLEXSPIOperation_Write;
flashXfer.seqNum = 1;
flashXfer.seqId = NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM;
@ -692,8 +691,8 @@ status_t NorFlash_Write_PageProgram(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t
uint8_t temp_data[256] = {0xff};
memcpy(temp_data,pBuffer,NumByteToWrite);
status_t status = FLASH_WritePage(WriteAddr,(void *)temp_data,FLASH_PAGE_SIZE);
status_t status = FLASH_WritePage(WriteAddr,(void *)temp_data,FLASH_PAGE_SIZE);
if(status != kStatus_Success)
{
KPrintf("Write_PageProgram 0x%x faild!\r\n",WriteAddr);
@ -773,9 +772,9 @@ status_t Flash_Erase(uint32_t start_addr, uint32_t imageSize)
for(i=0;i<sectorNum;i++)
{
status = FLASH_EraseSector(start_addr+i*SECTOR_SIZE);
if (status != kStatus_Success)
status = FLASH_EraseSector(start_addr+i*SECTOR_SIZE);
if(status != kStatus_Success)
{
KPrintf("Erase_Sector 0x%x faild!\r\n",i*SECTOR_SIZE);
return status;
@ -817,7 +816,7 @@ status_t Flash_Write(uint32_t WriteAddr, uint8_t *pBuffer, uint32_t NumByteToWri
while(1)
{
status = FLASH_ReadBuf(CHIP_FLAH_BASE + secPos*SECTOR_SIZE, (void *)NorFlash_BUF, SECTOR_SIZE);//读出整个扇区的内容
if (status != kStatus_Success)
if(status != kStatus_Success)
{
return status;
}
@ -831,7 +830,7 @@ status_t Flash_Write(uint32_t WriteAddr, uint8_t *pBuffer, uint32_t NumByteToWri
if(i < secRemain)//需要擦除
{
status = FLASH_EraseSector(CHIP_FLAH_BASE + secPos*SECTOR_SIZE);
if (status != kStatus_Success)
if(status != kStatus_Success)
{
return status;
}
@ -840,7 +839,7 @@ status_t Flash_Write(uint32_t WriteAddr, uint8_t *pBuffer, uint32_t NumByteToWri
NorFlash_BUF[i+secOff] = pBuffer[i];
}
status = NorFlash_Write_NoCheck(NorFlash_BUF,CHIP_FLAH_BASE + secPos*SECTOR_SIZE,SECTOR_SIZE);//写入整个扇区
if (status != kStatus_Success)
if(status != kStatus_Success)
{
return status;
}
@ -848,7 +847,7 @@ status_t Flash_Write(uint32_t WriteAddr, uint8_t *pBuffer, uint32_t NumByteToWri
else
{
status = NorFlash_Write_NoCheck(pBuffer,CHIP_FLAH_BASE + WriteAddr,secRemain);//写已经擦除了的,直接写入扇区剩余区间.
if (status != kStatus_Success)
if(status != kStatus_Success)
{
return status;
}
@ -896,7 +895,6 @@ status_t Flash_Read(uint32_t addr, uint8_t *buf, uint32_t len)
{
return FLASH_ReadBuf(addr, (void *)buf, len);
}
else
{
void* result = memcpy(buf, (void*)addr, len);
@ -907,8 +905,7 @@ status_t Flash_Read(uint32_t addr, uint8_t *buf, uint32_t len)
else
{
return (status_t)kStatus_Success;
}
}
}
}
@ -993,10 +990,10 @@ status_t NOR_FLASH_Write(uint32_t* FlashAddress, uint8_t* Data ,uint16_t DataLen
uint32_t WriteAddr;
WriteAddr = *FlashAddress;
status = Flash_Write(WriteAddr,Data,DataLength);
if (status != kStatus_Success)
if(status != kStatus_Success)
{
return status;
}
}
*FlashAddress += DataLength;
return (status_t)kStatus_Success;
}
@ -1015,13 +1012,13 @@ status_t NOR_FLASH_Write(uint32_t* FlashAddress, uint8_t* Data ,uint16_t DataLen
packetNum ++;
if(1 == packetNum)
{
WriteAddr = *FlashAddress;
WriteAddr = *FlashAddress;
}
if(dataLen>=SECTOR_SIZE)
{
status = Flash_Write(WriteAddr,dataBuff,dataLen);
if (status != kStatus_Success)
if(status != kStatus_Success)
{
return status;
}
@ -1033,10 +1030,10 @@ status_t NOR_FLASH_Write(uint32_t* FlashAddress, uint8_t* Data ,uint16_t DataLen
else
{
status = Flash_Write(WriteAddr,dataBuff,dataLen);
if (status != kStatus_Success)
if(status != kStatus_Success)
{
return status;
}
}
packetNum = 0;
dataLen = 0;
}

View File

@ -350,10 +350,9 @@ static uint8 SdCardReadCd(void)
return BusDevReadData(pin->owner_haldev, &read_param);
}
static int sd_card_status = 0;
static void SdCardTask(void* parameter)
{
static int sd_card_status = 0;
while (1) {
if (!SdCardReadCd()) {
if (!sd_card_status) {
@ -369,6 +368,11 @@ static void SdCardTask(void* parameter)
}
}
int GetSdCardStatus(void)
{
return sd_card_status;
}
#ifdef MOUNT_SDCARD
int MountSDCard()
{

View File

@ -596,7 +596,7 @@ KERNELPATHS +=-I$(KERNEL_ROOT)/tool/bootloader/flash \
-I$(KERNEL_ROOT)/tool/bootloader/ota #
endif
ifeq ($(CONFIG_TOOL_USING_MQTT), y)
ifeq ($(CONFIG_LIB_USING_MQTT), y)
KERNELPATHS +=-I$(KERNEL_ROOT)/../../APP_Framework/lib/mqtt
endif

View File

@ -7,7 +7,7 @@ menu "OTA function"
if TOOL_USING_OTA
choice
prompt "Compile bootloader bin or application bin."
default MCUBOOT_BOOTLOADER
default MCUBOOT_APPLICATION
config MCUBOOT_BOOTLOADER
bool "Config as bootloader."
@ -23,7 +23,7 @@ menu "OTA function"
config OTA_BY_PLATFORM
bool "Through IoT management platform."
select TOOL_USING_MQTT
select LIB_USING_MQTT
config OTA_BY_TCPSERVER
bool "Through the public network TCP server."
@ -65,10 +65,10 @@ menu "OTA function"
default 10000 if OTA_BY_TCPSERVER
default 10000 if MCUBOOT_BOOTLOADER
config OTA_RX_BUFFERSIZE
int "OTA receive data buffer size."
config OTA_FRAME_SIZE
int "OTA receive data frame size."
default 3072 if OTA_BY_PLATFORM
default 2048 if OTA_BY_TCPSERVER
default 1024 if OTA_BY_TCPSERVER
default 256 if MCUBOOT_BOOTLOADER
endif

View File

@ -19,9 +19,10 @@
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <transform.h>
#include "shell.h"
#include "xsconfig.h"
#include "mcuboot.h"
#include "ymodem.h"
#include "ota.h"
@ -34,6 +35,10 @@
#include "platform_mqtt.h"
#endif
#ifdef USING_DOWNLOAD_JSON
#include "cJSON.h"
#endif
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
@ -42,7 +47,7 @@ static int create_version(uint8_t* cur_version, uint8_t* new_version);
static status_t UpdateOTAFlag(ota_info_t *ptr);
static void InitialVersion(void);
static void BackupVersion(void);
static void UpdateNewApplication(void);
static bool UpdateNewApplication(void);
static void Update(void);
static void BootLoaderJumpApp(void);
@ -128,7 +133,7 @@ static uint32_t calculate_crc32(uint32_t addr, uint32_t len)
* : cur_version:,new_version:
* : 0:,-1:
* : ,OTA传输而来的版本号也要保持这样三段式的形式
major.minor.patch,01.02.03
major.minor.patch,001.002.003
*******************************************************************************/
static int create_version(uint8_t* cur_version, uint8_t* new_version)
{
@ -226,30 +231,39 @@ static void BackupVersion(void)
ota_info.status = OTA_STATUS_BACKUP;
UpdateOTAFlag(&ota_info);
status = mcuboot.op_flash_copy(BAKUP_FLAH_ADDRESS, XIUOS_FLAH_ADDRESS, ota_info.bak.size);
if((status == kStatus_Success) &&(calculate_crc32(XIUOS_FLAH_ADDRESS, ota_info.bak.size) == ota_info.bak.crc32))
// 1.先清空XiUOS System分区
status = mcuboot.op_flash_erase(XIUOS_FLAH_ADDRESS, ota_info.os.size);
if(status == kStatus_Success)
{
mcuboot.print_string("\r\n------Backup app version success!------\r\n");
ota_info.os.size = ota_info.bak.size;
ota_info.os.crc32 = ota_info.bak.crc32;
memset(ota_info.os.version,0,sizeof(ota_info.os.version));
strncpy(ota_info.os.version, ota_info.bak.version, sizeof(ota_info.bak.version));
memset(ota_info.os.description,0,sizeof(ota_info.os.description));
strncpy(ota_info.os.description, ota_info.bak.description, sizeof(ota_info.bak.description));
memset(&ota_info.os,0,sizeof(ota_info.os));
UpdateOTAFlag(&ota_info);
mcuboot.print_string("\r\n------Clear app partition success!------\r\n");
}
else
{
mcuboot.print_string("\r\n------Backup app version failed!------\r\n");
ota_info.status = OTA_STATUS_ERROR;
memset(ota_info.error_message,0,sizeof(ota_info.error_message));
strncpy(ota_info.error_message, "Backup app version failed!",sizeof(ota_info.error_message));
mcuboot.print_string("\r\n------Clear app partition failed!------\r\n");
return;
}
// 2.拷贝backup分区到XiUOS System分区
status = mcuboot.op_flash_copy(BAKUP_FLAH_ADDRESS, XIUOS_FLAH_ADDRESS, ota_info.bak.size);
if(status == kStatus_Success)
{
ota_info.os.size = ota_info.bak.size;
ota_info.os.crc32 = ota_info.bak.crc32;
memset(ota_info.os.version,0,sizeof(ota_info.os.version));
strncpy(ota_info.os.version, ota_info.bak.version, sizeof(ota_info.bak.version));
memset(ota_info.os.description,0,sizeof(ota_info.os.description));
strncpy(ota_info.os.description, ota_info.bak.description, sizeof(ota_info.bak.description));
UpdateOTAFlag(&ota_info);
mcuboot.print_string("\r\n------Version rollback successful!------\r\n");
}
else
{
ota_info.status = OTA_STATUS_ERROR;
memset(ota_info.error_message,0,sizeof(ota_info.error_message));
strncpy(ota_info.error_message, "Version rollback failed!",sizeof(ota_info.error_message));
UpdateOTAFlag(&ota_info);
mcuboot.print_string("\r\n------Version rollback failed!------\r\n");
}
}
@ -258,10 +272,11 @@ static void BackupVersion(void)
* : UpdateNewApplication
* : bootloader里进行调用,Flash中Flag分区中的信息决定是否进行版本更新
* :
* :
* : true:,flash搬移的操作,
false:,flash搬移
* : APP分区保持不变,APP分区的版本为新版本
*******************************************************************************/
static void UpdateNewApplication(void)
static bool UpdateNewApplication(void)
{
status_t status;
ota_info_t ota_info; // 定义OTA信息结构体
@ -270,97 +285,126 @@ static void UpdateNewApplication(void)
// 从Flash中读取OTA信息
mcuboot.op_flash_read(FLAG_FLAH_ADDRESS, (void*)&ota_info, sizeof(ota_info_t));
// 如果OTA升级状态为准备状态且APP分区与download分区版本不同,才可以进行升级
// 如果OTA升级状态为准备状态,且APP分区与download分区版本不同,才需要进行升级
if((ota_info.status == OTA_STATUS_READY) && (ota_info.os.crc32 != ota_info.down.crc32))
{
mcuboot.print_string("\r\n------Start to update the app!------\r\n");
mcuboot.print_string("\r\n------Start upgrading to new version!------\r\n");
// 校验downlad分区固件CRC
if(calculate_crc32(DOWN_FLAH_ADDRESS, ota_info.down.size) == ota_info.down.crc32)
{
ota_info.status = OTA_STATUS_UPDATING;
UpdateOTAFlag(&ota_info);
// 1.如果CRC校验通过,开始升级,逐字节拷贝Flash,先备份当前XiUOS System分区内容
// 1.如果CRC校验通过,开始升级,先清空Backup分区
status = mcuboot.op_flash_erase(BAKUP_FLAH_ADDRESS, ota_info.bak.size);
if(status == kStatus_Success)
{
memset(&ota_info.bak,0,sizeof(ota_info.bak));
UpdateOTAFlag(&ota_info);
mcuboot.print_string("\r\n------Clear backup partition success!------\r\n");
}
else
{
mcuboot.print_string("\r\n------Clear backup partition failed!------\r\n");
goto finish;
}
// 2.逐字节拷贝Flash,备份当前XiUOS System分区内容到Backup分区
status = mcuboot.op_flash_copy(XIUOS_FLAH_ADDRESS, BAKUP_FLAH_ADDRESS, ota_info.os.size);
if((status == kStatus_Success) &&(calculate_crc32(BAKUP_FLAH_ADDRESS, ota_info.os.size) == ota_info.os.crc32))
{
mcuboot.print_string("\r\n------Backup app success!------\r\n");
ota_info.bak.size = ota_info.os.size;
ota_info.bak.crc32 = ota_info.os.crc32;
memset(ota_info.bak.version,0,sizeof(ota_info.bak.version));
strncpy(ota_info.bak.version, ota_info.os.version, sizeof(ota_info.os.version));
memset(ota_info.bak.description,0,sizeof(ota_info.bak.description));
strncpy(ota_info.bak.description, ota_info.os.description, sizeof(ota_info.os.description));
UpdateOTAFlag(&ota_info);;
UpdateOTAFlag(&ota_info);
mcuboot.print_string("\r\n------Backup app success!------\r\n");
}
else
{
mcuboot.print_string("\r\n------Backup app failed!------\r\n");
ota_info.status = OTA_STATUS_ERROR;
memset(ota_info.error_message,0,sizeof(ota_info.error_message));
strncpy(ota_info.error_message, "Backup app failed!",sizeof(ota_info.error_message));
UpdateOTAFlag(&ota_info);;
UpdateOTAFlag(&ota_info);
mcuboot.print_string("\r\n------Backup app failed!------\r\n");
goto finish;
}
// 2.拷贝download分区到XiUOS System分区
// 3.清空XiUOS System分区
status = mcuboot.op_flash_erase(XIUOS_FLAH_ADDRESS, ota_info.os.size);
if(status == kStatus_Success)
{
memset(&ota_info.os,0,sizeof(ota_info.os));
UpdateOTAFlag(&ota_info);
mcuboot.print_string("\r\n------Clear app partition success!------\r\n");
}
else
{
mcuboot.print_string("\r\n------Clear app partition failed!------\r\n");
goto finish;
}
// 4.拷贝download分区到XiUOS System分区
status = mcuboot.op_flash_copy(DOWN_FLAH_ADDRESS, XIUOS_FLAH_ADDRESS, ota_info.down.size);
if((status == kStatus_Success) &&(calculate_crc32(XIUOS_FLAH_ADDRESS, ota_info.down.size) == ota_info.down.crc32))
{
mcuboot.print_string("\r\n------The download partition is copied successfully!------\r\n");
ota_info.os.size = ota_info.down.size;
ota_info.os.crc32 = ota_info.down.crc32;
memset(ota_info.os.version,0,sizeof(ota_info.os.version));
strncpy(ota_info.os.version, ota_info.down.version, sizeof(ota_info.down.version));
memset(ota_info.os.description,0,sizeof(ota_info.os.description));
strncpy(ota_info.os.description, ota_info.down.description, sizeof(ota_info.down.description));
ota_info.status == OTA_STATUS_IDLE; // 拷贝download分区到XiUOS System分区成功,将OTA升级状态设置为IDLE
UpdateOTAFlag(&ota_info);;
UpdateOTAFlag(&ota_info);
mcuboot.print_string("\r\n------The download partition is copied successfully!------\r\n");
}
else
{
mcuboot.print_string("\r\n------The download partition copy failed!------\r\n");
ota_info.status = OTA_STATUS_ERROR;
memset(ota_info.error_message,0,sizeof(ota_info.error_message));
strncpy(ota_info.error_message, "The download partition copy failed!",sizeof(ota_info.error_message));
UpdateOTAFlag(&ota_info);;
UpdateOTAFlag(&ota_info);
mcuboot.print_string("\r\n------The download partition copy failed!------\r\n");
goto finish;
}
mcuboot.print_string("\r\n------Update completed!------\r\n");
// 5.清空download分区
status = mcuboot.op_flash_erase(DOWN_FLAH_ADDRESS, ota_info.down.size);
if(status == kStatus_Success)
{
memset(&ota_info.down,0,sizeof(ota_info.down));
UpdateOTAFlag(&ota_info);
mcuboot.print_string("\r\n------Clear download partition success!------\r\n");
}
else
{
mcuboot.print_string("\r\n------Clear download partition failed!------\r\n");
goto finish;
}
ota_info.status == OTA_STATUS_IDLE; //将OTA升级状态设置为IDLE
UpdateOTAFlag(&ota_info);
mcuboot.print_string("\r\n------New version upgrade completed,reboot again!------\r\n");
goto finish;
}
else
{
// 如果download分区CRC校验失败升级失败
mcuboot.print_string("\r\n------Download Firmware CRC check failed!------\r\n");
// 如果download分区CRC校验失败,升级失败
ota_info.status = OTA_STATUS_ERROR;
memset(ota_info.error_message,0,sizeof(ota_info.error_message));
strncpy(ota_info.error_message, "Download Firmware CRC check failed!",sizeof(ota_info.error_message));
UpdateOTAFlag(&ota_info);;
UpdateOTAFlag(&ota_info);
mcuboot.print_string("\r\n------Download Firmware CRC check failed!------\r\n");
goto finish;
}
}
else
{
mcuboot.print_string("\r\n------No need to update the app!------\r\n");
goto finish;
return false;
}
finish:
return;
return true;
}
@ -376,23 +420,33 @@ static void Update(void)
mcuboot.flash_init();
memset(&ota_info, 0, sizeof(ota_info_t));
mcuboot.op_flash_read(FLAG_FLAH_ADDRESS, (void*)&ota_info, sizeof(ota_info_t));
/* 此时APP分区还没有有效的固件,需要在bootloader下通过iap烧写出厂固件 */
if((ota_info.os.size > APP_FLASH_SIZE) || (calculate_crc32(XIUOS_FLAH_ADDRESS, ota_info.os.size) != ota_info.os.crc32))
/* APP分区无有效固件时,需在bootloader下烧写初始固件, os.size大于分区大小视为无效固件*/
if(ota_info.os.size > APP_FLASH_SIZE)
{
mcuboot.print_string("\r\nNeed to flash initial firmware!\r\n");
InitialVersion();
mcuboot.flash_deinit();
}
else
/*进行新版本的升级*/
else
{
UpdateNewApplication();
if(UpdateNewApplication() == true) /*如果实际发生了flash搬移,操作完成后再重启一次*/
{
mcuboot.flash_deinit();
mcuboot.op_delay(2000);
mcuboot.op_reset();
}
else /*如果实际未发生flash搬移,说明未发生实际的升级,操作完成后不必再重启*/
{
mcuboot.flash_deinit();
}
}
mcuboot.flash_deinit();
}
/*******************************************************************************
* : BootLoaderJumpApp
* : ,BAKUP分区进行恢复
* : ,BAKUP分区进行恢复,
* :
* :
*******************************************************************************/
@ -406,7 +460,7 @@ static void BootLoaderJumpApp(void)
if(ota_info.lastjumpflag == JUMP_FAILED_FLAG)
{
mcuboot.print_string("\r\n------Bootloader false, begin backup!------\r\n");
mcuboot.print_string("\r\n------Jump to app partition failed,start version rollback!------\r\n");
BackupVersion();
}
else
@ -466,6 +520,7 @@ static void app_ota_by_iap(void)
UpdateOTAFlag(&ota_info);
}
mcuboot.flash_deinit();
MdelayKTask(2000);
mcuboot.op_reset();
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),iap, app_ota_by_iap, ota by iap function);
@ -527,6 +582,11 @@ static void get_start_signal(struct Adapter* adapter)
KPrintf("waiting for start msg...\n");
if(AdapterDeviceRecv(adapter, &start_msg, sizeof(start_msg)) >= 0 && start_msg.header.frame_flag == STARTFLAG)
{
if(start_msg.header.total_len > APP_FLASH_SIZE)
{
KPrintf("File size is larger than partition size,the partition size is %dk.\n",APP_FLASH_SIZE/1024);
break;
}
if(mcuboot.op_flash_erase(DOWN_FLAH_ADDRESS,start_msg.header.total_len) != kStatus_Success)
{
KPrintf("Failed to erase target fash!\n");
@ -726,7 +786,7 @@ static void app_ota_by_4g(void)
}
}
mcuboot.flash_deinit();
KPrintf("ota file transfer complete,start reboot!\n");
KPrintf("firmware file transfer successful,start reboot!\n");
MdelayKTask(2000);
mcuboot.op_reset();
}
@ -734,13 +794,301 @@ static void app_ota_by_4g(void)
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),ota, app_ota_by_4g, ota by 4g function);
#endif
#ifdef OTA_BY_PLATFORM
#define FRAME_LEN 2048 //每帧数据的数据包长度
static uint8_t MqttRxbuf[3072];
static uint8_t FrameBuf[FRAME_LEN];
static OTA_TCB AliOTA;
#if (OTA_FRAME_SIZE <= MQTT_FRAME_SIZE)
#define FRAME_LEN OTA_FRAME_SIZE
#else
#error "The value of FRAME_LEN should not be greater than MQTT_FRAME_SIZE!!"
#endif
static uint8_t MqttRxbuf[FRAME_LEN + 512];
static uint8_t FrameBuf[FRAME_LEN];
static OTA_TCB platform_ota;
#ifdef XIUOS_PLATFORM
/*******************************************************************************
* : PropertyVersion
* :
* :
* :
*******************************************************************************/
static void PropertyVersion(void)
{
uint8_t tempdatabuff[128];
ota_info_t ota_info;
memset(&ota_info, 0, sizeof(ota_info_t));
mcuboot.op_flash_read(FLAG_FLAH_ADDRESS, (void*)&ota_info, sizeof(ota_info_t));
memset(tempdatabuff,0,128);
sprintf(tempdatabuff,"{\"clientId\":\"%s\",\"version\":\"%s\"}",CLIENTID,ota_info.os.version);
KPrintf("------current version is:%s------\r\n",ota_info.os.version);
MQTT_PublishDataQs1("xiuosiot/ota/version",tempdatabuff,strlen(tempdatabuff)); //发送等级QS=1的PUBLISH报文
}
/*-------------------------------------------------*/
/*函数名OTA下载数据 */
/*参 数size:本次下载量 */
/*参 数offset:本次下载偏移量 */
/*返回值:无 */
/*-------------------------------------------------*/
static void OTA_Download(int size, int offset)
{
uint8_t tempdatabuff[128];
memset(tempdatabuff,0,128);
sprintf(tempdatabuff,"{\"clientId\":\"%s\",\"fileId\":%d,\"fileOffset\":%d,\"size\":%d}",Platform_mqtt.ClientID,platform_ota.streamId,offset,size);
MQTT_PublishDataQs0("xiuosiot/ota/files", tempdatabuff, strlen(tempdatabuff));
}
/*******************************************************************************
* : mqttCloudInteraction
* : MQTT协议与云平台交互
* :
* :
*******************************************************************************/
static void mqttCloudInteraction(void* parameter)
{
int datalen;
int ret = 0;
int freecnt = 0;
ota_info_t ota_info;
uint32_t heart_time = 0;
uint32_t flashdestination = DOWN_FLAH_ADDRESS;
uint8_t topicdatabuff[2][32];
char *ptr1, *ptr2;
uint16_t cmdlen;
mcuboot.flash_init();
memset(&ota_info, 0, sizeof(ota_info_t));
mcuboot.op_flash_read(FLAG_FLAH_ADDRESS, (void*)&ota_info, sizeof(ota_info_t));
ota_info.status = OTA_STATUS_DOWNLOADING;
UpdateOTAFlag(&ota_info);
memset(topicdatabuff,0,sizeof(topicdatabuff));
sprintf(topicdatabuff[0],"ota/%s/update",CLIENTID);
sprintf(topicdatabuff[1],"ota/%s/files",CLIENTID);
reconnect:
if((AdapterNetActive() == 0) && MQTT_Connect() && MQTT_SubscribeTopic(topicdatabuff[0]) && MQTT_SubscribeTopic(topicdatabuff[1]))
{
KPrintf("Log in to the cloud platform and subscribe to the ota topic successfully.\n");
PropertyVersion();
}
else
{
KPrintf("Log in to the cloud platform failed, retry!\n");
goto reconnect;
}
#ifdef USING_DOWNLOAD_JSON
uint8_t jsontopicdatabuff[32];
uint8_t jsonfilename[32];
memset(jsontopicdatabuff,0,sizeof(jsontopicdatabuff));
sprintf(jsontopicdatabuff,"protocol/%s/files",CLIENTID);
if(MQTT_SubscribeTopic(jsontopicdatabuff))
{
KPrintf("subscribe to the json download topic successfully.\n");
}
#endif
while(1)
{
memset(MqttRxbuf,0,sizeof(MqttRxbuf));
datalen = MQTT_Recv(MqttRxbuf, sizeof(MqttRxbuf));
if(datalen <= 0)
{
freecnt++;
if((freecnt >= 20) && (CalculateTimeMsFromTick(CurrentTicksGain()) - heart_time >= HEART_TIME)) //连续20次未收到数据默认为为空闲状态,需每隔一段时间发送需要发送心跳包保活
{
heart_time = CalculateTimeMsFromTick(CurrentTicksGain());
freecnt = 0;
if(!MQTT_SendHeart()) //发送心跳包失败可能连接断开,需要重连
{
KPrintf("The connection has been disconnected, reconnecting!\n");
goto reconnect;
}
KPrintf("Send heartbeat packet successful!\n");
}
}
else if(MqttRxbuf[0] == 0x30)
{
freecnt = 0;
cmdlen = MQTT_DealPublishData(MqttRxbuf, datalen);
// 1.获取新版本固件大小及版本信息
ptr1 = strstr((char *)Platform_mqtt.cmdbuff,topicdatabuff[0]);
ptr2 = strstr((char *)Platform_mqtt.cmdbuff,"{\"fileSize\":");
if((ptr1 != NULL) &&(ptr2 != NULL))
{
if(sscanf(ptr2,"{\"fileSize\":%d,\"version\":\"%11s\",\"fileId\":%d,\"md5\"",&platform_ota.size,platform_ota.version,&platform_ota.streamId)==3)
{
KPrintf("------Start the firmware file transfer!------\r\n");
KPrintf("file size:%d,file id:%d,file version:%s\r\n",platform_ota.size,platform_ota.streamId,platform_ota.version);
KPrintf("---------------------------------------------\r\n");
if(platform_ota.size > APP_FLASH_SIZE)
{
KPrintf("File size is larger than partition size,the partition size is %dk.\n",APP_FLASH_SIZE/1024);
ret = -1;
ota_info.status = OTA_STATUS_ERROR;
memset(ota_info.error_message,0,sizeof(ota_info.error_message));
strncpy(ota_info.error_message, "File size is larger than partition size!",sizeof(ota_info.error_message));
UpdateOTAFlag(&ota_info);
break;
}
if(mcuboot.op_flash_erase(DOWN_FLAH_ADDRESS,platform_ota.size) != kStatus_Success)
{
KPrintf("Failed to erase download partition!\n");
ret = -1;
ota_info.status = OTA_STATUS_ERROR;
memset(ota_info.error_message,0,sizeof(ota_info.error_message));
strncpy(ota_info.error_message, "Failed to erase download partition!",sizeof(ota_info.error_message));
UpdateOTAFlag(&ota_info);
break;
}
platform_ota.counter = (platform_ota.size%FRAME_LEN != 0)? (platform_ota.size/FRAME_LEN + 1):(platform_ota.size/FRAME_LEN);
platform_ota.num = 1; //下载次数,初始值为1
platform_ota.downlen = FRAME_LEN; //记录本次下载量
OTA_Download(platform_ota.downlen,(platform_ota.num - 1)*FRAME_LEN); //发送要下载的数据信息给服务器
}
else
{
KPrintf("Failed to get ota information!\n");
ret = -1;
ota_info.status = OTA_STATUS_ERROR;
memset(ota_info.error_message,0,sizeof(ota_info.error_message));
strncpy(ota_info.error_message, "Failed to get ota information!",sizeof(ota_info.error_message));
UpdateOTAFlag(&ota_info);
break;
}
}
// 2.分片接收新版本固件
if(strstr((char *)Platform_mqtt.cmdbuff,topicdatabuff[1]))
{
memset(FrameBuf,0,sizeof(FrameBuf));
memcpy(FrameBuf, &MqttRxbuf[datalen-platform_ota.downlen], platform_ota.downlen);
if(mcuboot.op_flash_write(flashdestination,FrameBuf,platform_ota.downlen) != kStatus_Success)
{
KPrintf("current frame[%d] flash failed.\n",platform_ota.num-1);
ret = -1;
ota_info.status = OTA_STATUS_ERROR;
memset(ota_info.error_message,0,sizeof(ota_info.error_message));
sprintf(ota_info.error_message,"current frame[%d] flash failed.",platform_ota.num-1);
UpdateOTAFlag(&ota_info);
break;
}
else
{
KPrintf("current frame[%d] is written to flash 0x%x address successful.\n", platform_ota.num -1, flashdestination);
KPrintf("current progress is %d/%d.\r\n",platform_ota.num,platform_ota.counter);
flashdestination += platform_ota.downlen;
platform_ota.num++;
}
if(platform_ota.num < platform_ota.counter) //如果小于总下载次数
{
platform_ota.downlen = FRAME_LEN; //记录本次下载量
OTA_Download(platform_ota.downlen,(platform_ota.num - 1)*FRAME_LEN); //发送要下载的数据信息给服务器
}
else if(platform_ota.num == platform_ota.counter) //如果等于总下载次数,说明是最后一次下载
{
if(platform_ota.size%FRAME_LEN == 0) //判断固件大小是否是FRAME_LEN的整数倍
{
platform_ota.downlen = FRAME_LEN; //记录本次下载量
OTA_Download(platform_ota.downlen,(platform_ota.num - 1)*FRAME_LEN); //发送要下载的数据信息给服务器
}
else
{
platform_ota.downlen = platform_ota.size%FRAME_LEN; //记录本次下载量
OTA_Download(platform_ota.downlen,(platform_ota.num - 1)*FRAME_LEN); //发送要下载的数据信息给服务器
}
}
else //下载完毕
{
ret = 0;
break;
}
}
#ifdef USING_DOWNLOAD_JSON
// 3.下载json文件,SD卡要确保已经插入
extern int GetSdCardStatus(void);
if(strstr((char *)Platform_mqtt.cmdbuff,jsontopicdatabuff) && GetSdCardStatus())
{
KPrintf("------Start download joson file !------\r\n");
memset(jsonfilename,0,sizeof(jsonfilename));
memset(FrameBuf,0,sizeof(FrameBuf));
memcpy(FrameBuf, &Platform_mqtt.cmdbuff[strlen(jsontopicdatabuff)],cmdlen-strlen(jsontopicdatabuff));
cJSON *json_obj = cJSON_Parse(FrameBuf);
char* product_name = cJSON_GetObjectItem(json_obj, "productName")->valuestring;
sprintf(jsonfilename,"%s",product_name);
strcat(jsonfilename,".json");
FILE *fp = fopen(jsonfilename, "w");
if(fp == NULL)
{
KPrintf("%s file create failed,please check!\r\n",jsonfilename);
cJSON_Delete(json_obj);
continue;
}
else
{
KPrintf("%s file create success!\r\n",jsonfilename);
char *json_print_str = cJSON_Print(json_obj);
fprintf(fp, "%s", json_print_str);
fclose(fp);
cJSON_free(json_print_str);
cJSON_Delete(json_obj);
}
KPrintf("download %s file done!------\r\n",jsonfilename);
}
#endif
}
else
{
freecnt = 0;
continue;
}
}
// 新版本固件接收完毕,写入描述信息
if(0 == ret)
{
ota_info.down.size = platform_ota.size;
ota_info.down.crc32 = calculate_crc32(DOWN_FLAH_ADDRESS, platform_ota.size);
memset(ota_info.down.version,0,sizeof(ota_info.down.version));
strncpy(ota_info.down.version, platform_ota.version, sizeof(ota_info.down.version));
memset(ota_info.down.description,0,sizeof(ota_info.down.description));
strncpy(ota_info.down.description, "MQTT OTA bin.",sizeof(ota_info.down.description));
ota_info.status = OTA_STATUS_READY;
memset(ota_info.error_message,0,sizeof(ota_info.error_message));
strncpy(ota_info.error_message, "No error message!",sizeof(ota_info.error_message));
UpdateOTAFlag(&ota_info);
KPrintf("firmware file transfer successful,start reboot!\n");
}
else
{
KPrintf("firmware file transfer failed,start reboot!\n");
}
MQTT_UnSubscribeTopic(topicdatabuff[0]);
MQTT_UnSubscribeTopic(topicdatabuff[1]);
MQTT_Disconnect();
mcuboot.flash_deinit();
MdelayKTask(2000);
mcuboot.op_reset();
}
#endif
#ifdef ALIBABA_PLATFORM
/*******************************************************************************
* : PropertyVersion
* :
@ -761,6 +1109,7 @@ static void PropertyVersion(void)
memset(tempdatabuff,0,128);
sprintf(tempdatabuff,"{\"id\": \"1\",\"params\": {\"version\": \"%s\"}}",ota_info.os.version);
KPrintf("------current version is:%s------\r\n",ota_info.os.version);
MQTT_PublishDataQs1(topicdatabuff,tempdatabuff,strlen(tempdatabuff)); //发送等级QS=1的PUBLISH报文
}
@ -768,11 +1117,11 @@ static void PropertyVersion(void)
/*-------------------------------------------------*/
/*函数名OTA下载数据 */
/*参 数size本次下载量 */
/*参 数offset本次下载偏移量 */
/*参 数size:本次下载量 */
/*参 数offset:本次下载偏移量 */
/*返回值:无 */
/*-------------------------------------------------*/
void OTA_Download(int size, int offset)
static void OTA_Download(int size, int offset)
{
uint8_t topicdatabuff[64];
uint8_t tempdatabuff[128];
@ -781,18 +1130,18 @@ void OTA_Download(int size, int offset)
sprintf(topicdatabuff,"/sys/%s/%s/thing/file/download",PLATFORM_PRODUCTKEY,CLIENT_DEVICENAME);
memset(tempdatabuff,0,128);
sprintf(tempdatabuff,"{\"id\": \"1\",\"params\": {\"fileInfo\":{\"streamId\":%d,\"fileId\":1},\"fileBlock\":{\"size\":%d,\"offset\":%d}}}",AliOTA.streamId,size,offset);
sprintf(tempdatabuff,"{\"id\": \"1\",\"params\": {\"fileInfo\":{\"streamId\":%d,\"fileId\":1},\"fileBlock\":{\"size\":%d,\"offset\":%d}}}",platform_ota.streamId,size,offset);
MQTT_PublishDataQs0(topicdatabuff, tempdatabuff, strlen(tempdatabuff));
}
/*******************************************************************************
* : app_ota_by_platform
* : MQTT进行升级
* : mqttCloudInteraction
* : MQTT协议与云平台交互
* :
* :
*******************************************************************************/
static void app_ota_by_platform(void* parameter)
static void mqttCloudInteraction(void* parameter)
{
int datalen;
int ret = 0;
@ -812,7 +1161,7 @@ static void app_ota_by_platform(void* parameter)
sprintf(topicdatabuff,"/sys/%s/%s/thing/file/download_reply",PLATFORM_PRODUCTKEY,CLIENT_DEVICENAME);
reconnect:
if((AdapterNetActive() == 0) && (MQTT_Connect() == 0) && MQTT_SubscribeTopic(topicdatabuff) == 0)
if((AdapterNetActive() == 0) && MQTT_Connect() && MQTT_SubscribeTopic(topicdatabuff))
{
KPrintf("Log in to the cloud platform and subscribe to the topic successfully.\n");
PropertyVersion();
@ -829,73 +1178,105 @@ reconnect:
datalen = MQTT_Recv(MqttRxbuf, sizeof(MqttRxbuf));
if(datalen <= 0)
{
freecnt++;
freecnt++;
if((freecnt >= 20) && (CalculateTimeMsFromTick(CurrentTicksGain()) - heart_time >= HEART_TIME)) //连续20次未收到数据默认为为空闲状态,需每隔一段时间发送需要发送心跳包保活
{
heart_time = CalculateTimeMsFromTick(CurrentTicksGain());
freecnt = 0;
if(!MQTT_SendHeart()) //发送心跳包失败可能连接断开,需要重连
{
KPrintf("The connection has been disconnected, reconnecting!\n");
goto reconnect;
}
KPrintf("Send heartbeat packet successful!\n");
}
}
else if(MqttRxbuf[0] == 0x30)
{
freecnt = 0;
MQTT_DealPublishData(MqttRxbuf, datalen);
ptr = strstr((char *)Platform_mqtt.cmdbuff,"{\"code\":\"1000\"");
// 1.获取新版本固件大小及版本信息
ptr = strstr((char *)Platform_mqtt.cmdbuff,"{\"code\":\"1000\"");
if(ptr != NULL)
{
if(sscanf(ptr,"{\"code\":\"1000\",\"data\":{\"size\":%d,\"streamId\":%d,\"sign\":\"%*32s\",\"dProtocol\":\"mqtt\",\"version\":\"%11s\"",&AliOTA.size,&AliOTA.streamId,AliOTA.version)==3)
if(sscanf(ptr,"{\"code\":\"1000\",\"data\":{\"size\":%d,\"streamId\":%d,\"sign\":\"%*32s\",\"dProtocol\":\"mqtt\",\"version\":\"%11s\"",&platform_ota.size,&platform_ota.streamId,platform_ota.version)==3)
{
KPrintf("ota file size:%d\r\n",AliOTA.size);
KPrintf("ota file id:%d\r\n",AliOTA.streamId);
KPrintf("ota file version:%s\r\n",AliOTA.version);
if(mcuboot.op_flash_erase(DOWN_FLAH_ADDRESS,AliOTA.size != kStatus_Success))
KPrintf("------Start the firmware file transfer!------\r\n");
KPrintf("file size:%d,file id:%d,file version:%s\r\n",platform_ota.size,platform_ota.streamId,platform_ota.version);
KPrintf("---------------------------------------------\r\n");
if(platform_ota.size > APP_FLASH_SIZE)
{
KPrintf("Failed to erase target fash!\n");
KPrintf("File size is larger than partition size,the partition size is %dk.\n",APP_FLASH_SIZE/1024);
ret = -1;
ota_info.status = OTA_STATUS_ERROR;
memset(ota_info.error_message,0,sizeof(ota_info.error_message));
strncpy(ota_info.error_message, "File size is larger than partition size!",sizeof(ota_info.error_message));
UpdateOTAFlag(&ota_info);
break;
}
if(mcuboot.op_flash_erase(DOWN_FLAH_ADDRESS,platform_ota.size) != kStatus_Success)
{
KPrintf("Failed to erase download partition!\n");
ret = -1;
break;
}
AliOTA.counter = (AliOTA.size%FRAME_LEN != 0)? (AliOTA.size/FRAME_LEN + 1):(AliOTA.size/FRAME_LEN);
AliOTA.num = 1; //下载次数,初始值为1
AliOTA.downlen = FRAME_LEN; //记录本次下载量
OTA_Download(AliOTA.downlen,(AliOTA.num - 1)*FRAME_LEN); //发送要下载的数据信息给服务器
platform_ota.counter = (platform_ota.size%FRAME_LEN != 0)? (platform_ota.size/FRAME_LEN + 1):(platform_ota.size/FRAME_LEN);
platform_ota.num = 1; //下载次数,初始值为1
platform_ota.downlen = FRAME_LEN; //记录本次下载量
OTA_Download(platform_ota.downlen,(platform_ota.num - 1)*FRAME_LEN); //发送要下载的数据信息给服务器
}
else
{
KPrintf("Failed to get ota information!\n");
ret = -1;
break;
KPrintf("Failed to get ota information!\n");
ret = -1;
ota_info.status = OTA_STATUS_ERROR;
memset(ota_info.error_message,0,sizeof(ota_info.error_message));
strncpy(ota_info.error_message, "Failed to get ota information!",sizeof(ota_info.error_message));
UpdateOTAFlag(&ota_info);
break;
}
}
// 2.分片接收新版本固件
if(strstr((char *)Platform_mqtt.cmdbuff,"download_reply"))
{
memset(FrameBuf,0,sizeof(FrameBuf));
memcpy(FrameBuf, &MqttRxbuf[datalen-AliOTA.downlen-2], AliOTA.downlen);
if(mcuboot.op_flash_write(flashdestination,FrameBuf,AliOTA.downlen) != kStatus_Success)
memcpy(FrameBuf, &MqttRxbuf[datalen-platform_ota.downlen-2], platform_ota.downlen);
if(mcuboot.op_flash_write(flashdestination,FrameBuf,platform_ota.downlen) != kStatus_Success)
{
KPrintf("current frame[%d] flash failed.\n",AliOTA.num-1);
KPrintf("current frame[%d] flash failed.\n",platform_ota.num-1);
ret = -1;
ota_info.status = OTA_STATUS_ERROR;
memset(ota_info.error_message,0,sizeof(ota_info.error_message));
sprintf(ota_info.error_message,"current frame[%d] flash failed.",platform_ota.num-1);
UpdateOTAFlag(&ota_info);
break;
}
else
{
KPrintf("current frame[%d] is written to flash 0x%x address successful.\n", AliOTA.num -1, flashdestination);
KPrintf("Current progress is %d/%d\r\n",AliOTA.num,AliOTA.counter);
flashdestination += AliOTA.downlen;
AliOTA.num++;
KPrintf("current frame[%d] is written to flash 0x%x address successful.\n", platform_ota.num -1, flashdestination);
KPrintf("current progress is %d/%d.\r\n",platform_ota.num,platform_ota.counter);
flashdestination += platform_ota.downlen;
platform_ota.num++;
}
if(AliOTA.num < AliOTA.counter) //如果小于总下载次数
if(platform_ota.num < platform_ota.counter) //如果小于总下载次数
{
AliOTA.downlen = FRAME_LEN; //记录本次下载量
OTA_Download(AliOTA.downlen,(AliOTA.num - 1)*FRAME_LEN); //发送要下载的数据信息给服务器
platform_ota.downlen = FRAME_LEN; //记录本次下载量
OTA_Download(platform_ota.downlen,(platform_ota.num - 1)*FRAME_LEN); //发送要下载的数据信息给服务器
}
else if(AliOTA.num == AliOTA.counter) //如果等于总下载次数,说明是最后一次下载
else if(platform_ota.num == platform_ota.counter) //如果等于总下载次数,说明是最后一次下载
{
if(AliOTA.size%FRAME_LEN == 0) //判断固件大小是否是FRAME_LEN的整数倍
if(platform_ota.size%FRAME_LEN == 0) //判断固件大小是否是FRAME_LEN的整数倍
{
AliOTA.downlen = FRAME_LEN; //记录本次下载量
OTA_Download(AliOTA.downlen,(AliOTA.num - 1)*FRAME_LEN); //发送要下载的数据信息给服务器
platform_ota.downlen = FRAME_LEN; //记录本次下载量
OTA_Download(platform_ota.downlen,(platform_ota.num - 1)*FRAME_LEN); //发送要下载的数据信息给服务器
}
else
{
AliOTA.downlen = AliOTA.size%FRAME_LEN; //记录本次下载量
OTA_Download(AliOTA.downlen,(AliOTA.num - 1)*FRAME_LEN); //发送要下载的数据信息给服务器
platform_ota.downlen = platform_ota.size%FRAME_LEN; //记录本次下载量
OTA_Download(platform_ota.downlen,(platform_ota.num - 1)*FRAME_LEN); //发送要下载的数据信息给服务器
}
}
@ -912,28 +1293,16 @@ reconnect:
freecnt = 0;
continue;
}
if((freecnt >= 10) && (CalculateTimeMsFromTick(CurrentTicksGain()) - heart_time >= HEART_TIME)) //连续10次未收到数据默认为为空闲状态,需每隔一段时间发送需要发送心跳包保活
{
heart_time = CalculateTimeMsFromTick(CurrentTicksGain());
if(MQTT_SendHeart() != 0) //发送心跳包失败可能连接断开,需要重连
{
KPrintf("The connection has been disconnected, reconnecting!\n");
freecnt = 0;
heart_time = 0;
goto reconnect;
}
KPrintf("Send heartbeat packet successful!\n");
}
}
// 新版本固件接收完毕,写入描述信息
if(0 == ret)
{
ota_info.down.size = AliOTA.size;
ota_info.down.crc32= calculate_crc32(DOWN_FLAH_ADDRESS, AliOTA.size);
ota_info.down.size = platform_ota.size;
ota_info.down.crc32 = calculate_crc32(DOWN_FLAH_ADDRESS, platform_ota.size);
memset(ota_info.down.version,0,sizeof(ota_info.down.version));
strncpy(ota_info.down.version, AliOTA.version, sizeof(ota_info.down.version));
strncpy(ota_info.down.version, platform_ota.version, sizeof(ota_info.down.version));
memset(ota_info.down.description,0,sizeof(ota_info.down.description));
strncpy(ota_info.down.description, "MQTT OTA bin.",sizeof(ota_info.down.description));
@ -944,28 +1313,26 @@ reconnect:
strncpy(ota_info.error_message, "No error message!",sizeof(ota_info.error_message));
UpdateOTAFlag(&ota_info);
}
KPrintf("firmware file transfer successful,start reboot!\n");
}
else
{
ota_info.status = OTA_STATUS_ERROR;
memset(ota_info.error_message,0,sizeof(ota_info.error_message));
strncpy(ota_info.error_message, "Failed to download firmware to download partition!",sizeof(ota_info.error_message));
UpdateOTAFlag(&ota_info);
KPrintf("firmware file transfer failed,start reboot!\n");
}
MQTT_UnSubscribeTopic(topicdatabuff);
MQTT_Disconnect();
mcuboot.flash_deinit();
KPrintf("ota file transfer complete,start reboot!\n");
MdelayKTask(2000);
mcuboot.op_reset();
}
#endif
int OtaTask(void)
{
int32 ota_task = 0;
ota_task = KTaskCreate("ota_platform", app_ota_by_platform, NULL,8192, 10);
ota_task = KTaskCreate("mqtt_platform", mqttCloudInteraction, NULL,10240, 10);
if(ota_task < 0) {
KPrintf("ota_task create failed ...%s %d.\n", __FUNCTION__,__LINE__);
KPrintf("matt platform task create failed ...%s %d.\n", __FUNCTION__,__LINE__);
return ERROR;
}
@ -1008,14 +1375,14 @@ void ota_entry(void)
mcuboot.board_init();
mcuboot.print_string("Please press 'space' key into menu in 10s !!!\r\n");
mcuboot.print_string("Please press 'space' key into menu in 5s !!!\r\n");
while(timeout)
{
ret = (SerialKeyPressed((uint8_t*)&ch1));
if(ret) break;
timeout--;
mcuboot.op_delay(10);
mcuboot.op_delay(5);
}
while(1)

View File

@ -22,60 +22,61 @@
#define __OTA_DEF_H__
#include "flash_ops.h"
#include "xsconfig.h"
#define JUMP_FAILED_FLAG 0XABABABAB
#define JUMP_SUCCESS_FLAG 0XCDCDCDCD
#define STARTFLAG 0x1A2B //数据帧开始信号标记
#define DATAFLAG 0x3C4D //数据帧数据信号标记
#define ENDTFLAG 0x5E6F //数据帧结束信号标记
#define LENGTH 1024 //每帧数据的数据包长度
typedef enum {
OTA_STATUS_IDLE = 0, // 空闲状态,没有进行OTA升级
OTA_STATUS_READY, // 准备状态,可以进行OTA升级
OTA_STATUS_DOWNLOADING, // 正在下载固件
OTA_STATUS_DOWNLOADED, // 固件下载完成
OTA_STATUS_UPDATING, // 正在进行OTA升级
OTA_STATUS_BACKUP, // 正在版本回退
OTA_STATUS_ERROR, // 出现错误,升级失败
OTA_STATUS_IDLE = 0, //空闲状态,没有进行OTA升级
OTA_STATUS_READY, //准备状态,可以进行OTA升级
OTA_STATUS_DOWNLOADING, //正在下载固件
OTA_STATUS_DOWNLOADED, //固件下载完成
OTA_STATUS_UPDATING, //正在进行OTA升级
OTA_STATUS_BACKUP, //正在版本回退
OTA_STATUS_ERROR, //出现错误,升级失败
} ota_status_t;
/* Flash分区中保存固件的属性描述 */
typedef struct {
uint32_t size; // 应用程序大小,记录分区固件的大小
uint32_t crc32; // 应用程序CRC32校验值,记录分区固件的crc32值
uint8_t version[32]; // 应用程序版本号,记录分区固件的版本
uint8_t description[32]; // 固件的描述信息,最多32个字符
uint32_t size; //应用程序大小,记录分区固件的大小
uint32_t crc32; //应用程序CRC32校验值,记录分区固件的crc32值
uint8_t version[32]; //应用程序版本号,记录分区固件的版本
uint8_t description[32]; //固件的描述信息,最多32个字符
} firmware_t;
/* OTA升级过程中的信息结构体 */
typedef struct {
firmware_t os; // XiUOS System分区属性信息
firmware_t bak; // Bakup分区属性信息
firmware_t down; // Download分区属性信息
uint32_t status; // 升级状态,取值来自于ota_status_t类型
uint32_t lastjumpflag; // bootloaer跳转失败的标志,bootloader里置0xABABABAB,跳转成功后在应用里置0xCDCDCDCD
uint8_t error_message[64]; // 错误信息,最多64个字符
firmware_t os; //XiUOS System分区属性信息
firmware_t bak; //Bakup分区属性信息
firmware_t down; //Download分区属性信息
uint32_t status; //升级状态,取值来自于ota_status_t类型
uint32_t lastjumpflag; //bootloaer跳转失败的标志,bootloader里置0xABABABAB,跳转成功后在应用里置0xCDCDCDCD
uint8_t error_message[64]; //错误信息,最多64个字符
} ota_info_t;
#ifdef OTA_BY_TCPSERVER
#define STARTFLAG 0x1A2B //数据帧开始信号标记
#define DATAFLAG 0x3C4D //数据帧数据信号标记
#define ENDTFLAG 0x5E6F //数据帧结束信号标记
#define LENGTH OTA_FRAME_SIZE //每帧数据的数据包长度
/*bin包传输过程中的数据帧相关的结构体*/
typedef struct
{
uint16_t frame_flag; // frame start flag 2 Bytes
uint16_t dev_sid; // device software version
uint32_t total_len; // send data total length caculated from each frame_len
uint16_t frame_flag; //frame start flag 2 Bytes
uint16_t dev_sid; //device software version
uint32_t total_len; //send data total length caculated from each frame_len
} ota_header_t;
typedef struct
{
uint32_t frame_id; // Current frame id
uint8_t frame_data[LENGTH]; // Current frame data
uint16_t frame_len; // Current frame data length
uint16_t crc; // Current frame data crc
uint32_t frame_id; //Current frame id
uint8_t frame_data[LENGTH]; //Current frame data
uint16_t frame_len; //Current frame data length
uint16_t crc; //Current frame data crc
} ota_frame_t;
typedef struct
@ -87,13 +88,13 @@ typedef struct
#ifdef OTA_BY_PLATFORM
typedef struct{
uint32_t size; //OTA固件大小
uint32_t streamId; //OTA固件下载时ID编号
uint32_t counter; //OTA总下载次数
uint32_t num; //OTA当前下载次数
uint32_t downlen; //OTA当前下载次数的下载量
uint8_t version[32]; //OTA下载时存储版本号的缓存区
}OTA_TCB;
uint32_t size; //OTA固件大小
uint32_t streamId; //OTA固件下载时ID编号
uint32_t counter; //OTA总下载次数
uint32_t num; //OTA当前下载次数
uint32_t downlen; //OTA当前下载次数的下载量
uint8_t version[32]; //OTA下载时存储版本号的缓存区
} OTA_TCB;
#endif
void app_clear_jumpflag(void);