Files
banban/ql-kernel/threadx/quec/quec_hx_gps_update.c
T

689 lines
19 KiB
C

/*============================================================================================
Copyright(c) 2018 Quectel Wierless Solution,Co.,Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential.
============================================================================*/
#include <stdio.h>
#include "quec_rtos.h"
#include "gps_channel.h"
#include "quec_gps_rom.h"
#include "quec_hx_gps_update.h"
#include "gps_debug.h"
#include "quec_hx_apflash.h"
#include "quec_hx_gps.h"
#include "guilin_lite.h"
#include "quec_gpio.h"
#define XMODEM_SOH 0x01
#define XMODEM_STX 0x02
#define XMODEM_EOT 0x04
#define XMODEM_ACK 0x06
#define XMODEM_NAK 0x15
#define XMODEM_CAN 0x18
#define XMODEM_CRC_CHR 'C'
#define XMODEM_CRC_SIZE 2 /* Crc_High Byte + Crc_Low Byte */
#define XMODEM_FRAME_ID_SIZE 2 /* Frame_Id + 255-Frame_Id */
#define XMODEM_DATA_SIZE_SOH 128 /* for Xmodem protocol */
#define XMODEM_DATA_SIZE_STX 1024 /* for 1K xmodem protocol */
#define USE_1K_XMODEM 1 /* 1 for use 1k_xmodem 0 for xmodem */
#define TIMEOUT_USEC 0
#define TIMEOUT_SEC 10
#define GNSS_UART_BAUD_230400 230400
#define GNSS_UART_BAUD_921600 921600
#define GNSS_UART_BAUD_115200 115200
#define GNSS_UART_BAUD_460800 460800
#define GNSS_UART_BAUD_1843200 1843200
void quec_gnss_power_on_off(int flags);
#if (USE_1K_XMODEM)
#define XMODEM_DATA_SIZE XMODEM_DATA_SIZE_STX
#define XMODEM_HEAD XMODEM_STX
#else
#define XMODEM_DATA_SIZE XMODEM_DATA_SIZE_SOH
#define XMODEM_HEAD XMODEM_SOH
#endif
void dump(void *buf, int len)
{
char *p = (char *)buf;
int i;
for(i = 0; i < len; i++)
{
if(i % 16 == 0) GPS_LOGI("%04x:", i);
if(i % 16 == 8) GPS_LOGI(" -");
GPS_LOGI(" %02x", p[i]);
if(i % 16 == 15) GPS_LOGI("\n");
}
if(i % 16) GPS_LOGI("\n");
}
unsigned short get_crc16 ( char *ptr, unsigned short count )
{
unsigned short crc, i;
crc = 0;
while(count--)
{
crc = crc ^ (int) *ptr++ << 8;
for(i = 0; i < 8; i++)
{
if(crc & 0x8000)
crc = crc << 1 ^ 0x1021;
else
crc = crc << 1;
}
}
return (crc & 0xFFFF);
}
/*阻塞式检测总线buffer是否存在数据*/
int select_read(int delay_time)
{
int buflen=0;
unsigned int gps_flags = 0;
QUEC_GPS_DEV_T * quec_gps = quec_get_gps_dev();
quec_rtos_flag_wait(quec_gps->gps_event_flag_ref,QUEC_GPS_DOWNLOAD_FIRM, QUEC_FLAG_OR_CLEAR, &gps_flags, delay_time);
buflen=GPS_COM_GetByteStatus();
return buflen;
}
/*读取总线buffer中数据*/
int deal_read(char *ack_id,unsigned int len)
{
if(ack_id==NULL)
{
return -1;
}
int buflen=0;
buflen=GPS_COM_GetByte_Buffer((char*)ack_id,len);
if(buflen)
{
return buflen;
}
else
{
memset(ack_id,0,len);
return 0;
}
}
/*校验固件合法性*/
int check_firmware_is_vailed(firm_type t)
{
#if defined (HX_GNSS_CC11_SUPPORT)
icoe_image_header_t header;
#else
uc_image_header_t header;
#endif
unsigned int buf[1024];
unsigned int fsize, checksum, i;
unsigned short crc;
size_t rByte;
if(!quec_gnss_firm_open(t)){
return -1;
}
fsize = quec_gnss_get_firm_size(t);
if(fsize == 0)
return -1;
while(fsize > sizeof(header)) {
rByte = quec_gnss_read_firm_buffer(t,(char *)&header,sizeof(header));
#if 0
dump((char *)&header, sizeof(header));
GPS_LOGI("%04x\n,%04x\n,%04x\n,%04x\n,%04x\n,%04x\n,%04x\n,%04x\n",
header.ih_magic,
header.ih_checksum,
header.ih_time,
header.ih_size,
header.ih_reserved,
header.pkg_flash_addr,
header.pkg_run_addr,
header.ih_hcrc);
#endif
crc = get_crc16 ( (char *) &header, sizeof(header)-4);
GPS_LOGI("crc16 [%08x]\n", crc);
if((header.ih_hcrc & 0xFFFF) != crc) {
GPS_LOGE("%s[err]crc is err",__func__);
quec_gnss_firm_close(t);
return -1;
}
fsize -= sizeof(header);
fsize -= header.ih_size;
checksum = 0;
while(header.ih_size > 0)
{
if(header.ih_size >= 1024 )
rByte = 1024;
else
rByte = header.ih_size;
memset(buf, 0, sizeof(buf));
rByte = quec_gnss_read_firm_buffer(t,(char *)buf,rByte);
for(i = 0; i < (rByte+3)/4; i++)
checksum += buf[i];
header.ih_size -= rByte;
}
GPS_LOGI("checksum [%08x]\n\n",checksum);
if( checksum != header.ih_checksum) {
GPS_LOGE("%s[err]checksum is err",__func__);
quec_gnss_firm_close(t);
return -1;
}
}
quec_gnss_firm_close(t);
return 0;
}
unsigned int send_request_and_response_is_ok(void)
{
unsigned int ret = 0;
char cmd[20]={0};
char ack_id[64]={0};
char cnt = 50;
int i=5;
int len = 0;
sprintf(cmd,"M!TM!TM!T");
while(cnt--)
{
GPS_COM_PutByte_Buffer(cmd, 9);
#if defined (HX_GNSS_CC11_SUPPORT)
memset(ack_id,0,64);
while (select_read(5) && i-- > 0)
{
len = deal_read(ack_id+len,64);
if(strchr((char *)ack_id, 'Y') && strchr((char *)ack_id, 'C'))
{
ret=1;
cnt=0;
break;
}
}
#else
if(select_read(5))
{
memset(ack_id,0,4);
deal_read(ack_id,4);
//for(i=0;i<64;i++){
// GPS_LOGI("check nmea_data = %x", ack_id[i]);
//}
if(ack_id[0]=='Y' && ack_id[1]=='C')
{
ret = 1;
break;
}
if(ack_id[0]=='C' && ack_id[1]=='Y')
{
ret = 1;
break;
}
}
else
{
GPS_LOGE("retry...");
}
#endif
}
return ret;
}
int xmodem_send(firm_type t)
{
char packet_data[XMODEM_DATA_SIZE];
char frame_data[XMODEM_DATA_SIZE + XMODEM_CRC_SIZE + XMODEM_FRAME_ID_SIZE + 1];
int complete,retry_num,pack_counter,read_number,i;
unsigned short crc_value;
char ack_id = 'C';
int retry=0;
//char name[100]={};
pack_counter = 0; // 包计数器清零
complete = 0;
retry_num = 0;
/*如果不存在固件就报错,退出程序。*/
if((quec_gnss_firm_open(t))==0){
GPS_LOGE("\n can't open this file or not exist! \n");
return -1;
}
else{
GPS_LOGI("Ready to send the file\n");
}
GPS_LOGI("Waiting for signal C/NAK!\n");
/*while(retry<50)
{
if(select_read())
{
deal_read(&ack_id,1);
GPS_LOGI("%c",ack_id);
if(ack_id == 'C')
break;
retry++;
}
}*/
GPS_LOGI("The signal NAK: %02x ok!!!\n",ack_id);//打印接收到的NAK信息
while(!complete)
{
switch(ack_id)
{
case XMODEM_CRC_CHR: // 接收到字符'C'开始启动传输,并使用CRC校验
GPS_LOGI("begining to Send file ...\n");
case XMODEM_ACK: //0x06
retry_num = 0;
pack_counter++;
ack_id = 0;
read_number = quec_gnss_read_firm_buffer(t,packet_data, XMODEM_DATA_SIZE);
if(read_number > 0)/*read_number为返回的读取实际字节数*/
{
if(read_number < XMODEM_DATA_SIZE_STX)/*最后一包数据*/
{
GPS_LOGI("Start filling the last frame!\n");
for(; read_number < XMODEM_DATA_SIZE; read_number++)
packet_data[read_number] = 0x1A; // 不足128字节用0x1A填充
}
frame_data[0] = XMODEM_HEAD; // 帧开始字符
frame_data[1] = (char)pack_counter; // 信息包序号
frame_data[2] = (char)(255 - frame_data[1]); // 信息包序号的补码
for(i=0; i < XMODEM_DATA_SIZE; i++) // 128字节的数据段
frame_data[i+3] = packet_data[i];//把收到的字符和信息头一起打包
crc_value = get_crc16(packet_data, XMODEM_DATA_SIZE); // 16位crc校验
frame_data[XMODEM_DATA_SIZE+3] = (char)(crc_value >> 8);// 高八位数据
frame_data[XMODEM_DATA_SIZE+4] = (char)(crc_value); //低八位数据
/* 发送1024+5字节数据 */
GPS_COM_PutByte_Buffer((char*)frame_data, XMODEM_DATA_SIZE+3+2);
GPS_LOGI("read_number=%d pack_counter = %d\n",read_number,pack_counter); //ADD: process
if(select_read(1000))
{
deal_read(&ack_id,1);
}
if(ack_id == XMODEM_ACK) {
GPS_LOGI("ACK Ok!!Ready sending next pack!\n");
GPS_LOGI(" Ok!\n");
}
else
{
GPS_LOGE("ACK Error!\n");
GPS_LOGE("0x%02X\n",ack_id);
//GPS_LOGE("pack_counter = %d\n", pack_counter);
}
}
else // 文件发送完成
{
ack_id = XMODEM_EOT;
GPS_LOGI("Complete ACK\n");
GPS_LOGI("send XMODEM_EOT\r\n");
GPS_COM_PutByte_Buffer(&ack_id, 1);
if(select_read(1000))
{
deal_read(&ack_id,1);
GPS_LOGI("ack_id=%x",ack_id);
if(ack_id == XMODEM_ACK)
{
complete = 1;
}
}
if(complete == 1)
{
GPS_LOGI("Send file successful!!!\n");
quec_gnss_firm_close(t);
}
else
{
GPS_LOGE("Send file failed!!!\n");
quec_gnss_firm_close(t);
return -1;
}
}
break;
case XMODEM_NAK:
if( retry_num++ > 10)
{
GPS_LOGE("Retry too many times,Quit!\n");
complete = 1;
}
else //重试,发送
{
GPS_COM_PutByte_Buffer((char*)frame_data, XMODEM_DATA_SIZE + 5);
//write_number = write(fd, frame_data, XMODEM_DATA_SIZE + 5);
GPS_LOGD("Retry for ACK,%d...", pack_counter);
//while((read(fd, &ack_id, 1)) <= 0);
if(select_read(1000))
{
//read(fd,&ack_id,1);
deal_read(&ack_id,1);
}
if( ack_id == XMODEM_ACK )
GPS_LOGI("OK\n");
else
GPS_LOGE("Error!\n");
}
break;
default:
GPS_LOGE("Fatal Error! %d\n", ack_id);
complete = 1;
return -1;
}
}
quec_gnss_firm_close(t);
return 0;
}
/*check=>reset=>bootloader=>apflash=>firmware*/
extern int quec_gnss_type_check(void);
extern int quec_hx_bckp_get(void);
int hx_gnss_upgrade(unsigned int reset_pin_num)
{
unsigned int reset_sucess = 0;
int downloader_bootload = 0;
int downloader_firmware = 0;
int downloader_apflash = 0;
int i;
int retry = 0;
char name[20]={0};
char rbuf[1024];
int bootloader_file_sta=0;
int firmware_file_sta=0;
int apflash_file_sta = 0;
unsigned int rByte=0;
int gnss_rom_type = quec_gnss_type_check();
int gnss_vbckp_select = quec_hx_bckp_get();
if((2==gnss_rom_type)&&(0 == gnss_vbckp_select)){
gnss_rom_type = 3;//20231011 add type 3:ROM2不接备电
}
quec_gnss_apflash_struct_t *gnss_apflash = get_hx_apflash_req_status();
GPS_LOGI("L26 1st start, chenck bootloader&firmware checksum\r\n");
//1st,check bootloader and firmware
bootloader_file_sta = check_firmware_is_vailed(GNSS_BOOT_TYPE);
firmware_file_sta = check_firmware_is_vailed(GNSS_KERNEL_TYPE);
if((1 == gnss_rom_type) ||(3 == gnss_rom_type))
{
if(gnss_apflash->en){
apflash_file_sta = check_firmware_is_vailed(GNSS_APFLASH_TYPE);
}
}
if(bootloader_file_sta<0 || firmware_file_sta<0)
{
GPS_LOGE("L26 check error! bootloader_file_sta:%d,firmware_file_sta%d\r\n",bootloader_file_sta,firmware_file_sta);
return HX_L26_INIT_CHECKSUM_ERROR;
}
GPS_LOGI("L26 2nd start,reset L26\r\n");
GPS_COM_Init();
#if defined (HX_GNSS_CC11_SUPPORT)
GPS_COM_SetBaudRate(GNSS_UART_BAUD_1843200);
#else
GPS_COM_SetBaudRate(GNSS_UART_BAUD_230400);
#endif
quec_gnss_power_on_off(0);
gps_delay_ms(50);
quec_gnss_power_on_off(1);
for(i = 0; i < 20; i++)
{
GPS_COM_PurgeFIFO();
reset_sucess = send_request_and_response_is_ok();
if(reset_sucess)
{
GPS_LOGI("L26 2rd ok\r\n");
break;
}
else
{
GPS_LOGE("L26 2rd err\r\n");
quec_gnss_power_on_off(0);
gps_delay_ms(50);
quec_gnss_power_on_off(1);
}
}
if(!reset_sucess)
{
GPS_LOGE("L26 reset failed \r\n");
return HX_L26_INIT_RESET_ERROR;
}
GPS_LOGI("L26 3th start, downloader l26 bootloader\r\n");
//4th,send bootloader file to uc6226
GPS_COM_PurgeFIFO();
downloader_bootload = xmodem_send(GNSS_BOOT_TYPE);
if(!downloader_bootload)
{
GPS_LOGI("L26 3th ok\r\n");
}
else
{
GPS_LOGE("L26 downloader_bootload failed \r\n");
return HX_L26_INIT_DOWNLOAD_BOOT_ERROR;
}
#if defined (HX_GNSS_CC11_SUPPORT)
quec_rtos_task_sleep_ms(100);
#else
//切换波特率1843200
GPS_COM_SetBaudRate(GNSS_UART_BAUD_1843200);
while(retry<10) {
if(select_read(500))
{
rByte=deal_read((char*)rbuf,sizeof(rbuf)-1);
rbuf[rByte] = 0;
GPS_LOGI( "%s", rbuf);
if(strstr(rbuf,"Begin to download from uart and run") != NULL)//此处根据厂商规定修改,实测发现厂商不同固件有区别
break;
}
else
{
GPS_LOGI("retry...\n");
retry++;
}
}
#endif
GPS_LOGI("L26 4th start,downloader l26 firmware \r\n");
if((1 == gnss_rom_type) ||(3 == gnss_rom_type))
{
if(!apflash_file_sta && gnss_apflash->en){
GPS_LOGI("apflash check ok\r\n");
if(select_read(5)){/*clear buffer 发现有概率性升级失败可能rb数据没清*/
rByte=deal_read((char*)rbuf,sizeof(rbuf)-1);
rbuf[rByte] = 0;
GPS_LOGI( "%s", rbuf);
}
downloader_apflash = xmodem_send(GNSS_APFLASH_TYPE);
if(!downloader_firmware)
{
GPS_LOGI("L26 4th ok\r\n");
}
else
{
GPS_LOGE("L26 downloader_apflash failed \r\n");
return HX_L26_INIT_DOWNLOAD_APFLSH_ERROR;
}
#ifndef HX_GNSS_CC11_SUPPORT
if(select_read(500)){
rByte=deal_read((char*)rbuf,sizeof(rbuf)-1);
rbuf[rByte] = 0;
GPS_LOGI( "%s", rbuf);
}
sprintf(name,"2\n");
GPS_COM_PutByte_Buffer((char*)name,2);
if(select_read(500)){
rByte=deal_read((char*)rbuf,sizeof(rbuf)-1);
rbuf[rByte] = 0;
GPS_LOGI( "%s", rbuf);
}
#endif
}
else {
GPS_LOGE("APFLASH\r\n");
}
}
if(select_read(5)){/*clear buffer 发现有概率性升级失败可能rb数据没清*/
rByte=deal_read((char*)rbuf,sizeof(rbuf)-1);
rbuf[rByte] = 0;
GPS_LOGI( "%s", rbuf);
}
downloader_firmware = xmodem_send(GNSS_KERNEL_TYPE);
if(!downloader_firmware)
{
GPS_LOGI("L26 5th ok\r\n");
}
else
{
GPS_LOGE("L26 downloader_kernel failed \r\n");
return HX_L26_INIT_DOWNLOAD_FIRMWARE_ERROR;
}
#if defined (HX_GNSS_CC11_SUPPORT)
GPS_COM_SetBaudRate(GNSS_UART_BAUD_460800);
#else
GPS_COM_SetBaudRate(GNSS_UART_BAUD_230400);
#endif
retry = 0;
while(retry<50) {
if(select_read(1000) > 0)
{
rByte = deal_read((char*)rbuf,sizeof(rbuf)-1);
rbuf[rByte] = 0;
GPS_LOGI( "%s", rbuf);
if(strstr(rbuf,"RMC") != NULL){
#ifndef HX_GNSS_CC11_SUPPORT
GPS_COM_PutByte_Buffer("$CFGPRT,1,h0,230400,129,35\r\n",sizeof("$CFGPRT,1,h0,230400,129,35\r\n"));
GPS_COM_PutByte_Buffer("$CFGSAVE\r\n",sizeof("$CFGSAVE\r\n"));
#endif
break;
}
}
retry++;
}
GPS_COM_PurgeFIFO();
return HX_L26_INIT_NO_ERROR;
}
void quec_gnss_power_on_off(int flags)
{
if(gps_gpio_pin.pwr_en)
{
#if defined (__QUECTEL_PROJECT_EG915NLA_GK__)
*(volatile unsigned long *)(GPIO_MFPR_ADDR(gps_gpio_pin.pwr_en)) = MFP_AF0;
#else
*(volatile unsigned long *)(GPIO_MFPR_ADDR(gps_gpio_pin.pwr_en)) = MFP_AF1;
#endif
/*power_enable脚配置为输出低,mos管导通,给gnss供电*/
GpioSetDirection(gps_gpio_pin.pwr_en, GPIO_OUT_PIN);
GpioSetLevel(gps_gpio_pin.pwr_en, !flags);
}
else{
GuilinLite_Ldo_8_set(flags);
if(flags)
{
GuilinLite_Ldo_8_set_1_8();
}
}
}
int hx_gnss_open(void)
{
int ret = HX_L26_INIT_NO_ERROR;
ret = hx_gnss_upgrade(gps_gpio_pin.rst);
return ret;
}
int hx_gnss_close(void)
{
quec_gnss_power_on_off(0);
return HX_L26_INIT_NO_ERROR;
}
static const unsigned short crc16tab[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
unsigned short crc16_ccitt(const char *buf, int len)
{
register int counter;
register unsigned short crc = 0;
for (counter = 0; counter < len; counter++)
crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ *(char *)buf++) & 0x00FF];
return crc;
}