#include "comm_cfginfo.h"
#include "getcfg.h"
#include "bsp_ser.h"
#include "check.h"
#include "w25q128.h"
#include "Lan8720.h"
#include "stdlib.h"
#include "ptz_struct.h"
u_int8_t g_device_local_ip[21];
u_int8_t g_device_mac[21];
u_int8_t g_device_netmask[21];
u_int8_t g_device_gateway[21];

system_cfg_info system_info;

static int ipStrValid( const char * str_ip,u_int8_t  *rvalue);
static int macStrValid( const char * str_ip,u_int8_t *rvalue);
/******************************************************************************
** 文件名称：config.c
** 功    能：包含所有配置相关的函数
** 修改日志：
******************************************************************************/

static u_int8_t config_buff[1500];
/******************************************************************************
** 文件名称：read_config_file
** 功    能：从片内flash中读ini文件
** 修改日志：
******************************************************************************/
static BOOL read_config_file(void)
{           
 if (!app_crc_OK(HY_PKG_TYPE_CFG_FILE)){//校验失败
      memset(system_info.cmd_id, 0x30, sizeof(system_info.cmd_id));
      pdebug(DEBUG_LEVEL_FATAL,"read config file failed\n\r");
      return FALSE;
  }
  if (!pack_head_verify(HY_PKG_TYPE_CFG_FILE)){//检查包头数据有效性
      pdebug(DEBUG_LEVEL_FATAL,"read config file failed\n\r"); 
      return FALSE;
   }   
  return TRUE;
}

/******************************************************************************
** 文件名称：get_system_config_from_file(void)
** 功    能：得到配置信息
** 修改日志：
******************************************************************************/  
BOOL  get_system_config_from_file(void)
{     
   unsigned long ret =1;
//   Flash_GPIO_Init();
   Exit4ByteAddrMode();
   //初次上电或擦除flash之后会获取失败，导致自检初始化时无法判断。
//   if (!read_config_file())
//        return FALSE;
   read_config_file();
   
//   pdebug(DEBUG_LEVEL_INFO,"get hyt_config:\n\r");
   //host_mk60_cfg
//   pdebug(DEBUG_LEVEL_INFO,"[host_mk60_cfg]\n\r");
   //硬件版本号   
   ret = GetConfigFromBuf("host_mk60_cfg",
		          "hardwarever",
		          "00000000000000",
	                  (char *)system_info.hardware_version,
		          sizeof(system_info.hardware_version),
		          (char *)config_buff
		    );
   if (ret != 0){
       pdebug(DEBUG_LEVEL_FATAL,"get hardwarever failed\n\r");   
   }else{
       pdebug(DEBUG_LEVEL_INFO,"hardwarever: %s\n\r",system_info.hardware_version); 
   }
   
   //公司出厂唯一CMDid号
   ret = GetConfigFromBuf("host_mk60_cfg",
		          "cmd_id",
		          "HY_OLMS_000000000",
	                  (char *)system_info.cmd_id,//终端id
		          sizeof(system_info.cmd_id),
		          (char *)config_buff
		    );
   if (ret != 0){
       pdebug(DEBUG_LEVEL_FATAL,"get cmd_id failed\n\r"); 
   }else{
       pdebug(DEBUG_LEVEL_INFO,"cmd_id: %s\n\r",system_info.cmd_id);
   }
   
   //公司出厂唯一被监测设备id号
    ret = GetConfigFromBuf("host_mk60_cfg",
		          "component_id",
		          "HY_OLMS_000000000",
	                  (char *)system_info.component_id,
		          sizeof(system_info.component_id),
		          (char *)config_buff
		    );
   if (ret != 0){
       pdebug(DEBUG_LEVEL_FATAL,"get component_id failed\n\r"); 
   }else{
       pdebug(DEBUG_LEVEL_INFO,"component_id: %s\n\r",system_info.component_id);
   } 
   
  //local
  pdebug(DEBUG_LEVEL_INFO,"[local]\n\r");
  ret = GetConfigFromBuf("local",
                        "ip",
                        "192.168.8.200",
                        (char *)g_device_local_ip,
                        sizeof(g_device_local_ip),
                        (char *)config_buff
                  );
 if (ret != 0){
   pdebug(DEBUG_LEVEL_FATAL,"get local_ip failed,default value: %s\n\r",g_device_local_ip);
   ipStrValid((const char *)g_device_local_ip,g_local_ip);
 }else{
   pdebug(DEBUG_LEVEL_INFO,"local_ip: %s\n\r",g_device_local_ip);
   ipStrValid((const char *)g_device_local_ip,g_local_ip);
 }        

 //mac
  ret = GetConfigFromBuf("local",
                        "mac",
                        "42:00:00:00:00:01",
                        (char *)g_device_mac,
                        sizeof(g_device_mac),
                        (char *)config_buff
                  );
 if (ret != 0){
   pdebug(DEBUG_LEVEL_FATAL,"get mac failed,default value: %s\n\r",g_device_mac);
   macStrValid((const char *)g_device_mac,gCfgLoca_MAC);
 }else{
   pdebug(DEBUG_LEVEL_INFO,"mac: %s\n\r",g_device_mac);
   macStrValid((const char *)g_device_mac,gCfgLoca_MAC);
 }        
 
 //netmask
  ret = GetConfigFromBuf("local",
                        "netmask",
                        "255.255.255.0",
                        (char *)g_device_netmask,
                        sizeof(g_device_netmask),
                        (char *)config_buff
                  );
 if (ret != 0){
   pdebug(DEBUG_LEVEL_FATAL,"get netmask failed,default value: %s\n\r",g_device_netmask);
   ipStrValid((const char *)g_device_netmask,g_netmask);
 }else{
   pdebug(DEBUG_LEVEL_INFO,"netmask: %s\n\r",g_device_netmask);
   ipStrValid((const char *)g_device_netmask,g_netmask);
 }
  
   //gateway
  ret = GetConfigFromBuf("local",
                        "gateway",
                        "172.16.19.254",
                        (char *)g_device_gateway,
                        sizeof(g_device_gateway),
                        (char *)config_buff
                  );
 if (ret != 0){
   pdebug(DEBUG_LEVEL_FATAL,"get gateway failed,default value: %s\n\r",g_device_gateway);
   ipStrValid((const char *)g_device_gateway,g_gateway);
 }else{
   pdebug(DEBUG_LEVEL_INFO,"gateway: %s\n\r",g_device_gateway);
   ipStrValid((const char *)g_device_gateway,g_gateway);
 } 
 
 //function
 pdebug(DEBUG_LEVEL_INFO,"[self_check]\n\r");
 //simplify_self_check
#ifdef PTZ_LIGHT_GEAR_L6235D_AS5047D  //直齿云台默认自检打开
  ret = GetConfigFromBuf("self_check",
                        "simplify_check",
                        "both_enabled",
                        (char *)system_info.simplify_self_check,
                        sizeof(system_info.simplify_self_check),
                        (char *)config_buff
                  );
#else  //其余蜗轮蜗杆默认简易自检关闭
  ret = GetConfigFromBuf("self_check",
                        "simplify_check",
                        "both_disabled",
                        (char *)system_info.simplify_self_check,
                        sizeof(system_info.simplify_self_check),
                        (char *)config_buff
                  );
#endif
 if (ret != 0){
   pdebug(DEBUG_LEVEL_FATAL,"get simplify_check failed,default value: %s\n\r",SIMPLIFY_SELF_CHECK_DEFAULT);
 }else{
   pdebug(DEBUG_LEVEL_INFO,"simplify_check: %s\n\r",system_info.simplify_self_check);
 }
//complete_self_check
  ret = GetConfigFromBuf("self_check",
                        "complete_check",
                        "enable",
                        (char *)system_info.complete_self_check,
                        sizeof(system_info.complete_self_check),
                        (char *)config_buff
                  );
 if (ret != 0){
   pdebug(DEBUG_LEVEL_FATAL,"get complete_check failed,default value: %s\n\r",COMPLETE_SELF_CHECK_DEFAULT);
 }else{
   pdebug(DEBUG_LEVEL_INFO,"complete_check: %s\n\r",system_info.complete_self_check);
 }

 //uart_baud
 pdebug(DEBUG_LEVEL_INFO,"[baud_and_add]\n\r");

 //uart_422_baud
  ret = GetConfigFromBuf("baud_and_add",
                        "uart_422_baud",
                        "9600",
                        (char *)system_info.uart_422_baud,
                        sizeof(system_info.uart_422_baud),
                        (char *)config_buff
                  );
 if (ret != 0){
   pdebug(DEBUG_LEVEL_FATAL,"get uart_422_baud failed,default value: %s\n\r",UART_422_BAUD_DEFAULT);
   g_ptz.uart_422_baud = 9600;//配置信息获取失败，使用默认值
 }else{
   pdebug(DEBUG_LEVEL_INFO,"uart_422_baud: %s\n\r",system_info.uart_422_baud);
   system_info.uart_422baud = atoi((const char *)system_info.uart_422_baud);
   g_ptz.uart_422_baud = atoi((const char *)system_info.uart_422_baud);//确定波特率，用于串口初始化
 }
  //uart_485_baud
  ret = GetConfigFromBuf("baud_and_add",
                        "uart_485_baud",
                        "9600",
                        (char *)system_info.uart_485_baud,
                        sizeof(system_info.uart_485_baud),
                        (char *)config_buff
                  );
 if (ret != 0){
   pdebug(DEBUG_LEVEL_FATAL,"get uart_485_baud failed,default value: %s\n\r",UART_485_BAUD_DEFAULT);
   g_ptz.uart_485_baud = 9600;//配置信息获取失败，使用默认值
 }else{
   pdebug(DEBUG_LEVEL_INFO,"uart_485_baud: %s\n\r",system_info.uart_485_baud);
   system_info.uart_485baud = atoi((const char *)system_info.uart_485_baud);
   g_ptz.uart_485_baud = atoi((const char *)system_info.uart_485_baud);//确定波特率，用于串口初始化
 }
 //hyt_address
  ret = GetConfigFromBuf("baud_and_add",
                        "hyt_address",
                        "1",
                        (char *)system_info.hyt_address,
                        sizeof(system_info.hyt_address),
                        (char *)config_buff
                  );
 if (ret != 0){
   pdebug(DEBUG_LEVEL_FATAL,"get hyt_address failed,default value: %s\n\r",HYT_ADDRESS_DEFAULT);
   g_ptz.address = 1;//配置信息获取失败，使用默认值
 }else{
   pdebug(DEBUG_LEVEL_INFO,"hyt_address: %s\n\r",system_info.hyt_address);
   system_info.add = atoi((const char *)system_info.hyt_address);
   g_ptz.address = atoi((const char *)system_info.hyt_address);
 }
 //error_compensation
  ret = GetConfigFromBuf("baud_and_add",
                        "compensation_switch",
                        "on",
                        (char *)system_info.error_compensation,
                        sizeof(system_info.error_compensation),
                        (char *)config_buff
                  );
 if (ret != 0){
   pdebug(DEBUG_LEVEL_FATAL,"get compensation_switch failed,default value: %s\n\r",ERROR_compensation_switch);
 }else{
   pdebug(DEBUG_LEVEL_INFO,"compensation_switch: %s\n\r",system_info.error_compensation);
 }
 pdebug(DEBUG_LEVEL_INFO,"[end]\n\r");
 return TRUE;   
}
/******************************************************************************
** 函数名称:check_sum
** 功    能：
** 修改日志：
******************************************************************************/
static u_int8_t 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;
}

/******************************************************************************
** 函数名称:upgrade_pkg_head_checksum_OK
** 功    能：检查升级包头的checksum
** 修改日志：
******************************************************************************/
u_int8_t upgrade_pkg_head_checksum_OK(hy_release_file_head *pkg_head)
{
  return check_sum((u_int8_t *)pkg_head, (u_int8_t *)(&pkg_head->head_checksum) - (u_int8_t *)pkg_head)
    == pkg_head->head_checksum;
}

/******************************************************************************
** 函数名称：ext_flash_erase
** 功    能：擦除片外rom中的存储空间
** 修改日志：
******************************************************************************/
BOOL ext_flash_erase(hy_release_file_head *pkg_head)
{
  u_int32_t total_len = pkg_head->data_len;

 if(pkg_head->file_type == HY_PKG_TYPE_PUB_KEY){
    if((pkg_head->addr + total_len) > KEY_ADDR_END)
       return FALSE;
       Flash_Erase_Sector(EXT_FLASH_BLOCK_NUM,KEY_HEAD_SECTOR_BEGIN);
       Flash_Erase_Sector(EXT_FLASH_BLOCK_NUM,KEY_SECTOR_BEGIN);       
  }else if(pkg_head->file_type == HY_PKG_TYPE_CERT){
    if((pkg_head->addr + total_len) > CERT_ADDR_END)
       return FALSE;
    Flash_Erase_Sector(EXT_FLASH_BLOCK_NUM,CERT_HEAD_SECTOR_BEGIN);
    Flash_Erase_Sector(EXT_FLASH_BLOCK_NUM,CERT_SECTOR_BEGIN);      
  }else if(pkg_head->file_type == HY_PKG_TYPE_CFG_FILE){
    if((pkg_head->addr + total_len) > CFG_FILE_ADDR_END)
       return FALSE;
     Flash_Erase_Sector(EXT_FLASH_BLOCK_NUM,CFG_FILE_HEAD_SECTOR_BEGIN);
     Flash_Erase_Sector(EXT_FLASH_BLOCK_NUM,CFG_FILE_SECTOR_BEGIN);  
  }
     
  return TRUE;
}
/******************************************************************************
** 函数名称: app_crc_OK
** 功    能：校验已写入片内rom的应用程序包 通过crc16方式校验
** 修改日志：
******************************************************************************/

BOOL app_crc_OK(u_int8_t file_type)
{
  u_int16_t crc16;
  hy_release_file_head h_read;  
  u_int8_t crc16_read2[2] = {0x00}; 
  u_int32_t read_addr = 0;
  u_int32_t read_len = 0;
  
    if (file_type == HY_PKG_TYPE_CERT){
        Flash_Read((u_int8_t *)&h_read, CERT_HEAD_BEGIN, sizeof(h_read)-1);
        if(h_read.file_type != HY_PKG_TYPE_CERT)
            return FALSE;
        if (!upgrade_pkg_head_checksum_OK(&h_read))
            return FALSE;
         read_addr = CERT_ADDR_BEGIN;
     }else if (file_type == HY_PKG_TYPE_PUB_KEY){
        Flash_Read((u_int8_t *)&h_read, KEY_HEAD_BEGIN, sizeof(h_read)-1);
        if(h_read.file_type != HY_PKG_TYPE_PUB_KEY)
            return FALSE;
        if (!upgrade_pkg_head_checksum_OK(&h_read))
            return FALSE;
         read_addr = KEY_ADDR_BEGIN;
     }else if (file_type == HY_PKG_TYPE_CFG_FILE){
         Flash_Read((u_int8_t *)&h_read,CFG_FILE_HEAD_BEGIN, sizeof(h_read)-1);
         if(h_read.file_type != HY_PKG_TYPE_CFG_FILE)
            return FALSE;
         if (!upgrade_pkg_head_checksum_OK(&h_read))
            return FALSE;
          read_addr = CFG_FILE_ADDR_BEGIN; 
     }      
     CRC16_init(&crc16);
    //先算包头crc
     CRC16_update(&crc16,(u_int8_t *)&h_read, sizeof(h_read)-1);
     read_len = h_read.data_len; //包括crc16内容
     if(read_len > 1000)
       return FALSE;
     Flash_Read(config_buff, read_addr,read_len);
     Flash_Read((u_int8_t *)crc16_read2, read_addr+read_len,sizeof(u_int16_t));
     CRC16_update(&crc16,config_buff, read_len);
     
     return crc16 == *(u_int16_t *)&crc16_read2;
}

/******************************************************************************
 *函数名: write_pack_head_to_ext_flash
 *功  能：写包头到片外flash中
 *参  数：
 *返回值：
 *修  改：
******************************************************************************/
BOOL write_pack_head_to_ext_flash(hy_release_file_head *pkg_head)
{ 
  char test_buff[100] = {0x00};
  
  if(pkg_head->file_type == HY_PKG_TYPE_PUB_KEY){
      Flash_Write_MorePage((u_int8_t *)pkg_head,KEY_HEAD_BEGIN,sizeof(*pkg_head));
  }else if(pkg_head->file_type == HY_PKG_TYPE_CERT){
      Flash_Write_MorePage((u_int8_t *)pkg_head,CERT_HEAD_BEGIN,sizeof(*pkg_head)); 
  }else if(pkg_head->file_type == HY_PKG_TYPE_CFG_FILE){
    
//	FLASH_WP_ENABLE;  
	Flash_Write_MorePage((u_int8_t *)pkg_head,CFG_FILE_HEAD_BEGIN,sizeof(*pkg_head));
	  Flash_Read((u_int8_t *)test_buff,CFG_FILE_HEAD_BEGIN, 50);
	  Flash_Read((u_int8_t *)test_buff,CFG_FILE_HEAD_BEGIN, 50);
	  Flash_Read((u_int8_t *)test_buff,CFG_FILE_HEAD_BEGIN, 50);
	  
	  
  }

  return TRUE;
}

/******************************************************************************
 *函数名: write_file_to_ext_flash
 *功  能：写文件到外部flash中
 *参  数：
 *返回值：
 *修  改：
******************************************************************************/
BOOL write_file_to_ext_flash(hy_release_file_head *pkg_head)
{
  u_int32_t len = pkg_head->data_len + sizeof(u_int16_t); //内容+crc16
  u_int32_t write_addr = pkg_head->addr;
  Flash_Write_MorePage(pkg_head->data,write_addr,len);
  return TRUE;
}
                          
/******************************************************************************
 *函数名: pack_head_verify
 *功  能：校验包头数据的有效性
 *参  数：
 *返回值：
 *修  改：
******************************************************************************/
BOOL pack_head_verify(u_int8_t file_type)
{
  hy_release_file_head pkg_head = {0x00};
  u_int32_t read_addr;
  
   if (file_type == HY_PKG_TYPE_PUB_KEY){
       read_addr = KEY_HEAD_BEGIN;
   }else if (file_type == HY_PKG_TYPE_CERT){
       read_addr = CERT_HEAD_BEGIN;
   }else if (file_type == HY_PKG_TYPE_CFG_FILE){  
       read_addr = CFG_FILE_HEAD_BEGIN;
   } 
   
   Flash_Read((u_int8_t *)&pkg_head,read_addr, sizeof(pkg_head)-1);
  
  //数据长度限制
  if((pkg_head.data_len) > (1024*2))
    return FALSE;
 
  //起始标志检查
  if(pkg_head.flag != HY_RELEASE_FILE_FLAG)
    return FALSE;
  
  //头长度检验
  if(pkg_head.head_len != (sizeof(pkg_head)-1))
    return FALSE;
  
  //文件类型检验 boot app cert key cfg_file
  if((pkg_head.file_type != HY_PKG_TYPE_APP) && (pkg_head.file_type != HY_PKG_TYPE_BOOT_LOADER) && (pkg_head.file_type != HY_PKG_TYPE_CERT) && (pkg_head.file_type != HY_PKG_TYPE_PUB_KEY)&& (pkg_head.file_type != HY_PKG_TYPE_CFG_FILE))
    return FALSE;
  
  //文件格式版本
  if(pkg_head.file_format_ver != 1)
    return FALSE;  
  
  if(pkg_head.file_type == HY_PKG_TYPE_APP){ //App
    //烧写地址检验
    if(pkg_head.addr < APP_ADDR_BEGIN)
      return FALSE;
    //空间检验
    if((pkg_head.addr + pkg_head.data_len) > APP_ADDR_END)
      return FALSE;
  }else if(pkg_head.file_type == HY_PKG_TYPE_BOOT_LOADER){ //Bootloader
    //烧写地址检验
    if(pkg_head.addr != 0) //bootloader必须以0为起始地址
      return FALSE;
    //空间检验
    if((pkg_head.addr + pkg_head.data_len) > BOOTLOADER_ADDR_END)
      return FALSE;
  }else if(pkg_head.file_type == HY_PKG_TYPE_CERT){//CERT
     //烧写地址
    if(pkg_head.addr < CERT_ADDR_BEGIN)
      return FALSE;
    //空间检验
    if((pkg_head.addr + pkg_head.data_len) > CERT_ADDR_END)
      return FALSE;    
  }else if(pkg_head.file_type == HY_PKG_TYPE_PUB_KEY){//KEY
     //烧写地址
    if(pkg_head.addr < KEY_ADDR_BEGIN)
      return FALSE;
    //空间检验
    if((pkg_head.addr + pkg_head.data_len) > KEY_ADDR_END)
      return FALSE;   
  }else if(pkg_head.file_type == HY_PKG_TYPE_CFG_FILE){//CFG FILE
     //烧写地址
    if(pkg_head.addr < CFG_FILE_ADDR_BEGIN)
      return FALSE;
    //空间检验
    if((pkg_head.addr + pkg_head.data_len) > CFG_FILE_ADDR_END)
      return FALSE;   
  }  
  return TRUE;
}

//擦除片外flash缓存空间
void erase_ext_flash(u_int8_t block_begin,u_int32_t total_len)
{
  int i = 0;
  int block_count = total_len / Flash_BLOCKBYTE_LENGTH;
  
  if(total_len % Flash_BLOCKBYTE_LENGTH)
    block_count++;
  
  for(i = 0; i<block_count; i++){
    Flash_Erase_Block(block_begin + i);
    BSP_OS_TimeDlyMs(10);
  }
}

/******************************************************************************
** 函数名称：
** 功    能：将字符转成整数  如“192.168.8.1”转成192 168 8 1存在2个数组中
** 入口参数：
** 出口参数：
*******************************************************************************/
static int ipStrValid( const char * str_ip,u_int8_t  *rvalue)
{
	char	p[20];
	int	n,i,dotnumber,j;
	int	num_len=0;
	
	char	k[4];
	
        memset(p,0,sizeof(p));
	if(str_ip==NULL)
		return 0;
	n=strlen(str_ip);
	if(n==0)
		return 0;
	j=0;
	dotnumber=0;
	for(i=0;i<n;i++)
	{
		if(str_ip[i]=='.')
		{
			p[j]=0;
			num_len = strlen(p);
			if( num_len  == 0 )
				return 0;
			k[dotnumber] = atoi(p);
			//if(k[dotnumber]>252)
			//	return 0;
			dotnumber++;
			if(dotnumber>3)
				return 0;
			j=0;
			continue;
		}
		else if( (str_ip[i]<='9') && (str_ip[i]>='0') )
		{
			p[j++]=str_ip[i];
		}
		else
		{
			return 0;
		}
	}
	p[j]=0;
	k[3]=atoi(p);        
	if(dotnumber!=3)
		return 0;
	if(k[3]>=255)//默认不能等于255 广播地址
		return 0;
        memcpy(rvalue,k,4);//拷贝到目标数组中
	return 1;	
}
/******************************************************************************
** 函数名称：
** 功    能：将字符转成整数  如“192.168.8.1”转成192 168 8 1存在2个数组中
** 入口参数：
** 出口参数：
*******************************************************************************/
static int macStrValid( const char * str_ip,u_int8_t *rvalue)
{
	char	p[20];
	int	n,i,dotnumber,j;
	int	num_len=0;
	
	char	k[6];
	
        memset(p,0,sizeof(p));
	if(str_ip==NULL)
		return 0;
	n=strlen(str_ip);
	if(n==0)
		return 0;
	j=0;
	dotnumber=0;
	for(i=0;i<n;i++)
	{
          if(str_ip[i]==':')
		{
			p[j]=0;
			num_len = strlen(p);
			if( num_len  == 0 )
				return 0;
			k[dotnumber] = atoi(p);
			dotnumber++;
			if(dotnumber>6)
				return 0;
			j=0;
			continue;
		}
		else if( (str_ip[i]<='9') && (str_ip[i]>='0') )
		{
			p[j++]=str_ip[i];
		}
		else
		{
			return 0;
		}
	}
	p[j]=0;
	k[5]=atoi(p);        
	if(dotnumber!=5)
		return 0;
        memcpy(rvalue,k,6);//拷贝到目标数组中
	return 1;	
}
    
/********************00000000000000000000000000000000**********************/
/********************00000000000000000000000000000000**********************/
/********************00000000000000000000000000000000**********************/
u_int16_t cfg_crc16;//配置文件CRC效验
hy_release_file_head cfg_head;//文件头
u_int8_t cfg_buff[1500];
u_int8_t cfg_crc16_a[2] = {0x00};
//检查文件头，查看配置文件是否正确
//文件头错误返回0，文件头正确返回1
static u_int16_t ptz_check_cfg_head(hy_release_file_head head)
{
  //文件头校验码
  if (!upgrade_pkg_head_checksum_OK(&head))
    return FALSE;
  
  //数据长度限制
  if((head.data_len) > (1024*2))
    return FALSE;
 
  //起始标志检查
  if(head.flag != HY_RELEASE_FILE_FLAG)
    return FALSE;
  
  //头长度检验
  if(head.head_len != (sizeof(head)-1))
    return FALSE;
  
  //文件类型检验 
  if(head.file_type != HY_PKG_TYPE_CFG_FILE)
    return FALSE;
  
  //文件格式版本
  if(head.file_format_ver != 1)
    return FALSE;  
  
   //烧写地址
  if(head.addr < CFG_FILE_ADDR_BEGIN)
    return FALSE;
  
  //空间检验
  if((head.addr + head.data_len) > CFG_FILE_ADDR_END)
    return FALSE;   

  return TRUE;
}

//判断IP地址是否合法，并将字符串IP转化为数字
//并同时将字符型IP地址转化为对应的数字IP
static int ptz_check_ip_gateway_netmask_and_str_to_num( const char * str_ip,u_int8_t  *rvalue)
{
	char	p[20];
	int	n,i,dotnumber,j;
	int	num_len=0;
	
	unsigned char	k[4];
	
        memset(p,0,sizeof(p));
	if(str_ip==NULL)
		return 0;
	n=strlen(str_ip);
	if(n==0)
		return 0;
	j=0;
	dotnumber=0;
	for(i=0;i<n;i++)
	{
		if(str_ip[i]=='.')
		{
			p[j]=0;
			num_len = strlen(p);
			if( num_len  == 0 )
				return 0;
			k[dotnumber] = atoi(p);
			//if(k[dotnumber]>252)
			//	return 0;
			dotnumber++;
			if(dotnumber>3)
				return 0;
			j=0;
			continue;
		}
		else if( (str_ip[i]<='9') && (str_ip[i]>='0') )
		{
			p[j++]=str_ip[i];
		}
		else
		{
			return 0;
		}
	}
	p[j]=0;
	k[3]=atoi(p);        
	if(dotnumber!=3)
		return 0;
	//默认不能等于255 广播地址
//        if(k[0] <= 0 || k[0] >= 255)
//        {
//          return 0; 
//        }
//        if(k[1] <= 0 || k[1] >= 255)
//        {
//          return 0; 
//        }
//        if(k[2] <= 0 || k[2] >= 255)
//        {
//          return 0; 
//        }
//        if(k[3] <= 0 || k[3] >= 255)
//        {
//          return 0; 
//        }
        memcpy(rvalue,k,4);//拷贝到目标数组中
	return 1;	
}

//判断MAC地址是否合法
//并同时将字符型MAC地址转化为对应的数字MAC
static int ptz_check_mac_and_str_to_num( const char * str_mac,u_int8_t *rvalue)
{
	char	p[20];
	int	n,i,dotnumber,j;
	int	num_len=0;
	
	char	k[6];
	
        memset(p,0,sizeof(p));
	if(str_mac==NULL)
		return 0;
	n=strlen(str_mac);
	if(n==0)
		return 0;
	j=0;
	dotnumber=0;
	for(i=0;i<n;i++)
	{
          if(str_mac[i]==':')
		{
			p[j]=0;
			num_len = strlen(p);
			if( num_len  == 0 )
				return 0;
			k[dotnumber] = atoi(p);
			dotnumber++;
			if(dotnumber>6)
				return 0;
			j=0;
			continue;
		}
		else if( (str_mac[i]<='9') && (str_mac[i]>='0') )
		{
			p[j++]=str_mac[i];
		}
		else
		{
			return 0;
		}
	}
	p[j]=0;
	k[5]=atoi(p);        
	if(dotnumber!=5)
		return 0;
        memcpy(rvalue,k,6);//拷贝到目标数组中
	return 1;	
}

//指令修改云台配置文件,str输入的字符串，type修改的内容
BOOL ptz_set_cfg(char *str, char type)
{
  char head_state = TRUE;//文件头状态
  char data_state = TRUE;//数据状态
  
  static char hardwarever[50] = HARDWAREVER;
  static char cmd_id[50] = CMD_ID;       
  static char component_id[50] = COMPONENT_ID; 
  
  static char ip[50] = LOCAL_IP ;                                                   
  static char mac[50] = LOCAL_MAC;               
  static char netmask[50] = LOCAL_NETMASK;                                                  
  static char gateway[50] = LOCAL_GATEWAY; 
  
  //新增功能配置信息,可通过更改配置文件实现相关功能的使用-lqc-20220316
  static char simplify_self_check[50] = SIMPLIFY_SELF_CHECK;
  static char complete_self_check[50] = COMPLETE_SELF_CHECK;
  
  static char uart_422_baud[50] = UART_422_BAUD;
  static char uart_485_baud[50] = UART_485_BAUD;
  static char hyt_address[50] = HYT_ADDRESS;
  static char error_compensation[50] = ERROR_compensation;
  
  static char data_buff[30];
  
  static u_int8_t num_ip_gateway_netmask[4] = {0};   
  static u_int8_t num_mac[6] = {0};
  static hy_release_file_head cfg_head_flash;
  static u_int8_t cfg_buff_flash[1500];
  
  u_int8_t* cfg_buff_p = cfg_buff;
  char save_num = 0;
  
  memset(&hardwarever, 0, sizeof(hardwarever));
  memset(&cmd_id, 0, sizeof(cmd_id));
  memset(&component_id, 0, sizeof(component_id));
  
  memset(&ip, 0, sizeof(ip));
  memset(&mac, 0, sizeof(mac));
  memset(&netmask, 0, sizeof(netmask));
  memset(&gateway, 0, sizeof(gateway));
  
  memset(&simplify_self_check, 0, sizeof(simplify_self_check));
  memset(&complete_self_check, 0, sizeof(complete_self_check));
  
  memset(&uart_422_baud, 0, sizeof(uart_422_baud));
  memset(&uart_485_baud, 0, sizeof(uart_485_baud));
  memset(&hyt_address, 0, sizeof(hyt_address));
  memset(&error_compensation, 0, sizeof(error_compensation));
  
  memset(&data_buff, 0, sizeof(data_buff));
  
  memset(&num_ip_gateway_netmask, 0, sizeof(num_ip_gateway_netmask));
  memset(&num_mac, 0, sizeof(num_mac));
  memset(&cfg_head_flash, 0, sizeof(cfg_head_flash));
  memset(&cfg_buff_flash, 0, sizeof(cfg_buff_flash));
  
  OSTimeDlyHMSM(0u, 0u, 0u, 2u);
  
  memcpy(hardwarever, HARDWAREVER, sizeof(HARDWAREVER));  
  memcpy(cmd_id, CMD_ID, sizeof(CMD_ID)); 
  memcpy(component_id, COMPONENT_ID, sizeof(COMPONENT_ID)); 

  memcpy(ip, LOCAL_IP, sizeof(LOCAL_IP)); 
  memcpy(mac, LOCAL_MAC, sizeof(LOCAL_MAC)); 
  memcpy(netmask, LOCAL_NETMASK, sizeof(LOCAL_NETMASK)); 
  memcpy(gateway, LOCAL_GATEWAY, sizeof(LOCAL_GATEWAY)); 

  memcpy(simplify_self_check, SIMPLIFY_SELF_CHECK, sizeof(SIMPLIFY_SELF_CHECK));
  memcpy(complete_self_check, COMPLETE_SELF_CHECK, sizeof(COMPLETE_SELF_CHECK));
  
  memcpy(uart_422_baud, UART_422_BAUD, sizeof(UART_422_BAUD));
  memcpy(uart_485_baud, UART_485_BAUD, sizeof(UART_485_BAUD));
  memcpy(hyt_address, HYT_ADDRESS, sizeof(HYT_ADDRESS));
  memcpy(error_compensation, ERROR_compensation, sizeof(ERROR_compensation));

  
  //查看FLASH有没有保存配置文件头，以及配置文件头是否正确
  //读取文件头
  memset(&cfg_head, 0, sizeof(cfg_head));
  OSTimeDlyHMSM(0u, 0u, 0u, 2u);
  Flash_Read((u_int8_t *)&cfg_head,CFG_FILE_HEAD_BEGIN, sizeof(cfg_head)-1);
  OSTimeDlyHMSM(0u, 0u, 0u, 2u);
  //判断文件头
  if(ptz_check_cfg_head(cfg_head) == FALSE)
  {
    head_state = FALSE;
    data_state = FALSE;//文件头是坏的，那么数据肯定也是坏的
  }
  else
  {//文件头是正确的，则判断后面的数据对不对
    head_state = TRUE;
    //如果文件头是好的则开始判断文件数据部分
    memset(cfg_buff, 0, sizeof(cfg_buff));
    //提取数据
    OSTimeDlyHMSM(0u, 0u, 0u, 2u);
    Flash_Read(cfg_buff, CFG_FILE_ADDR_BEGIN, cfg_head.data_len);
    //提取保存的CRC16效验码
    OSTimeDlyHMSM(0u, 0u, 0u, 2u);
    Flash_Read((u_int8_t *)cfg_crc16_a, CFG_FILE_ADDR_BEGIN + cfg_head.data_len, sizeof(cfg_crc16_a));
    CRC16_init(&cfg_crc16);
    OSTimeDlyHMSM(0u, 0u, 0u, 2u);
    //先算包头crc16
    CRC16_update(&cfg_crc16,(u_int8_t *)&cfg_head, sizeof(cfg_head)-1);
    //再算数据部分CRC16
    CRC16_update(&cfg_crc16,cfg_buff, cfg_head.data_len);
    //判断CRC16是否正确
    if(cfg_crc16 == *(u_int16_t *)&cfg_crc16_a)
    {//如果CRC16正确
      data_state = TRUE;
    }
    else//如果CRC16不正确
    {
      data_state = FALSE;
    }
  }
  
  //如果文件头不正确，或者不存在，则从新封装文件头
  if(head_state == FALSE)
  {
    memset(&cfg_head, 0, sizeof(cfg_head));
    cfg_head.flag = HY_RELEASE_FILE_FLAG;      //4byte 标志，必须为"HYPK",如果文件不是以此开头，则认为是非法文件
    cfg_head.head_len = sizeof(cfg_head)-1;    //4byte头长度文件头长度，包含"标志"
    cfg_head.file_type = HY_PKG_TYPE_CFG_FILE; //1byte文件类型，1,1：应用程序升级包 2:bootloader
    cfg_head.file_format_ver = 1;              //2byte 文件格式版本号，1用于确定文件的处理方式
    cfg_head.hardware_type[0] = 0;             //2byte硬件类型,升级包适用的硬件类型
    cfg_head.hardware_type[1] = 0;             //2byte硬件类型,升级包适用的硬件类型
    cfg_head.hardware_ver = 0;                 //2byte硬件版本,升级包适用的硬件版本
    cfg_head.software_ver = 0;                 //4byte软件版本,本升级包的应用软件版本
    cfg_head.data_len = 0;                     //4byte 数据长度,不包含2个字节的crc
    cfg_head.addr = CFG_FILE_ADDR_BEGIN;       //4byte 烧写地址
    cfg_head.head_checksum = 0;                //1byte头校验,以上内容的checksum，包括"标志"，单字节异或
    cfg_head.data[1] = 0;                      //数据
  }
  //如果配置文件内部数据不正确
  if(data_state == FALSE)
  {//如果配置文件存储的数据是错的则要对数据从新封装
    strcat(hardwarever, HARDWAREVER_DEFAULT);
    strcat(cmd_id, CMD_ID_DEFAULT);
    strcat(component_id, COMPONENT_ID_DEFAULT);
    
    strcat(ip, LOCAL_IP_DEFAULT);
    strcat(mac, LOCAL_MAC_DEFAULT);
    strcat(netmask, LOCAL_NETMASK_DEFAULT);
    strcat(gateway, LOCAL_GATEWAY_DEFAULT);
    
    strcat(simplify_self_check, SIMPLIFY_SELF_CHECK_DEFAULT);
    strcat(complete_self_check, COMPLETE_SELF_CHECK_DEFAULT);
    
    strcat(uart_422_baud, UART_422_BAUD_DEFAULT);
    strcat(uart_485_baud, UART_485_BAUD_DEFAULT);
    strcat(hyt_address, HYT_ADDRESS_DEFAULT);
    strcat(error_compensation, ERROR_compensation_switch);
  }
  else
  {//如果配置文件是正确的直接读取配置文件内部数据
    //获取hardwarever
    memset(data_buff, 0, sizeof(data_buff));
    GetConfigFromBuf("host_mk60_cfg",
                     "hardwarever", HARDWAREVER_DEFAULT,
                    (char *)data_buff, sizeof(data_buff),
                    (char *)cfg_buff);
    strcat(hardwarever, data_buff); 
     
    //获取cmd_id
    memset(data_buff, 0, sizeof(data_buff));
    GetConfigFromBuf("host_mk60_cfg",
                     "cmd_id", CMD_ID_DEFAULT,
                    (char *)data_buff, sizeof(data_buff),
                    (char *)cfg_buff);
    strcat(cmd_id, data_buff); 
    
    //获取component_id
    memset(data_buff, 0, sizeof(data_buff));
    GetConfigFromBuf("host_mk60_cfg",
                     "component_id", COMPONENT_ID_DEFAULT,
                    (char *)data_buff, sizeof(data_buff),
                    (char *)cfg_buff);
    strcat(component_id, data_buff); 
    
    //获取IP
    memset(data_buff, 0, sizeof(data_buff));
    GetConfigFromBuf("local",
                     "ip", LOCAL_IP_DEFAULT,
                    (char *)data_buff, sizeof(data_buff),
                    (char *)cfg_buff);
    strcat(ip, data_buff);
    
    //获取MAC
    memset(data_buff, 0, sizeof(data_buff));
    GetConfigFromBuf("local",
                     "mac", LOCAL_MAC_DEFAULT,
                    (char *)data_buff, sizeof(data_buff),
                    (char *)cfg_buff);
    strcat(mac, data_buff);
    
    //获取netmask
    memset(data_buff, 0, sizeof(data_buff));
    GetConfigFromBuf("local",
                     "netmask", LOCAL_NETMASK_DEFAULT,
                    (char *)data_buff, sizeof(data_buff),
                    (char *)cfg_buff);
    strcat(netmask, data_buff);
    
    //获取gateway
    memset(data_buff, 0, sizeof(data_buff));
    GetConfigFromBuf("local",
                     "gateway", LOCAL_GATEWAY_DEFAULT,
                    (char *)data_buff, sizeof(data_buff),
                    (char *)cfg_buff);
    strcat(gateway, data_buff);
    
    
    //获取简易自检参数
    memset(data_buff, 0, sizeof(data_buff));
    GetConfigFromBuf("self_check",
                     "simplify_check", SIMPLIFY_SELF_CHECK_DEFAULT,
                    (char *)data_buff, sizeof(data_buff),
                    (char *)cfg_buff);
    strcat(simplify_self_check, data_buff);
    
    //获取全自检参数
    memset(data_buff, 0, sizeof(data_buff));
    GetConfigFromBuf("self_check",
                     "complete_check", COMPLETE_SELF_CHECK_DEFAULT,
                    (char *)data_buff, sizeof(data_buff),
                    (char *)cfg_buff);
    strcat(complete_self_check, data_buff);

    //获取422串口波特率
    memset(data_buff, 0, sizeof(data_buff));
    GetConfigFromBuf("baud_and_add",
                     "uart_422_baud", UART_422_BAUD_DEFAULT,
                    (char *)data_buff, sizeof(data_buff),
                    (char *)cfg_buff);
    strcat(uart_422_baud, data_buff);
    //获取485串口波特率
    memset(data_buff, 0, sizeof(data_buff));
    GetConfigFromBuf("baud_and_add",
                     "uart_485_baud", UART_485_BAUD_DEFAULT,
                    (char *)data_buff, sizeof(data_buff),
                    (char *)cfg_buff);
    strcat(uart_485_baud, data_buff);
    //获取地址
    memset(data_buff, 0, sizeof(data_buff));
    GetConfigFromBuf("baud_and_add",
                     "hyt_address", HYT_ADDRESS_DEFAULT,
                    (char *)data_buff, sizeof(data_buff),
                    (char *)cfg_buff);
    strcat(hyt_address, data_buff);
    //误差补偿开关
    memset(data_buff, 0, sizeof(data_buff));
    GetConfigFromBuf("baud_and_add",
                     "error_compensation", ERROR_compensation_switch,
                    (char *)data_buff, sizeof(data_buff),
                    (char *)cfg_buff);
    strcat(error_compensation, data_buff);
  }
  
  switch(type)//解析是需要修改配置文件的哪个部分
  {
    case SET_LOCAL_IP:             //1设置IP
      if(ptz_check_ip_gateway_netmask_and_str_to_num(str, num_ip_gateway_netmask) == 0)//说明IP地址不合法
      {
        return FALSE;
      }
      memset(ip, 0, sizeof(ip));
      strcpy(ip, LOCAL_IP);
      strcat(ip, str);
      break;
      
    case SET_LOCAL_MAC:            //2设置MAC
      if(ptz_check_mac_and_str_to_num(str, num_mac) == 0)//判断MAC地址是否合法
      {
        return FALSE;
      }
      memset(mac, 0, sizeof(mac));
      strcpy(mac, LOCAL_MAC);
      strcat(mac, str);
      break;
      
    case SET_LOCAL_NETMASK:        //3设置NETMASK
      if(ptz_check_ip_gateway_netmask_and_str_to_num(str, num_ip_gateway_netmask) == 0)//说明IP地址不合法
      {
        return FALSE;
      }
      memset(netmask, 0, sizeof(netmask));
      strcpy(netmask, LOCAL_NETMASK);
      strcat(netmask, str);
      break;
      
    case SET_LOCAL_GATEWAY:        //4设置GATEWAY
      if(ptz_check_ip_gateway_netmask_and_str_to_num(str, num_ip_gateway_netmask) == 0)//说明IP地址不合法
      {
        return FALSE;
      }
      memset(gateway, 0, sizeof(gateway));
      strcpy(gateway, LOCAL_GATEWAY);
      strcat(gateway, str);
      break;
      
      
    case SET_HARDWAREVER:    //0X08
      memset(hardwarever, 0, sizeof(hardwarever));
      strcpy(hardwarever, HARDWAREVER);
      strcat(hardwarever, str);
      break; 
        
    case SET_CMD_ID:         //0X09
      memset(cmd_id, 0, sizeof(cmd_id));
      strcpy(cmd_id, CMD_ID);
      strcat(cmd_id, str);
      break;

    case SET_COMPONENT_ID:   //0X0A 
      memset(component_id, 0, sizeof(component_id));
      strcpy(component_id, COMPONENT_ID);
      strcat(component_id, str);
      break;
      
//      case SET_TERM_IP:
    case SET_SIMPLIFY_SELF_CHECK: //0X0B
      memset(simplify_self_check, 0, sizeof(simplify_self_check));
      strcpy(simplify_self_check, SIMPLIFY_SELF_CHECK);
      strcat(simplify_self_check, str);
      break;
      
//      case SET_WEB_IP:
    case SET_COMPLETE_SELF_CHECK: //0X0C
      memset(complete_self_check, 0, sizeof(complete_self_check));
      strcpy(complete_self_check, COMPLETE_SELF_CHECK);
      strcat(complete_self_check, str);
      break;  

//    case SET_WEB_IP:
    case SET_UART_422_BAUD: //0X0E
      memset(uart_422_baud, 0, sizeof(uart_422_baud));
      strcpy(uart_422_baud, UART_422_BAUD);
      strcat(uart_422_baud, str);
      break;
      
//  case SET_A9_IP:
    case SET_UART_485_BAUD: //0X0F
      memset(uart_485_baud, 0, sizeof(uart_485_baud));
      strcpy(uart_485_baud, UART_485_BAUD);
      strcat(uart_485_baud, str);
      break;
      
    case SET_HYT_ADDRESS: //0X10
      memset(hyt_address, 0, sizeof(hyt_address));
      strcpy(hyt_address, HYT_ADDRESS);
      strcat(hyt_address, str);
      break;  
  case SET_ERROR_compensation://0x11
    memset(error_compensation, 0, sizeof(error_compensation));
    strcpy(error_compensation, ERROR_compensation);
    strcat(error_compensation, str);
    break;
      
      

  default:
      return FALSE;
      break;
  }
  
  //开始组装配置文件内容数据
  memset(cfg_buff, 0, sizeof(cfg_buff));
  /**/
  memcpy(cfg_buff_p, HOST_MK60_CFG, strlen(HOST_MK60_CFG));
  cfg_buff_p = cfg_buff_p + strlen(HOST_MK60_CFG);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);

  memcpy(cfg_buff_p, hardwarever, strlen(hardwarever));
  cfg_buff_p = cfg_buff_p + strlen(hardwarever);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);

  memcpy(cfg_buff_p, cmd_id, strlen(cmd_id));
  cfg_buff_p = cfg_buff_p + strlen(cmd_id);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);
  
  memcpy(cfg_buff_p, component_id, strlen(component_id));
  cfg_buff_p = cfg_buff_p + strlen(component_id);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);

  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);
  /**/
  memcpy(cfg_buff_p, LOCAL, strlen(LOCAL));
  cfg_buff_p = cfg_buff_p + strlen(LOCAL);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);
  
  memcpy(cfg_buff_p, ip, strlen(ip));
  cfg_buff_p = cfg_buff_p + strlen(ip);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);

  memcpy(cfg_buff_p, mac, strlen(mac));
  cfg_buff_p = cfg_buff_p + strlen(mac);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);

  memcpy(cfg_buff_p, netmask, strlen(netmask));
  cfg_buff_p = cfg_buff_p + strlen(netmask);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);

  memcpy(cfg_buff_p, gateway, strlen(gateway));
  cfg_buff_p = cfg_buff_p + strlen(gateway);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);

  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);

  memcpy(cfg_buff_p, FUNCTION, strlen(FUNCTION));
  cfg_buff_p = cfg_buff_p + strlen(FUNCTION);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER); 
  
  memcpy(cfg_buff_p, simplify_self_check, strlen(simplify_self_check));
  cfg_buff_p = cfg_buff_p + strlen(simplify_self_check);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);
  
  memcpy(cfg_buff_p, complete_self_check, strlen(complete_self_check));
  cfg_buff_p = cfg_buff_p + strlen(complete_self_check);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);
  
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);
  
  memcpy(cfg_buff_p, BAUD_AND_ADD, strlen(BAUD_AND_ADD));
  cfg_buff_p = cfg_buff_p + strlen(BAUD_AND_ADD);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER); 
  
  memcpy(cfg_buff_p, uart_422_baud, strlen(uart_422_baud));
  cfg_buff_p = cfg_buff_p + strlen(uart_422_baud);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);
  
  memcpy(cfg_buff_p, uart_485_baud, strlen(uart_485_baud));
  cfg_buff_p = cfg_buff_p + strlen(uart_485_baud);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);
  
  memcpy(cfg_buff_p, hyt_address, strlen(hyt_address));
  cfg_buff_p = cfg_buff_p + strlen(hyt_address);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);
  
  memcpy(cfg_buff_p, error_compensation, strlen(error_compensation));
  cfg_buff_p = cfg_buff_p + strlen(error_compensation);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);
  /**/
  memcpy(cfg_buff_p, END, strlen(END));
  cfg_buff_p = cfg_buff_p + strlen(END);
  memcpy(cfg_buff_p, ENTER, strlen(ENTER));
  cfg_buff_p = cfg_buff_p + strlen(ENTER);
  /**/
  
  //计算文件头中的数据长度
  cfg_head.data_len = strlen((char *)cfg_buff) + 1;
  
  //计算文件头校验码
  cfg_head.head_checksum = 
    check_sum((u_int8_t *)(&cfg_head), (u_int8_t *)(&(cfg_head.head_checksum)) - (u_int8_t *)(&cfg_head));
  
  //计算文件CRC16效验码
  CRC16_init(&cfg_crc16);  
  CRC16_update(&cfg_crc16,(u_int8_t *)&cfg_head, (sizeof(cfg_head) - 1));
  CRC16_update(&cfg_crc16,cfg_buff, cfg_head.data_len);
  *((u_int16_t *)(&cfg_buff[cfg_head.data_len])) = cfg_crc16;

  for(save_num = 0; save_num < CFG_SAVE_FLASH_NUM; save_num++)
  {//超过保存次数退出
    //擦除原先的配置文件
    OSTimeDlyHMSM(0u, 0u, 0u, 2u);
    Flash_Erase_Sector(CFG_HEAD_BLOCK_NUM, CFG_HEAD_SECTOR_NUM);
    OSTimeDlyHMSM(0u, 0u, 0u, 2u);
    Flash_Erase_Sector(CFG_DATA_BLOCK_NUM, CFG_DATA_SECTOR_NUM);
    //保存文件头
    OSTimeDlyHMSM(0u, 0u, 0u, 2u);
    Flash_Write_MorePage((u_int8_t *)(&cfg_head), 
                         FLASH_SECTOR_ADD(CFG_HEAD_BLOCK_NUM, CFG_HEAD_SECTOR_NUM), 
                         sizeof(cfg_head));
    
    //保存文件数据
    OSTimeDlyHMSM(0u, 0u, 0u, 2u);
    Flash_Write_MorePage(cfg_buff,
                         FLASH_SECTOR_ADD(CFG_DATA_BLOCK_NUM, CFG_DATA_SECTOR_NUM),
                        (cfg_head.data_len + sizeof(u_int16_t)));
    
    //将写入FLASH的文件读出来，判断是否写入正确
    memset(&cfg_head_flash, 0, sizeof(cfg_head_flash));
    memset(cfg_buff_flash, 0, sizeof(cfg_buff_flash));
    
    //读出数据并判断
    OSTimeDlyHMSM(0u, 0u, 0u, 2u);
    Flash_Read((u_int8_t *)&cfg_head_flash,CFG_FILE_HEAD_BEGIN, sizeof(cfg_head_flash)-1);
    OSTimeDlyHMSM(0u, 0u, 0u, 2u);
    Flash_Read(cfg_buff_flash, CFG_FILE_ADDR_BEGIN, (cfg_head.data_len + sizeof(u_int16_t)));
    OSTimeDlyHMSM(0u, 0u, 0u, 2u);
    if(memcmp(&cfg_head, &cfg_head_flash, (sizeof(cfg_head)-1)) == 0 &&
       memcmp(&cfg_buff, &cfg_buff_flash, (cfg_head.data_len + sizeof(u_int16_t))) == 0)//判断写入数据是否正确
    {//数据相同，保存成功
      return TRUE;
    }
  }
  return FALSE;
}

//读取并判断配置文件数据，并将数据保存到buff中，同时返回数据总长度，如果数据错误返回0
unsigned short int ptz_read_cfg_data(char* buff)
{
  //查看FLASH有没有保存配置文件头，以及配置文件头是否正确
  //读取文件头
  memset(&cfg_head, 0, sizeof(cfg_head));
  OSTimeDlyHMSM(0u, 0u, 0u, 2u);
  Flash_Read((u_int8_t *)&cfg_head,CFG_FILE_HEAD_BEGIN, sizeof(cfg_head)-1);
  if(ptz_check_cfg_head(cfg_head) == FALSE)
  {
    return 0;
  }
  //如果文件头是好的则开始判断文件数据部分
  memset(cfg_buff, 0, sizeof(cfg_buff));
  //提取数据
  OSTimeDlyHMSM(0u, 0u, 0u, 2u);
  Flash_Read(cfg_buff, CFG_FILE_ADDR_BEGIN, cfg_head.data_len);
  //提取保存的CRC16效验码
  OSTimeDlyHMSM(0u, 0u, 0u, 2u);
  Flash_Read((u_int8_t *)cfg_crc16_a, CFG_FILE_ADDR_BEGIN + cfg_head.data_len, sizeof(cfg_crc16_a));
  CRC16_init(&cfg_crc16);
  //先算包头crc16
  CRC16_update(&cfg_crc16,(u_int8_t *)&cfg_head, sizeof(cfg_head)-1);
  //再算数据部分CRC16
  CRC16_update(&cfg_crc16,cfg_buff, cfg_head.data_len);
  //判断CRC16是否正确
  if(cfg_crc16 == *(u_int16_t *)&cfg_crc16_a)
  {//如果CRC16正确
    memcpy(buff, cfg_buff, cfg_head.data_len);
    return ((unsigned short int)cfg_head.data_len);
  }
  else//如果CRC16不正确
  {
    return 0;
  }
}
/********************00000000000000000000000000000000**********************/
/********************00000000000000000000000000000000**********************/
/********************00000000000000000000000000000000**********************/



