1306 lines
47 KiB
C
1306 lines
47 KiB
C
#include "ptz_header_file.h"
|
||
#include "agent_hyt.h"
|
||
#include "service_update.h"
|
||
#include "comm_cfginfo.h"
|
||
#include "includes.h"
|
||
#include "w25q128.h"
|
||
#include "rotate_plan.h"
|
||
#include "enet_to_udp.h"
|
||
#include "device_wdog.h"
|
||
#include "onchip_flash.h"
|
||
|
||
|
||
//void OnChip_Flash_read_in_add(uint32_t address,uint16_t cnt,uint8_t*bBuf);
|
||
//uint8_t OnChip_Flash_write_byte(uint32_t address,uint16_t cnt, uint8_t buf[]);
|
||
//uint8_t OnChip_Flash_erase_sector(uint16_t sectorNo);
|
||
|
||
/******************************************************************************
|
||
** 函数名称: ushort cmCRC_16(uchar *PuchMsg,ushort usDataLen)
|
||
** 功 能: 16位CRC校验
|
||
** 修改日志:
|
||
******************************************************************************/
|
||
extern system_cfg_info system_info;
|
||
|
||
static unsigned char auch_crc_h[]={
|
||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81, //DESCRIPTION:RTU CRC校验的高位字节表
|
||
0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,
|
||
0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,
|
||
0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,
|
||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,
|
||
0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,
|
||
0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,
|
||
0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,
|
||
0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,
|
||
0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,
|
||
0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||
0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,
|
||
0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,
|
||
0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,
|
||
0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40};
|
||
|
||
static unsigned char auch_crc_l[]={
|
||
0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,0x07,0xC7,0x05,0xC5,0xC4, //DESCRIPTION:RTU CRC校验的低位字节表
|
||
0x04,0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,0x0A,0xCA,0xCB,0x0B,0xC9,0x09,
|
||
0x08,0xC8,0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A,0x1E,0xDE,0xDF,0x1F,0xDD,
|
||
0x1D,0x1C,0xDC,0x14,0xD4,0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,
|
||
0x11,0xD1,0xD0,0x10,0xF0,0x30,0x31,0xF1,0x33,0xF3,0xF2,0x32,0x36,0xF6,0xF7,
|
||
0x37,0xF5,0x35,0x34,0xF4,0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,
|
||
0x3B,0xFB,0x39,0xF9,0xF8,0x38,0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA,0xEE,
|
||
0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C,0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,
|
||
0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,0xA0,0x60,0x61,0xA1,0x63,0xA3,0xA2,
|
||
0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4,0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,
|
||
0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68,0x78,0xB8,0xB9,0x79,0xBB,
|
||
0x7B,0x7A,0xBA,0xBE,0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,0xB4,0x74,0x75,0xB5,
|
||
0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0,0x50,0x90,0x91,
|
||
0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,0x9C,0x5C,
|
||
0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,0x99,0x59,0x58,0x98,0x88,
|
||
0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,
|
||
0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40};
|
||
|
||
|
||
static struct sockaddr_in ptz_update_local;//本地IP和端口
|
||
|
||
static struct sockaddr_in ptz_update_from;//IP和端口
|
||
static socklen_t ptz_update_fromlen;//长度
|
||
|
||
static struct sockaddr_in ptz_update_serv_a;//指定的默认升级服务端
|
||
static socklen_t ptz_update_servlen_a;
|
||
|
||
static struct sockaddr_in ptz_update_serv_b;//指定的默认升级服务端
|
||
static socklen_t ptz_update_servlen_b;
|
||
|
||
static struct sockaddr_in ptz_update_serv_c;//指定的默认升级服务端
|
||
static socklen_t ptz_update_servlen_c;
|
||
|
||
static struct sockaddr_in ptz_update_serv_d;//指定的默认升级服务端
|
||
static socklen_t ptz_update_servlen_d;
|
||
|
||
|
||
static int ptz_update_fd;//升级通道句柄
|
||
|
||
static UpdateRecvFifoBuff udrb;//数据接收存储
|
||
static UpdateRecvFifoBuff udpb;//数据处理存储
|
||
static UpdateRecvFifoBuff udsb;//数据发送存储区
|
||
|
||
static UpdateRecvFifoBuff urfb[UPDATE_BUFF_FIFO_NUM];//循环缓冲区
|
||
static int ptz_update_communicaton = PTZ_CONNECT_STATE_DEAD;
|
||
static unsigned short int ptz_update_fifo_read_addr;//循环存储区读地址标记
|
||
static unsigned short int ptz_update_fifo_write_addr;//循环存储区写地址标记
|
||
|
||
//static UpdateFileHead ptz_update_file_head;//升级文件头
|
||
static UpdateFileHead ptz_update_file_head_inf;//升级文件头
|
||
|
||
//用以保存接收到的升级frame的状态,
|
||
//每一位对应一个frame,如果对应的帧已经接收成功,则把这一位设置起来
|
||
//用frame_bit_map的每一位保存每一帧升级数据的接收保存状态
|
||
static unsigned char update_frame_bit_map[256];//升级状态存储区
|
||
static int update_bit_map_count = 0; //总共有多少bit
|
||
static int update_byte_map_count = 0;//总共有多少个byte
|
||
|
||
static unsigned char update_state;//云台升级状态
|
||
|
||
//升级补包表
|
||
static u_int16_t update_retrans_table_buff[MAX_RETRANS_TABLE_LEN+1];
|
||
static UpdateRetransTable *update_retrans_table = (UpdateRetransTable *)update_retrans_table_buff;
|
||
|
||
//文件校验
|
||
static u_int8_t flash_read_buff[256]; //片外flash读取的buffer
|
||
static u_int8_t flash_read_buff2[256];
|
||
static u_int8_t flash_read_buff3[256];
|
||
|
||
static u_int16_t feeddog_num = 0;
|
||
|
||
|
||
|
||
//UDP环形缓冲区的地址编号计算函数,如果到达唤醒缓冲区的尾部,将绕回到头部
|
||
static unsigned char ptz_update_fifo_addring(unsigned short int i)
|
||
{
|
||
return ((i + 1) == UPDATE_BUFF_FIFO_NUM) ? 0 : i+1;
|
||
}
|
||
|
||
//UDP环形缓冲区写入数据
|
||
static void ptz_update_fifo_write_data()
|
||
{
|
||
//把原来的数据清除
|
||
memset(&urfb[ptz_update_fifo_write_addr], 0, sizeof(urfb[ptz_update_fifo_write_addr]));
|
||
|
||
//保存数据,保存有效数据长度
|
||
memcpy(&urfb[ptz_update_fifo_write_addr], &udrb, sizeof(udrb));
|
||
ptz_update_fifo_write_addr = ptz_update_fifo_addring(ptz_update_fifo_write_addr);
|
||
}
|
||
|
||
|
||
//UDP环形缓冲区读出数据
|
||
static UpdateRecvFifoBuff ptz_update_fifo_read_data()
|
||
{
|
||
UpdateRecvFifoBuff fifo_data;
|
||
fifo_data = urfb[ptz_update_fifo_read_addr];
|
||
ptz_update_fifo_read_addr = ptz_update_fifo_addring(ptz_update_fifo_read_addr);
|
||
return fifo_data;
|
||
}
|
||
|
||
//效验码计算
|
||
static unsigned short int ptz_update_calc_frame_crc16( unsigned char *PuchMsg,unsigned int usDataLen)
|
||
{
|
||
unsigned char uch_crc_h; //high byte of CRC initialized
|
||
unsigned char uch_crc_l; //low byte of CRC initialized
|
||
unsigned short int uIndex; //will index into CRC lookup table
|
||
|
||
uch_crc_h=0xFF;
|
||
uch_crc_l=0xFF;
|
||
|
||
while(usDataLen--)
|
||
{
|
||
//calculate the CRC
|
||
uIndex = uch_crc_h^(unsigned char)(*PuchMsg++);
|
||
uch_crc_h = uch_crc_l^auch_crc_h[uIndex];
|
||
uch_crc_l = auch_crc_l[uIndex];
|
||
}
|
||
return(uch_crc_h <<8|uch_crc_l);
|
||
}
|
||
|
||
|
||
//应用升级包数据片写入片外flash缓存空间,空间必须先被擦除
|
||
//request是升级包总描述信息,frame是要写入的分片
|
||
static BOOL ptz_update_write_frame_to_flash_buff(UpdateRequest *request, UpdateData *frame)
|
||
{
|
||
u_int32_t offset = UPDATE_FLASH_BUFF_BEGIN_ADDR + request->frame_len * frame->index;
|
||
if((offset + frame->data_len) > UPDATE_FLASH_BUFF_END_ADDR)
|
||
return FALSE;
|
||
|
||
Flash_Write_MorePage(frame->data, offset, frame->data_len);
|
||
return TRUE;
|
||
}
|
||
|
||
//擦除片外flash应用升级包缓存空间,total_len是升级包的长度
|
||
static BOOL ptz_update_erase_flash_buff(unsigned int total_len)
|
||
{
|
||
int i = 0;
|
||
int block_count = total_len / Flash_BLOCKBYTE_LENGTH;
|
||
|
||
if(total_len>UPDATE_FLASH_BUFF_SIZE)
|
||
return FALSE;
|
||
|
||
if(total_len % Flash_BLOCKBYTE_LENGTH)
|
||
block_count++;
|
||
|
||
feeddog_num = 0;
|
||
for(i = 0; i<block_count; i++)
|
||
{
|
||
Flash_Erase_Block(UPDATE_FLASH_BUFF_BEGIN_BLOCK + i);
|
||
feeddog_num = feeddog_num + 1;
|
||
if(feeddog_num % 2 == 0)
|
||
{
|
||
OSTimeDlyHMSM(0u, 0u, 0u, 2u);
|
||
}
|
||
}
|
||
feeddog_num = 0;
|
||
return TRUE;
|
||
}
|
||
|
||
//初始化frame_bit_map,清空,同时设置总数
|
||
static int ptz_update_init_frame_bit_map(int frame_count)
|
||
{
|
||
int byte_count = frame_count / BITS_PER_UNIT;
|
||
if(frame_count % BITS_PER_UNIT)
|
||
byte_count++;
|
||
if(byte_count > sizeof(update_frame_bit_map))
|
||
{
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
update_bit_map_count = frame_count;
|
||
update_byte_map_count = byte_count;
|
||
memset(update_frame_bit_map, 0, sizeof(update_frame_bit_map));
|
||
return update_byte_map_count;
|
||
}
|
||
}
|
||
|
||
//设置序号为index的帧对应的bit_map
|
||
static BOOL ptz_update_set_frame_bit_map(int index)
|
||
{
|
||
if(index > update_bit_map_count)//index是从0开始的
|
||
return FALSE;
|
||
int byte_offset = index / BITS_PER_UNIT;
|
||
int bit_offset = index % BITS_PER_UNIT;
|
||
update_frame_bit_map[byte_offset] |= (0x01<<bit_offset);
|
||
return TRUE;
|
||
}
|
||
|
||
//根据bit_map返回补包表,参数max_count传入表中能保存的最大记录数
|
||
static BOOL ptz_update_get_upgrade_retrans_table(UpdateRequest *request_info, UpdateRetransTable *table, int max_count)
|
||
{
|
||
int byte_offset = 0;
|
||
int bit_offset = 0;
|
||
int index = 0;
|
||
table->count = 0;
|
||
memset(update_retrans_table_buff, 0, sizeof(update_retrans_table_buff));
|
||
for(byte_offset= 0; byte_offset < update_byte_map_count; byte_offset++)
|
||
{
|
||
for(bit_offset = 0; bit_offset < BITS_PER_UNIT; bit_offset++)
|
||
{
|
||
if(((0x01 << bit_offset) & update_frame_bit_map[byte_offset]) == 0) //该帧未成功收到
|
||
{
|
||
if(table->count >= max_count) //超出返回容量
|
||
return FALSE;
|
||
table->index[table->count] = index;
|
||
table->count++;
|
||
}
|
||
index++;
|
||
if(index >= request_info->frame_count)
|
||
return TRUE;
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
static void ptz_update_CRC16_init(CPU_INT16U *crc16)
|
||
{
|
||
*crc16 = 0xFFFF;
|
||
}
|
||
|
||
|
||
static CPU_INT16U ptz_update_CRC16( CPU_INT08U *PuchMsg,CPU_INT32U usDataLen)
|
||
{
|
||
CPU_INT08U uchCRCHi; //high byte of CRC initialized
|
||
CPU_INT08U uchCRCLo; //low byte of CRC initialized
|
||
CPU_INT16U uIndex; //will index into CRC lookup table
|
||
|
||
uchCRCHi=0xFF;
|
||
uchCRCLo=0xFF;
|
||
|
||
while(usDataLen--)
|
||
{
|
||
//calculate the CRC
|
||
uIndex = uchCRCHi^(CPU_INT08U)(*PuchMsg++);
|
||
uchCRCHi = uchCRCLo^auch_crc_h[uIndex];
|
||
uchCRCLo = auch_crc_l[uIndex];
|
||
}
|
||
return(uchCRCHi <<8|uchCRCLo);
|
||
}
|
||
|
||
static void ptz_update_CRC16_update(CPU_INT16U *crc16, CPU_INT08U *PuchMsg,CPU_INT32U usDataLen)
|
||
{
|
||
CPU_INT08U uchCRCHi; //high byte of CRC initialized
|
||
CPU_INT08U uchCRCLo; //low byte of CRC initialized
|
||
CPU_INT16U uIndex; //will index into CRC lookup table
|
||
|
||
uchCRCHi = (*crc16) >> 8;
|
||
uchCRCLo = (*crc16) & 0xFF;
|
||
|
||
while(usDataLen--)
|
||
{
|
||
uIndex = uchCRCHi^(CPU_INT08U)(*PuchMsg++);
|
||
uchCRCHi = uchCRCLo^auch_crc_h[uIndex];
|
||
uchCRCLo = auch_crc_l[uIndex];
|
||
}
|
||
|
||
*crc16 = (uchCRCHi <<8|uchCRCLo);
|
||
}
|
||
|
||
static u_int16_t _flash_buff_crc16(u_int32_t offset, u_int32_t len)
|
||
{
|
||
u_int16_t ret;
|
||
u_int32_t read_len;
|
||
ptz_update_CRC16_init(&ret);
|
||
feeddog_num = 0;
|
||
while(len)
|
||
{
|
||
if(len > sizeof(flash_read_buff))
|
||
read_len = sizeof(flash_read_buff);
|
||
else
|
||
read_len = len;
|
||
|
||
Flash_Read(flash_read_buff, offset, read_len);
|
||
ptz_update_CRC16_update(&ret, flash_read_buff, read_len);
|
||
len -= read_len;
|
||
offset += read_len;
|
||
feeddog_num = feeddog_num + 1;
|
||
if(feeddog_num % 20 == 0)
|
||
{
|
||
OSTimeDlyHMSM(0u, 0u, 0u, 5u);
|
||
}
|
||
}
|
||
feeddog_num = 0;
|
||
return ret;
|
||
}
|
||
|
||
//检验片外flash缓存空间中的应用升级包的CRC是否正确
|
||
//total_len是升级包的总长度,包括结尾的crc16
|
||
static BOOL ptz_update_flash_buff_file_crc_OK(u_int32_t total_len)
|
||
{
|
||
u_int16_t crc_calc = 0;
|
||
u_int16_t crc_read = 0;
|
||
|
||
if(total_len < sizeof(crc_calc))
|
||
return FALSE;
|
||
|
||
crc_calc = flash_buff_crc16(total_len-2);
|
||
|
||
Flash_Read((u_int8_t *)&crc_read, UPDATE_FLASH_BUFF_BEGIN_ADDR + total_len - sizeof(crc_calc), sizeof(crc_calc));
|
||
return crc_calc == crc_read;
|
||
}
|
||
|
||
|
||
|
||
void ptz_update_complete_frame_packet(UpdateFrame *pack)
|
||
{
|
||
pack->frame_type = UPDATE_FRAME_TYPE_SEND;
|
||
*(u_int16_t *)(&pack->data[pack->data_len]) = ptz_update_CRC16((u_int8_t *)pack, UPDATE_FRAME_SIZE(pack) - sizeof(u_int16_t));
|
||
}
|
||
|
||
|
||
//计算chcksum
|
||
static u_int8_t ptz_check_sum(u_int8_t *p, int len)
|
||
{
|
||
u_int8_t ret = 0;
|
||
int i = 0;
|
||
|
||
for(; i<len; i++)
|
||
{
|
||
ret += p[i];
|
||
}
|
||
return (~ret)+1;
|
||
}
|
||
|
||
//检查片内升级包头的checksum
|
||
static u_int8_t ptz_update_file_head_checksum_OK(UpdateFileHead *file_head)
|
||
{
|
||
return ptz_check_sum((u_int8_t *)file_head, (u_int8_t *)(&file_head->head_checksum) - (u_int8_t *)file_head)
|
||
== file_head->head_checksum;
|
||
}
|
||
|
||
|
||
//校验片外存储器中缓存的升级包的完整性
|
||
static BOOL ptz_update_file_head_verify(u_int32_t total_len, UpdateFileHead *file_head)
|
||
{
|
||
Flash_Read((u_int8_t *)file_head, UPDATE_FLASH_BUFF_BEGIN_ADDR, sizeof(*file_head));
|
||
|
||
//检查头的checksum
|
||
if(!ptz_update_file_head_checksum_OK(file_head))
|
||
return FALSE;
|
||
|
||
//数据长度确认
|
||
if(file_head->data_len != (total_len - sizeof(u_int16_t) - sizeof(*file_head)))
|
||
return FALSE;
|
||
|
||
//起始标志检查
|
||
if(file_head->flag != UPDATE_RELEASE_FILE_FLAG)
|
||
return FALSE;
|
||
|
||
//头长度检验
|
||
if(file_head->head_len != sizeof(*file_head))
|
||
return FALSE;
|
||
|
||
//文件类型检验 boot app cert key cfg_file
|
||
if((file_head->file_type != UPDATE_FILE_TYPE_NW_INFO) && (file_head->file_type != UPDATE_FILE_TYPE_APP) && (file_head->file_type != UPDATE_FILE_TYPE_BOOT_LOADER) && (file_head->file_type != UPDATE_FILE_TYPE_CERT) && (file_head->file_type != UPDATE_FILE_TYPE_PUB_KEY)&& (file_head->file_type != UPDATE_FILE_TYPE_CFG_FILE) && ((file_head->file_type != UPDATE_FILE_TYPE_CFG_IP)))
|
||
return FALSE;
|
||
|
||
//文件格式版本
|
||
if(file_head->file_format_ver != 1)
|
||
return FALSE;
|
||
|
||
if(file_head->file_type == UPDATE_FILE_TYPE_APP){ //App
|
||
//烧写地址检验
|
||
if(file_head->addr < (UPDATE_APP_ADDR_BEGIN - APP_ADD_BEGIN_OFFEST))
|
||
return FALSE;
|
||
//空间检验
|
||
if((file_head->addr + file_head->data_len) > (UPDATE_APP_ADDR_END - APP_ADD_BEGIN_OFFEST))
|
||
return FALSE;
|
||
}else if(file_head->file_type == UPDATE_FILE_TYPE_BOOT_LOADER){ //Bootloader
|
||
//烧写地址检验
|
||
if(file_head->addr != 0) //bootloader必须以0为起始地址
|
||
return FALSE;
|
||
//空间检验
|
||
if((file_head->addr + file_head->data_len) > UPDATE_BOOTLOADER_ADDR_END)
|
||
return FALSE;
|
||
}else if(file_head->file_type == UPDATE_FILE_TYPE_CERT){//CERT
|
||
//烧写地址
|
||
if(file_head->addr < UPDATE_CERT_ADDR_BEGIN)
|
||
return FALSE;
|
||
//空间检验
|
||
if((file_head->addr + file_head->data_len) > UPDATE_CERT_ADDR_END)
|
||
return FALSE;
|
||
}else if(file_head->file_type == UPDATE_FILE_TYPE_PUB_KEY){//KEY
|
||
//烧写地址
|
||
if(file_head->addr < UPDATE_KEY_ADDR_BEGIN)
|
||
return FALSE;
|
||
//空间检验
|
||
if((file_head->addr + file_head->data_len) > UPDATE_KEY_ADDR_END)
|
||
return FALSE;
|
||
}else if(file_head->file_type == UPDATE_FILE_TYPE_CFG_FILE){//CFG FILE
|
||
//烧写地址
|
||
if(file_head->addr < UPDATE_CFG_FILE_ADDR_BEGIN)
|
||
return FALSE;
|
||
//空间检验
|
||
if((file_head->addr + file_head->data_len) > UPDATE_CFG_FILE_ADDR_END)
|
||
return FALSE;
|
||
}else if (file_head->file_type == UPDATE_FILE_TYPE_CFG_IP){//CFG IP
|
||
//烧写地址
|
||
if(file_head->addr < UPDATE_CFG_IP_ADDR_BEGIN)
|
||
return FALSE;
|
||
//空间检验
|
||
if((file_head->addr + file_head->data_len) > UPDATE_CFG_IP_ADDR_END)
|
||
return FALSE;
|
||
}else if (file_head->file_type == UPDATE_FILE_TYPE_NW_INFO){//NW INFO
|
||
//烧写地址
|
||
if(file_head->addr < UPDATE_CFG_NW_INFO_ADDR_BEGIN)
|
||
return FALSE;
|
||
//空间检验
|
||
if((file_head->addr + file_head->data_len) > UPDATE_CFG_NW_INFO_ADDR_END)
|
||
return FALSE;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
//擦除应用程序在片内rom中的存储空间
|
||
//如果是应用app/bootloader擦除片内flash.
|
||
//如果是cert--/key/cfg片外flash
|
||
static BOOL ptz_update_program_flash_erase(UpdateFileHead *file_head)
|
||
{
|
||
//int i = 0;
|
||
u_int32_t total_len = file_head->data_len;
|
||
//int sector_begin = file_head->addr / UPDATE_ON_CHIP_FLASH_SECTOR_SIZE;
|
||
//int sector_count = total_len / UPDATE_ON_CHIP_FLASH_SECTOR_SIZE;
|
||
|
||
if(file_head->file_type == UPDATE_FILE_TYPE_APP)
|
||
{
|
||
if((file_head->addr + total_len) > UPDATE_APP_ADDR_END)
|
||
{
|
||
return FALSE;
|
||
}
|
||
// return TRUE;
|
||
if(1 == OnChip_Flash_erase_sector(APP_PKG_HEAD_SECTOR_BEGIN))
|
||
{
|
||
term_printf("\n 擦除片内rom失败,APP_PKG_HEAD_SECTOR_BEGIN \r\n");
|
||
return FALSE;
|
||
}
|
||
if(1 == OnChip_Flash_erase_sector(CTL_SECTOR_NUMBER_4))
|
||
{
|
||
term_printf("\n 擦除片内rom失败,CTL_SECTOR_NUMBER_4 \r\n");
|
||
return FALSE;
|
||
}
|
||
if(1 == OnChip_Flash_erase_sector(CTL_SECTOR_NUMBER_5))
|
||
{
|
||
term_printf("\n 擦除片内rom失败,CTL_SECTOR_NUMBER_5 \r\n");
|
||
return FALSE;
|
||
}
|
||
// OnChip_Flash_erase_sector(UPDATE_APP_PKG_HEAD_SECTOR_BEGIN);//同时为升级包的头信息删除一个sector
|
||
// if(total_len % UPDATE_ON_CHIP_FLASH_SECTOR_SIZE)
|
||
// sector_count++;
|
||
//
|
||
// for(i = 0; i<sector_count; i++){
|
||
// OnChip_Flash_erase_sector(sector_begin + i);
|
||
// }
|
||
|
||
}
|
||
else if(file_head->file_type == UPDATE_FILE_TYPE_PUB_KEY)
|
||
{
|
||
if((file_head->addr + total_len) > UPDATE_KEY_ADDR_END)
|
||
return FALSE;
|
||
Flash_Erase_Sector(UPDATE_EXT_FLASH_BLOCK_NUM,UPDATE_KEY_HEAD_SECTOR_BEGIN);
|
||
Flash_Erase_Sector(UPDATE_EXT_FLASH_BLOCK_NUM,UPDATE_KEY_SECTOR_BEGIN);
|
||
}
|
||
else if(file_head->file_type == UPDATE_FILE_TYPE_CERT)
|
||
{
|
||
if((file_head->addr + total_len) > UPDATE_CERT_ADDR_END)
|
||
return FALSE;
|
||
Flash_Erase_Sector(UPDATE_EXT_FLASH_BLOCK_NUM,UPDATE_CERT_HEAD_SECTOR_BEGIN);
|
||
Flash_Erase_Sector(UPDATE_EXT_FLASH_BLOCK_NUM,UPDATE_CERT_SECTOR_BEGIN);
|
||
}
|
||
else if(file_head->file_type == UPDATE_FILE_TYPE_CFG_FILE)
|
||
{
|
||
if((file_head->addr + total_len) > UPDATE_CFG_FILE_ADDR_END)
|
||
return FALSE;
|
||
Flash_Erase_Sector(UPDATE_EXT_FLASH_BLOCK_NUM,UPDATE_CFG_FILE_HEAD_SECTOR_BEGIN);
|
||
Flash_Erase_Sector(UPDATE_EXT_FLASH_BLOCK_NUM,UPDATE_CFG_FILE_SECTOR_BEGIN);
|
||
}
|
||
else if(file_head->file_type == UPDATE_FILE_TYPE_CFG_IP)
|
||
{//ip配置
|
||
if((file_head->addr + total_len) > UPDATE_CFG_IP_ADDR_END)
|
||
return FALSE;
|
||
Flash_Erase_Sector(UPDATE_EXT_FLASH_BLOCK_NUM16,UPDATE_CFG_IP_HEAD_SECTOR_BEGIN);
|
||
Flash_Erase_Sector(UPDATE_EXT_FLASH_BLOCK_NUM16,UPDATE_CFG_IP_SECTOR_BEGIN);
|
||
}
|
||
else if(file_head->file_type == UPDATE_FILE_TYPE_NW_INFO)
|
||
{//南网台帐信息
|
||
if((file_head->addr + total_len) > UPDATE_CFG_NW_INFO_ADDR_END)
|
||
return FALSE;
|
||
Flash_Erase_Sector(UPDATE_EXT_FLASH_BLOCK_NUM16,UPDATE_CFG_NW_INFO_HEAD_SECTOR_BEGIN);
|
||
Flash_Erase_Sector(UPDATE_EXT_FLASH_BLOCK_NUM16,UPDATE_CFG_NW_INFO_SECTOR_BEGIN);
|
||
Flash_Erase_Sector(UPDATE_EXT_FLASH_BLOCK_NUM16,UPDATE_CFG_NW_INFO_SECTOR_BEGIN+1);
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
//app/booter从片外存储器将升级数据复制到片内rom
|
||
//cert/key/cfg_file 从片外缓冲区复制到片外另外区域
|
||
static BOOL ptz_update_program_flash_copy(UpdateFileHead *file_head)
|
||
{
|
||
u_int32_t read_len;
|
||
u_int32_t read_addr = UPDATE_FLASH_BUFF_BEGIN_ADDR + file_head->head_len;
|
||
u_int32_t len = file_head->data_len + sizeof(u_int16_t); //复制内容包括结尾的crc16
|
||
// u_int32_t write_addr = file_head->addr;
|
||
|
||
u_int32_t write_addr = APP_ADDR_BEGIN;
|
||
char erase_state=0;
|
||
|
||
if (file_head->file_type == UPDATE_FILE_TYPE_APP)
|
||
{//应用程序
|
||
// return TRUE;
|
||
while(len)
|
||
{//写程序
|
||
if(erase_state == 0)
|
||
{
|
||
erase_state++;
|
||
if(1 == OnChip_Flash_erase_sector(CTL_SECTOR_NUMBER_4))
|
||
{
|
||
term_printf("\n 擦除片内rom失败,CTL_SECTOR_NUMBER_4 \r\n");
|
||
return FALSE;
|
||
}
|
||
}
|
||
if(len > sizeof(flash_read_buff))
|
||
{
|
||
read_len = sizeof(flash_read_buff);
|
||
}else{
|
||
read_len = len;
|
||
}
|
||
memset(flash_read_buff,0,sizeof(flash_read_buff));
|
||
Flash_Read(flash_read_buff, read_addr, read_len);
|
||
// FeedDog();
|
||
// term_printf("\n 程序写入成功,地址write_addr = %d \r\n",flash_read_buff);
|
||
if(OnChip_Flash_write_byte(write_addr, read_len, flash_read_buff) != 0)
|
||
{
|
||
term_printf("\n 程序写入失败,地址write_addr = \r\n",write_addr);
|
||
return FALSE;
|
||
|
||
}
|
||
|
||
OnChip_Flash_read_in_add(write_addr, read_len, (uint8_t*)&flash_read_buff3);
|
||
|
||
if (memcmp(flash_read_buff, flash_read_buff3, read_len) != 0)
|
||
{
|
||
term_printf("\n write rom error to different \r\n");
|
||
return FALSE;
|
||
}
|
||
len -= read_len;
|
||
read_addr += read_len;
|
||
write_addr += read_len;
|
||
if(erase_state == 1 && write_addr >= 0x801FFFF)
|
||
{
|
||
erase_state++;
|
||
if(1 == OnChip_Flash_erase_sector(CTL_SECTOR_NUMBER_5))
|
||
{
|
||
term_printf("\n 擦除片内rom失败,CTL_SECTOR_NUMBER_5 \r\n");
|
||
return FALSE;
|
||
}
|
||
}
|
||
}
|
||
term_printf("\n 程序写入成功,地址write_addr = %d \r\n",write_addr);
|
||
// if(write_addr >= 0x8040c00)
|
||
// {
|
||
// term_printf("\n write_addr == 0x8040c00 \r\n");
|
||
// }
|
||
// OnChip_Flash_erase_sector(APP_PKG_HEAD_SECTOR_BEGIN);
|
||
if (OnChip_Flash_write_byte(APP_PKG_HEAD_BEGIN, sizeof(*file_head), (u_int8_t *)file_head) != 0)//写头
|
||
{
|
||
term_printf("\n 文件头写入失败,地址write_addr = \r\n",APP_PKG_HEAD_BEGIN);
|
||
return FALSE;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
feeddog_num = 0;
|
||
while(len)
|
||
{
|
||
if(len > sizeof(flash_read_buff))
|
||
read_len = sizeof(flash_read_buff);
|
||
else
|
||
read_len = len;
|
||
Flash_Read(flash_read_buff, read_addr, read_len);
|
||
Flash_Write_Page(flash_read_buff,write_addr,read_len);
|
||
len -= read_len;
|
||
read_addr += read_len;
|
||
write_addr += read_len;
|
||
feeddog_num = feeddog_num + 1;
|
||
if(feeddog_num % 20 == 0)
|
||
{
|
||
OSTimeDlyHMSM(0u, 0u, 0u, 5u);
|
||
}
|
||
}
|
||
feeddog_num = 0;
|
||
if (file_head->file_type == UPDATE_FILE_TYPE_PUB_KEY)
|
||
{//公钥
|
||
Flash_Write_Page((u_int8_t *)file_head,UPDATE_KEY_HEAD_BEGIN,sizeof(*file_head));
|
||
}
|
||
else if(file_head->file_type == UPDATE_FILE_TYPE_CERT)
|
||
{//证书
|
||
Flash_Write_Page((u_int8_t *)file_head,UPDATE_CERT_HEAD_BEGIN,sizeof(*file_head));
|
||
}
|
||
else if(file_head->file_type == UPDATE_FILE_TYPE_CFG_FILE)
|
||
{//配置文件
|
||
Flash_Write_Page((u_int8_t *)file_head,UPDATE_CFG_FILE_HEAD_BEGIN,sizeof(*file_head));
|
||
}
|
||
else if(file_head->file_type == UPDATE_FILE_TYPE_CFG_IP)
|
||
{//IP配置文件
|
||
Flash_Write_Page((u_int8_t *)file_head,UPDATE_CFG_IP_HEAD_BEGIN,sizeof(*file_head));
|
||
}
|
||
else if(file_head->file_type == UPDATE_FILE_TYPE_NW_INFO)
|
||
{//南网台帐
|
||
Flash_Write_Page((u_int8_t *)file_head,UPDATE_CFG_NW_INFO_HEAD_BEGIN,sizeof(*file_head));
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
//校验已写入片内rom的应用程序包
|
||
//通过读出片外flash内容与片内内容完全比较的方式校验
|
||
static BOOL ptz_update_program_app_verify(u_int8_t file_type)
|
||
{
|
||
u_int32_t read_len, len;
|
||
u_int32_t read_addr = UPDATE_FLASH_BUFF_BEGIN_ADDR + sizeof(UpdateFileHead);
|
||
|
||
static UpdateFileHead file_head;
|
||
static UpdateFileHead file_head2;
|
||
u_int32_t app_addr = 0;
|
||
|
||
memset(&file_head, 0, sizeof(file_head));
|
||
|
||
//首先校验头信息
|
||
if (file_type == UPDATE_FILE_TYPE_APP)
|
||
{//APP
|
||
app_addr = UPDATE_APP_ADDR_BEGIN;
|
||
Flash_Read((u_int8_t *)&file_head, UPDATE_FLASH_BUFF_BEGIN_ADDR, sizeof(file_head));
|
||
if(memcmp(&file_head, (u_int8_t *)UPDATE_APP_PKG_HEAD_BEGIN, sizeof(file_head)) != 0)
|
||
return FALSE;
|
||
len = file_head.data_len + sizeof(u_int16_t); //校验包括crc16内容
|
||
while(len){
|
||
if(len > sizeof(flash_read_buff))
|
||
read_len = sizeof(flash_read_buff);
|
||
else
|
||
read_len = len;
|
||
Flash_Read(flash_read_buff, read_addr, read_len);
|
||
|
||
if(memcmp(flash_read_buff, (u_int8_t *)app_addr, read_len) != 0)
|
||
return FALSE;
|
||
|
||
len -= read_len;
|
||
read_addr += read_len;
|
||
app_addr += read_len;
|
||
}
|
||
return TRUE;
|
||
}
|
||
else
|
||
{
|
||
if (file_type == UPDATE_FILE_TYPE_CERT)
|
||
{//CERT
|
||
app_addr = UPDATE_CERT_ADDR_BEGIN;
|
||
Flash_Read((u_int8_t *)&file_head, UPDATE_FLASH_BUFF_BEGIN_ADDR, sizeof(file_head));
|
||
Flash_Read((u_int8_t *)&file_head2, UPDATE_CERT_HEAD_BEGIN, sizeof(file_head2));
|
||
if(memcmp(&file_head,&file_head2, sizeof(file_head)) != 0)
|
||
return FALSE;
|
||
}
|
||
else if(file_type == UPDATE_FILE_TYPE_PUB_KEY)
|
||
{
|
||
app_addr = UPDATE_KEY_ADDR_BEGIN;
|
||
Flash_Read((u_int8_t *)&file_head, UPDATE_FLASH_BUFF_BEGIN_ADDR, sizeof(file_head));
|
||
Flash_Read((u_int8_t *)&file_head2, UPDATE_KEY_HEAD_BEGIN, sizeof(file_head2));
|
||
if (memcmp(&file_head,&file_head2, sizeof(file_head)) != 0)
|
||
return FALSE;
|
||
}
|
||
else if(file_type ==UPDATE_FILE_TYPE_CFG_FILE)
|
||
{
|
||
app_addr = UPDATE_CFG_FILE_ADDR_BEGIN;
|
||
Flash_Read((u_int8_t *)&file_head, UPDATE_FLASH_BUFF_BEGIN_ADDR, sizeof(file_head));
|
||
Flash_Read((u_int8_t *)&file_head2, UPDATE_CFG_FILE_HEAD_BEGIN, sizeof(file_head2));
|
||
if (memcmp(&file_head,&file_head2, sizeof(file_head)) != 0)
|
||
return FALSE;
|
||
}
|
||
else if(file_type ==UPDATE_FILE_TYPE_CFG_IP)
|
||
{
|
||
app_addr = UPDATE_CFG_IP_ADDR_BEGIN;
|
||
Flash_Read((u_int8_t *)&file_head, UPDATE_FLASH_BUFF_BEGIN_ADDR, sizeof(file_head));
|
||
Flash_Read((u_int8_t *)&file_head2, UPDATE_CFG_IP_HEAD_BEGIN, sizeof(file_head2));
|
||
if (memcmp(&file_head,&file_head2, sizeof(file_head)) != 0)
|
||
return FALSE;
|
||
}
|
||
else if(file_type ==UPDATE_FILE_TYPE_NW_INFO)
|
||
{
|
||
app_addr = UPDATE_CFG_NW_INFO_ADDR_BEGIN;
|
||
Flash_Read((u_int8_t *)&file_head, UPDATE_FLASH_BUFF_BEGIN_ADDR, sizeof(file_head));
|
||
Flash_Read((u_int8_t *)&file_head2, UPDATE_CFG_NW_INFO_HEAD_BEGIN, sizeof(file_head2));
|
||
if (memcmp(&file_head,&file_head2, sizeof(file_head)) != 0)
|
||
return FALSE;
|
||
}
|
||
|
||
len = file_head.data_len + sizeof(u_int16_t); //校验包括crc16内容
|
||
feeddog_num = 0;
|
||
while(len)
|
||
{
|
||
if(len > sizeof(flash_read_buff))
|
||
read_len = sizeof(flash_read_buff);
|
||
else
|
||
read_len = len;
|
||
Flash_Read(flash_read_buff, read_addr, read_len);
|
||
Flash_Read(flash_read_buff2,app_addr,read_len);
|
||
if(memcmp(flash_read_buff,flash_read_buff2, read_len) != 0)
|
||
return FALSE;
|
||
len -= read_len;
|
||
read_addr += read_len;
|
||
app_addr += read_len;
|
||
feeddog_num = feeddog_num + 1;
|
||
if(feeddog_num % 20 == 0)
|
||
{
|
||
OSTimeDlyHMSM(0u, 0u, 0u, 5u);
|
||
}
|
||
}
|
||
feeddog_num = 0;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
//校验并把片外flash中缓存的App升级包烧写进片内rom,然后再校验
|
||
static BOOL ptz_update_program_file(u_int32_t total_len)
|
||
{
|
||
static UpdateFileHead file_head;
|
||
|
||
memset(&file_head, 0, sizeof(file_head));
|
||
Flash_Read((u_int8_t *)&file_head, UPDATE_FLASH_BUFF_BEGIN_ADDR, sizeof(file_head));
|
||
|
||
if(!ptz_update_file_head_verify(total_len, &file_head))
|
||
return FALSE;
|
||
|
||
if((file_head.file_type == UPDATE_FILE_TYPE_NW_INFO) ||
|
||
(file_head.file_type == UPDATE_FILE_TYPE_APP) ||
|
||
(file_head.file_type == UPDATE_FILE_TYPE_PUB_KEY) ||
|
||
(file_head.file_type == UPDATE_FILE_TYPE_CERT) ||
|
||
(file_head.file_type == UPDATE_FILE_TYPE_CFG_FILE) ||
|
||
(file_head.file_type == UPDATE_FILE_TYPE_CFG_IP))
|
||
{
|
||
if(!ptz_update_program_flash_erase(&file_head))
|
||
return FALSE;
|
||
|
||
if(!ptz_update_program_flash_copy(&file_head))
|
||
return FALSE;
|
||
|
||
if(!ptz_update_program_app_verify(file_head.file_type))
|
||
return FALSE;
|
||
|
||
}else //不认识的文件类型
|
||
return FALSE;
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
static BOOL ptz_update_burn_bootloader(u_int32_t total_len)
|
||
{
|
||
static UpdateFileHead file_head;
|
||
|
||
memset(&file_head, 0, sizeof(file_head));
|
||
Flash_Read((u_int8_t *)&file_head, UPDATE_FLASH_BUFF_BEGIN_ADDR, sizeof(file_head));
|
||
|
||
if(file_head.file_type == UPDATE_FILE_TYPE_BOOT_LOADER)
|
||
{
|
||
if(!ptz_update_file_head_verify(total_len, &file_head))
|
||
return FALSE;
|
||
|
||
// if(!ptz_update_bootloader_flash_erase(&file_head))
|
||
// return FALSE;
|
||
//
|
||
// if(!ptz_update_bootloader_flash_copy(&file_head))
|
||
// return FALSE;
|
||
//
|
||
// if(!ptz_update_bootloader_verify())
|
||
// return FALSE;
|
||
|
||
|
||
}else
|
||
//不认识的文件类型
|
||
return FALSE;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
//云台向升级端发送升级回复
|
||
static void ptz_send_update_reply(unsigned char pack_type, const void *data, int len)
|
||
{
|
||
//建立一个指针指向发送数据缓冲区
|
||
UpdateFrame *pack = (UpdateFrame *)udsb.data_buff;
|
||
//对发送缓冲区数据清0
|
||
memset(&udsb, 0, sizeof(udsb));
|
||
//数据封包
|
||
pack->flag = UPDATE_FRAME_HEAD_FLAG;//帧头
|
||
pack->data_len = len;//数据长度
|
||
if(data && (len > 0))//判断有无数据
|
||
memcpy(pack->data, data, len);//有数据则装载数据
|
||
memcpy(pack->id, system_info.cmd_id, sizeof(pack->id));//复制设备ID
|
||
pack->frame_type = UPDATE_FRAME_TYPE_SEND;
|
||
pack->pack_type = pack_type;
|
||
//计算数据包总长度
|
||
udsb.data_len = UPDATE_FRAME_SIZE(pack);
|
||
ptz_update_complete_frame_packet(pack);
|
||
//发送数据
|
||
BSP_OS_SemWait(&udp_send_data_mutex, 0u);
|
||
if(ptz_update_communicaton == PTZ_CONNECT_STATE_SUCCESS){
|
||
int ret = sendto(ptz_update_fd, pack, udsb.data_len, 0, (struct sockaddr*)&ptz_update_from, ptz_update_fromlen);
|
||
if(ret == -1){
|
||
ptz_update_communicaton = PTZ_CONNECT_STATE_FAILED;
|
||
close(ptz_update_fd);
|
||
}
|
||
}
|
||
BSP_OS_SemPost(&udp_send_data_mutex);
|
||
}
|
||
|
||
|
||
//云台向指定的升级端发送心跳包ptz_send_update_reply(UPDATE_FRAME_TYPE_KEEP_ALIVE, NULL, 0);
|
||
static void ptz_send_update_heartbeat()
|
||
{
|
||
int ret;
|
||
//建立一个指针指向发送数据缓冲区
|
||
UpdateFrame *pack = (UpdateFrame *)udsb.data_buff;
|
||
//对发送缓冲区数据清0
|
||
memset(&udsb, 0, sizeof(udsb));
|
||
//数据封包
|
||
pack->flag = UPDATE_FRAME_HEAD_FLAG;//帧头
|
||
pack->data_len = 0;//数据长度
|
||
memcpy(pack->id, system_info.cmd_id, sizeof(pack->id));//复制设备ID
|
||
pack->frame_type = UPDATE_FRAME_TYPE_SEND;
|
||
pack->pack_type = UPDATE_FRAME_TYPE_KEEP_ALIVE;
|
||
//计算数据包总长度
|
||
udsb.data_len = UPDATE_FRAME_SIZE(pack);
|
||
ptz_update_complete_frame_packet(pack);
|
||
//发送数据
|
||
BSP_OS_SemWait(&udp_send_data_mutex, 0u);
|
||
if(ptz_update_communicaton == PTZ_CONNECT_STATE_SUCCESS)
|
||
{
|
||
ret = sendto(ptz_update_fd, pack, udsb.data_len, 0, (struct sockaddr*)&ptz_update_serv_a, ptz_update_servlen_a);
|
||
if(ret == -1){
|
||
ptz_update_communicaton = PTZ_CONNECT_STATE_FAILED;
|
||
close(ptz_update_fd);
|
||
BSP_OS_SemPost(&udp_send_data_mutex);
|
||
return;
|
||
}
|
||
|
||
ret = sendto(ptz_update_fd, pack, udsb.data_len, 0, (struct sockaddr*)&ptz_update_serv_b, ptz_update_servlen_b);
|
||
if(ret == -1){
|
||
ptz_update_communicaton = PTZ_CONNECT_STATE_FAILED;
|
||
close(ptz_update_fd);
|
||
BSP_OS_SemPost(&udp_send_data_mutex);
|
||
return;
|
||
}
|
||
|
||
ret = sendto(ptz_update_fd, pack, udsb.data_len, 0, (struct sockaddr*)&ptz_update_serv_c, ptz_update_servlen_c);
|
||
if(ret == -1){
|
||
ptz_update_communicaton = PTZ_CONNECT_STATE_FAILED;
|
||
close(ptz_update_fd);
|
||
BSP_OS_SemPost(&udp_send_data_mutex);
|
||
return;
|
||
}
|
||
|
||
ret = sendto(ptz_update_fd, pack, udsb.data_len, 0, (struct sockaddr*)&ptz_update_serv_d, ptz_update_servlen_d);
|
||
if(ret == -1){
|
||
ptz_update_communicaton = PTZ_CONNECT_STATE_FAILED;
|
||
close(ptz_update_fd);
|
||
BSP_OS_SemPost(&udp_send_data_mutex);
|
||
return;
|
||
}
|
||
}
|
||
BSP_OS_SemPost(&udp_send_data_mutex);
|
||
}
|
||
|
||
|
||
|
||
//升级数据接收
|
||
static void ptz_update_rece_data_task()
|
||
{
|
||
while(1)
|
||
{
|
||
//建立本地连接通道
|
||
if(ptz_update_communicaton != PTZ_CONNECT_STATE_SUCCESS)
|
||
{
|
||
ptz_update_fd = CreateUDPClientSock();
|
||
if(ptz_update_fd != -1)
|
||
{
|
||
// 设置服务器端ip和端口号
|
||
memset(&ptz_update_from, 0, sizeof(struct sockaddr_in));
|
||
ptz_update_local.sin_family = PF_INET;
|
||
// 监听端口
|
||
ptz_update_local.sin_port = htons(PTZ_UPDATE_PORT);
|
||
ptz_update_local.sin_addr.s_addr = INADDR_ANY;
|
||
ptz_update_fromlen = sizeof(ptz_update_from);
|
||
if(0!=bind(ptz_update_fd,(struct sockaddr*)&ptz_update_local,sizeof(ptz_update_local)))
|
||
{
|
||
close(ptz_update_fd);
|
||
}
|
||
else
|
||
{
|
||
ptz_update_communicaton = PTZ_CONNECT_STATE_SUCCESS;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ptz_update_communicaton = PTZ_CONNECT_STATE_FAILED;
|
||
close(ptz_update_fd);
|
||
}
|
||
}
|
||
|
||
if(ptz_update_communicaton == PTZ_CONNECT_STATE_SUCCESS)
|
||
{
|
||
memset(&udrb, 0, sizeof(udrb));//'\0'
|
||
udrb.data_len =
|
||
recvfrom(ptz_update_fd, udrb.data_buff, sizeof(udrb.data_buff), 0, (struct sockaddr*)&ptz_update_from, &ptz_update_fromlen);
|
||
if (udrb.data_len >0)
|
||
{
|
||
//将数据保存到环形缓冲区
|
||
ptz_update_fifo_write_data();
|
||
}
|
||
else
|
||
{
|
||
ptz_update_communicaton = PTZ_CONNECT_STATE_FAILED;
|
||
close(ptz_update_fd);
|
||
}
|
||
}
|
||
OSTimeDlyHMSM(0u, 0u, 0u, 2u);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
//云台升级数据处理
|
||
static void ptz_update_data_process_task()
|
||
{
|
||
static char info_str[256];
|
||
static char kh = 0;
|
||
int count = 0;
|
||
static UpdateFrame* update_frame = (UpdateFrame *)udpb.data_buff;//升级帧
|
||
static UpdateRequest request_info;//升级请求
|
||
static UpdateData* update_data = NULL;//升级具体数据
|
||
|
||
static unsigned char update_active_connect_switch = 0;//主动连接指定升级服务端开关
|
||
static unsigned int update_active_connect_timer = 0;//主动连接指定升级服务端计时
|
||
|
||
while(1)
|
||
{
|
||
#if 1
|
||
//判断循环buff里面是否有未处理的数据
|
||
if(ptz_update_fifo_read_addr != ptz_update_fifo_write_addr)
|
||
{
|
||
|
||
memset(&udpb, 0, sizeof(udpb));
|
||
//从循环buff读取数据
|
||
|
||
// udpb = ptz_update_fifo_read_data();
|
||
udpb = urfb[ptz_update_fifo_read_addr];
|
||
ptz_update_fifo_read_addr = ptz_update_fifo_addring(ptz_update_fifo_read_addr);
|
||
//开始处理数据
|
||
|
||
if(ptz_update_calc_frame_crc16(udpb.data_buff, udpb.data_len - 2) ==
|
||
UPDATE_FRAME_GET_CRC16(update_frame)) //首先判断每一帧的校验码是否正确
|
||
{
|
||
|
||
if(update_frame->frame_type == UPDATE_FRAME_TYPE_RECE &&//判断帧类型是不是接收数据
|
||
update_frame->flag == UPDATE_FRAME_HEAD_FLAG)//判断帧头是否正确
|
||
{
|
||
switch(update_frame->pack_type)
|
||
{
|
||
case UPDATE_FRAME_TYPE_KEEP_ALIVE: //0X01 用以保持连接
|
||
ptz_send_update_reply(UPDATE_FRAME_TYPE_KEEP_ALIVE, NULL, 0);
|
||
break;
|
||
|
||
case UPDATE_FRAME_TYPE_GET_DEVICE_INFO: //0X02 用于获取设备信息,包括软硬件版本等
|
||
memset((u_int8_t *)&ptz_update_file_head_inf, 0, sizeof(ptz_update_file_head_inf));
|
||
memcpy((u_int8_t *)&ptz_update_file_head_inf, (u_int8_t *)UPDATE_APP_PKG_HEAD, sizeof(ptz_update_file_head_inf));
|
||
//校验包头,若干片内没有头信息,则为出厂程序,头信息赋初始值
|
||
|
||
//检查头的checksum
|
||
if(!ptz_update_file_head_checksum_OK(&ptz_update_file_head_inf))
|
||
{
|
||
ptz_update_file_head_inf.hardware_type[0] = HARD_WARE_TYPE_DEFAULT_K;
|
||
ptz_update_file_head_inf.hardware_type[1] = HARD_WARE_TYPE_DEFAULT_6;
|
||
ptz_update_file_head_inf.hardware_ver = 1;
|
||
ptz_update_file_head_inf.software_ver = 1;
|
||
ptz_update_file_head_inf.addr = 0x00010000;
|
||
}
|
||
|
||
|
||
ptz_send_update_reply(UPDATE_FRAME_TYPE_GET_DEVICE_INFO, (u_int8_t *)&ptz_update_file_head_inf, sizeof(ptz_update_file_head_inf));
|
||
break;
|
||
|
||
case UPDATE_FRAME_TYPE_RESET_DEVICE: //0X03 设备复位
|
||
ptz_hori_stop(0);
|
||
ptz_vert_stop(0);
|
||
count = sprintf(info_str, "OK");
|
||
ptz_send_update_reply(UPDATE_FRAME_TYPE_RESET_DEVICE, info_str, count);
|
||
OSTimeDlyHMSM(0u, 0u, 0u, 10u);
|
||
GD32_RESET();
|
||
break;
|
||
|
||
case UPDATE_FRAME_TYPE_BOOT_APP: //0X04 要求设备载入应用(直接复位)
|
||
ptz_hori_stop(0);
|
||
ptz_vert_stop(0);
|
||
count = sprintf(info_str, "OK");
|
||
ptz_send_update_reply(UPDATE_FRAME_TYPE_BOOT_APP, info_str, count);
|
||
OSTimeDlyHMSM(0u, 0u, 0u, 10u);
|
||
GD32_RESET();
|
||
break;
|
||
|
||
case UPDATE_FRAME_TYPE_UPGRADE_REQ: //0X05 升级设备请求,数据内容是一个upgrade_request结构
|
||
memset(&request_info, 0, sizeof(request_info));
|
||
update_bit_map_count = 0; //总共有多少bit,每一位bit存储每一帧接收的状态
|
||
update_byte_map_count = 0;//总共有多少个byte,存储所有帧接收的状态要用多少个字节
|
||
//提取升级文件头
|
||
memcpy(&request_info, update_frame->data, sizeof(request_info));
|
||
//判断存储每一个帧的状态需要多少位BIT,多少个字节BYTE
|
||
if(!ptz_update_init_frame_bit_map(request_info.frame_count))
|
||
{
|
||
count = sprintf(info_str, "准备接收数据出错(init_frame_bit_map)!");
|
||
ptz_send_update_reply(UPDATE_FRAME_TYPE_ERROR, info_str, count);
|
||
break;
|
||
}
|
||
//判断升级数据包是否超出设定的片外FLASH存储的大小
|
||
if(!ptz_update_erase_flash_buff(request_info.total_len))
|
||
{
|
||
count = sprintf(info_str, "准备接收数据出错(erase_upgrad_flash_buff)!");
|
||
ptz_send_update_reply(UPDATE_FRAME_TYPE_ERROR, info_str, count);
|
||
break;
|
||
}
|
||
update_state = UPDATE_STATE_UPGRADE_DATA_TRANS;
|
||
ptz_send_update_reply(UPDATE_FRAME_TYPE_UPGRADE_REQ, &request_info, sizeof(request_info));
|
||
break;
|
||
|
||
case UPDATE_FRAME_TYPE_UPGRADE_DATE: //0X06 升级设备数据,数据内容是一个upgrade_frame结构
|
||
update_data = (UpdateData*)update_frame->data;
|
||
if(update_state != UPDATE_STATE_UPGRADE_DATA_TRANS)
|
||
{
|
||
count = sprintf(info_str, "设备未进入接收状态,请先发送升级请求包!");
|
||
ptz_send_update_reply(UPDATE_FRAME_TYPE_ERROR, info_str, count);
|
||
break;
|
||
}
|
||
if(!ptz_update_write_frame_to_flash_buff(&request_info, update_data))
|
||
{
|
||
count = sprintf(info_str, "升级数据写入失败!");
|
||
ptz_send_update_reply(UPDATE_FRAME_TYPE_ERROR, info_str, count);
|
||
break;
|
||
}
|
||
if(!ptz_update_set_frame_bit_map(update_data->index))
|
||
{
|
||
count = sprintf(info_str, "升级帧状态保存总数溢出");
|
||
ptz_send_update_reply(UPDATE_FRAME_TYPE_ERROR, info_str, count);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case UPDATE_FRAME_TYPE_UPGRADE_FINISH: //0X07 升级设备结束,SRV->Device数据内容空
|
||
if(update_state != UPDATE_STATE_UPGRADE_DATA_TRANS)
|
||
{
|
||
count = sprintf(info_str, "设备未进入接收状态,请先发送升级请求包!");
|
||
ptz_send_update_reply(UPDATE_FRAME_TYPE_ERROR, info_str, count);
|
||
break;
|
||
}
|
||
//判断哪些帧接收失败
|
||
if(!ptz_update_get_upgrade_retrans_table(&request_info, update_retrans_table, MAX_RETRANS_TABLE_LEN))
|
||
{
|
||
count = sprintf(info_str, "准备重传数据出错!");
|
||
ptz_send_update_reply(UPDATE_FRAME_TYPE_ERROR, info_str, count);
|
||
update_state = UPDATE_STATE_IDEL;
|
||
break;
|
||
}
|
||
//判断是否需要重传
|
||
if(update_retrans_table->count > 0)
|
||
{
|
||
ptz_send_update_reply(UPDATE_FRAME_TYPE_UPGRADE_FINISH, update_retrans_table, UPDATE_RETRANS_TABLE_SIZE(update_retrans_table));
|
||
update_state = UPDATE_STATE_UPGRADE_DATA_TRANS;
|
||
break;
|
||
}
|
||
//校验升级包文件
|
||
if(!ptz_update_flash_buff_file_crc_OK(request_info.total_len))
|
||
{
|
||
count = sprintf(info_str, "升级包CRC校验失败!");
|
||
ptz_send_update_reply(UPDATE_FRAME_TYPE_ERROR, info_str, count);
|
||
update_state = UPDATE_STATE_IDEL;
|
||
break;
|
||
}
|
||
//将bootloader存入单片机内部的RAM
|
||
if(request_info.file_head.file_type == UPDATE_FILE_TYPE_BOOT_LOADER)
|
||
{
|
||
// if(!ptz_update_burn_bootloader(request_info.total_len))
|
||
// {
|
||
// count = sprintf(info_str, "升级失败!!!!");
|
||
// ptz_send_update_reply(UPDATE_FRAME_TYPE_ERROR, info_str, count);
|
||
// update_state = UPDATE_STATE_IDEL;
|
||
// break;
|
||
// }
|
||
ptz_send_update_reply(UPDATE_FRAME_TYPE_UPGRADE_FINISH, update_retrans_table, UPDATE_RETRANS_TABLE_SIZE(update_retrans_table));
|
||
update_state = UPDATE_STATE_IDEL;
|
||
break;
|
||
}
|
||
//其他文件升级,包含应用程序,配置文件等
|
||
if(request_info.file_head.file_type != UPDATE_FILE_TYPE_BOOT_LOADER)
|
||
{
|
||
// if(!ptz_update_program_file(request_info.total_len))
|
||
// {
|
||
// count = sprintf(info_str, "升级包失败!!!!");
|
||
// ptz_send_update_reply(UPDATE_FRAME_TYPE_ERROR, info_str, count);
|
||
// update_state = UPDATE_STATE_IDEL;
|
||
// break;
|
||
// }
|
||
ptz_send_update_reply(UPDATE_FRAME_TYPE_UPGRADE_FINISH, update_retrans_table, UPDATE_RETRANS_TABLE_SIZE(update_retrans_table));
|
||
update_state = UPDATE_STATE_IDEL;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
#endif
|
||
|
||
//初始化指定升级服务端的IP和端口
|
||
if(ptz_update_communicaton == PTZ_CONNECT_STATE_SUCCESS)
|
||
{
|
||
if(update_active_connect_switch == 0)
|
||
{
|
||
//初始化指定升级服务端的IP和端口
|
||
ptz_update_serv_a.sin_family = PF_INET;
|
||
ptz_update_serv_a.sin_port = htons(PTZ_UPDATE_SERV_PORT_A);
|
||
ptz_update_serv_a.sin_addr.s_addr = inet_addr(PTZ_UPDATE_SERV_IP_A);
|
||
ptz_update_servlen_a = sizeof(ptz_update_serv_a);
|
||
|
||
ptz_update_serv_b.sin_family = PF_INET;
|
||
ptz_update_serv_b.sin_port = htons(PTZ_UPDATE_SERV_PORT_A);
|
||
ptz_update_serv_b.sin_addr.s_addr = inet_addr(PTZ_UPDATE_SERV_IP_B);
|
||
ptz_update_servlen_b = sizeof(ptz_update_serv_b);
|
||
|
||
ptz_update_serv_c.sin_family = PF_INET;
|
||
ptz_update_serv_c.sin_port = htons(PTZ_UPDATE_SERV_PORT_B);
|
||
ptz_update_serv_c.sin_addr.s_addr = inet_addr(PTZ_UPDATE_SERV_IP_A);
|
||
ptz_update_servlen_c = sizeof(ptz_update_serv_c);
|
||
|
||
ptz_update_serv_d.sin_family = PF_INET;
|
||
ptz_update_serv_d.sin_port = htons(PTZ_UPDATE_SERV_PORT_B);
|
||
ptz_update_serv_d.sin_addr.s_addr = inet_addr(PTZ_UPDATE_SERV_IP_B);
|
||
ptz_update_servlen_d = sizeof(ptz_update_serv_d);
|
||
update_active_connect_timer = 0;//发送间隔时间清0
|
||
update_active_connect_switch = 1;//初始化完成后默认打开发送心跳包
|
||
}
|
||
}
|
||
|
||
//判断是否需要发送心跳包
|
||
if(update_active_connect_switch != 0)
|
||
{//首先发送的端口和通道要完成初始化
|
||
if(update_state == UPDATE_STATE_UPGRADE_DATA_TRANS)
|
||
{
|
||
update_active_connect_switch = 2;//关闭心跳包发送
|
||
}
|
||
else//update_state == UPDATE_STATE_IDEL || update_state == UPDATE_STATE_DEAD
|
||
{
|
||
update_active_connect_switch = 1;//打开心跳包发送
|
||
}
|
||
}
|
||
//主动发送升级心跳包
|
||
if(ptz_update_communicaton == PTZ_CONNECT_STATE_SUCCESS)
|
||
{
|
||
if(update_active_connect_switch == 1)
|
||
{
|
||
if(kh == 0)
|
||
{//一旦进入应用程序先发送2包升级心跳包
|
||
kh = 1;
|
||
ptz_send_update_heartbeat();//发送升级心跳包
|
||
OSTimeDlyHMSM(0u, 0u, 1u, 0u);
|
||
ptz_send_update_heartbeat();//发送升级心跳包
|
||
}
|
||
|
||
|
||
update_active_connect_timer = update_active_connect_timer + 2;//改时间根据任务挂起时间计算
|
||
if(update_active_connect_timer >= 30000)//30S发一次
|
||
{
|
||
update_active_connect_timer = 0;
|
||
ptz_send_update_heartbeat();//发送升级心跳包
|
||
}
|
||
}
|
||
}
|
||
OSTimeDlyHMSM(0u, 0u, 0u, 2u);
|
||
}
|
||
}
|
||
|
||
|
||
static OS_STK task_update_rece_data_stk[TASK_PTZ_UPDATE_RECE_DATA_STK_SIZE];
|
||
static void creat_task_update_rece_data(void)
|
||
{
|
||
CPU_INT08U task_err;
|
||
CPU_INT08U name_err;
|
||
|
||
task_err = OSTaskCreateExt((void (*)(void *)) ptz_update_rece_data_task,
|
||
(void *) 0,
|
||
(OS_STK *)&task_update_rece_data_stk[TASK_PTZ_UPDATE_RECE_DATA_STK_SIZE - 1],
|
||
(INT8U ) TASK_PTZ_UPDATE_RECE_DATA_PRIO,
|
||
(INT16U ) TASK_PTZ_UPDATE_RECE_DATA_PRIO,
|
||
(OS_STK *)&task_update_rece_data_stk[0],
|
||
(INT32U ) TASK_PTZ_UPDATE_RECE_DATA_STK_SIZE,
|
||
(void *) 0,
|
||
(INT16U )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));
|
||
#if (OS_TASK_NAME_EN > 0)
|
||
OSTaskNameSet(TASK_PTZ_UPDATE_RECE_DATA_PRIO, "ptz_update_rece_data_task", &name_err);
|
||
#endif
|
||
|
||
if ((task_err == OS_ERR_NONE) && (name_err == OS_ERR_NONE)) {
|
||
pdebug(DEBUG_LEVEL_INFO,"create ptz_update_rece_data_task success...\n\r");
|
||
} else {
|
||
pdebug(DEBUG_LEVEL_FATAL,"create ptz_update_rece_data_task failed...\n\r");
|
||
}
|
||
}
|
||
|
||
|
||
|
||
static OS_STK task_update_data_process_stk[TASK_PTZ_UPDATE_DATA_PROCESS_STK_SIZE];
|
||
static void creat_task_update_data_process(void)
|
||
{
|
||
CPU_INT08U task_err;
|
||
CPU_INT08U name_err;
|
||
|
||
task_err = OSTaskCreateExt((void (*)(void *)) ptz_update_data_process_task,
|
||
(void *) 0,
|
||
(OS_STK *)&task_update_data_process_stk[TASK_PTZ_UPDATE_DATA_PROCESS_STK_SIZE - 1],
|
||
(INT8U ) TASK_PTZ_UPDATE_DATA_PROCESS_PRIO,
|
||
(INT16U ) TASK_PTZ_UPDATE_DATA_PROCESS_PRIO,
|
||
(OS_STK *)&task_update_data_process_stk[0],
|
||
(INT32U ) TASK_PTZ_UPDATE_DATA_PROCESS_STK_SIZE,
|
||
(void *) 0,
|
||
(INT16U )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));
|
||
#if (OS_TASK_NAME_EN > 0)
|
||
OSTaskNameSet(TASK_PTZ_UPDATE_DATA_PROCESS_PRIO, "ptz_update_data_process_task", &name_err);
|
||
#endif
|
||
|
||
if ((task_err == OS_ERR_NONE) && (name_err == OS_ERR_NONE)) {
|
||
pdebug(DEBUG_LEVEL_INFO,"create ptz_update_data_process_task success...\n\r");
|
||
} else {
|
||
pdebug(DEBUG_LEVEL_FATAL,"create ptz_update_data_process_task failed...\n\r");
|
||
}
|
||
}
|
||
|
||
|
||
void init_update_module()
|
||
{
|
||
creat_task_update_rece_data();
|
||
creat_task_update_data_process();
|
||
}
|
||
|
||
/*****************************/
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|