| #include <sys/stat.h> |
| #include <sys/time.h> |
| #include <errno.h> |
| #include <time.h> |
| #include <stdio.h> |
| #include <fcntl.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <sys/times.h> |
| #include <sys/types.h> |
| #include <termios.h> |
| #include <unistd.h> |
| #include <sys/ioctl.h> |
| #include <sys/wait.h> |
| #include <ctype.h> |
| #include <sched.h> |
| #include <limits.h> |
| #include <linux/serial.h> |
| |
| #define RTM_FILE_NAME "rtm.bin" |
| |
| #define PARA_ERR -1 |
| #define FILE_CHECK_ERR -2 |
| #define ENTER_UPDATE_MODE_ERR -3 |
| #define UPDATE_ERR -4 |
| #define UART_DEV_ERR -5 |
| |
| #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 |
| |
| #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 |
| |
| |
| /****************************************************************************** |
| * 时间处理相关的宏 |
| *****************************************************************************/ |
| // 时间超时标志 |
| int timeout_sign = 1; |
| // 获取当前时间 |
| #define GET_TIME() { gettimeofday(&time_m, NULL); \ |
| time_m.tv_sec += TIMEOUT_SEC;\ |
| } |
| // 设置从循环中退出的时间 |
| #define SET_TIME_OUT(x) { gettimeofday(&time_m, NULL); \ |
| time_m.tv_sec += x;\ |
| } |
| // 检测时间是否超时,超时则退出当前函数 |
| #define CHK_TIME() { gettimeofday(&time_n, NULL); \ |
| if(time_n.tv_sec > time_m.tv_sec) { \ |
| printf("\ntimeout!!!\n\n");\ |
| close(fd); \ |
| return ret; \ |
| } \ |
| } |
| // 检测时间是否超时,超时则退出当前循环 |
| #define CHK_TIME_BREAK() { gettimeofday(&time_n, NULL); \ |
| if(time_n.tv_sec > time_m.tv_sec) { \ |
| timeout_sign = 1; \ |
| printf("\ntimeout!!!\n\n");\ |
| break; \ |
| } \ |
| } |
| // 检测延时是否到达,到达则退出当前循环 |
| #define DELAY_TIME_BREAK() { gettimeofday(&time_n, NULL); \ |
| if(time_n.tv_sec > time_m.tv_sec) { \ |
| timeout_sign = 1; \ |
| break; \ |
| } \ |
| } |
| |
| // 检测时间是否超时,超时则退出当前函数 |
| #define CHK_TIME1() { gettimeofday(&time_n, NULL); \ |
| if(time_n.tv_sec > time_m.tv_sec) { \ |
| printf("\ntimeout!!!\n\n");\ |
| if(datafile != NULL) \ |
| fclose(datafile); \ |
| return ret; \ |
| } \ |
| } |
| |
| |
| /****************************************************************************** |
| * APData 相关定义、声明 |
| *****************************************************************************/ |
| // APData 数据头部定义 |
| typedef struct { |
| unsigned int ih_magic; // Image Header Magic Number |
| unsigned int ih_dcrc; // Image Data CRC checksum |
| unsigned int ih_time; // Image Creation Timestamp |
| unsigned int ih_size; // Image Data Size |
| unsigned int ih_compress; // Image Header compress or not:0, not compress |
| unsigned int pkg_flash_addr; // flash memory offset for package |
| unsigned int pkg_run_addr; // Run time address for this package |
| unsigned int ih_hcrc; // Image Header CRC checksum |
| } uc_image_header_t; |
| |
| // APData 数据头部长度 |
| #define HEADERLEN 32 |
| // APData 接收状态类型 |
| typedef enum ReceStat{ |
| WAIT_FD = 1, |
| WAIT_FC, |
| WAIT_FB, |
| WAIT_FA, |
| RECE_HEADER, |
| RECE_DATA, |
| } RecvStat_t; |
| // APData 接收状态变量 |
| static RecvStat_t recvStat = WAIT_FD; |
| // APData 接收状态变量 |
| static int isStartReceive = 0; |
| // APData 开始接收 |
| void af_start_receive(); |
| // APData 停止接收,在数据接收完成或出错时调用 |
| void af_stop_receive(); |
| // 获取isStartReceive 变量值 |
| int af_is_start_receive(); |
| // APData 数据接收入口 |
| int af_add_char(char *file, unsigned char c); |
| // 校验 APData 数据头 |
| int af_check_header(unsigned char *pbuf, unsigned int len); |
| // 校验 APData 数据区 |
| int af_check_data(unsigned int * pbuf, unsigned int len); |
| // 获取 APData 数据长度 |
| int af_get_data_len(); |
| // APData 数据接收缓存 |
| unsigned int recv_buf[1024 * 2]; |
| unsigned char *pbuf; |
| int data_len; |
| // 校验文件 |
| int check_file(char *fname); |
| |
| /****************************************************************************** |
| * 与接收机串口通讯相关定义、声明 |
| *****************************************************************************/ |
| // select功能使用变量 |
| static int use_select = 1; |
| // 初始化串口资源 |
| int initial_serialPort(char * serial_device); |
| // 设置串口波特率 |
| static int set_baudrate(int fd, int baudrate); |
| // 检测串口数据 |
| static int select_read(int fd, int timeout); |
| // 读取串口数据 |
| static ssize_t deal_read(int fd, void *buf, size_t count); |
| // 向接收机发送串口数据 |
| static void gps_dev_send(int fd, char *msg); |
| // 通过xmodem协议向接收机发送串口数据 |
| int xmodem_send(int fd, char *fname); |
| |
| /****************************************************************************** |
| * apflash 功能函数 |
| *****************************************************************************/ |
| // 检测接收机发送的'YC'信号,如果收到,则标志着接收机进入boot模式,并可以通过xmodem发送数据 |
| int check_YC(char newchar); |
| // 获取 APData 数据, 应该在接收机定位且星历数据接收完整时获取 |
| int getAPData(int fd, char *file); |
| // 向接收机发送 APData 数据,有效的APData数据可以让CI模块迅速定位 |
| int sendAPData(int fd, char *ap); |
| // 校验 APData 数据文件 |
| int checkAPData(char *apFile); |
| // 为接收机加载BootLoader,该流程执行时,需要根据终端提示,给接收机下电和上电,确保接收机进入boot模式 |
| int downloadBL(int fd, char *bl); |
| // 为接收机加载Firmware,该流程必须在加载BootLoader之后进行 |
| int downloadFW(int fd, char *fw); |
| |
| void printGetapUsage(char *app) |
| { |
| printf("\n%s getap -d receiverPort [-b baudrate] [-h] -a apfile \n", app); |
| printf("\tfunction: read APData from receiver\n"); |
| printf("\tparas:\n"); |
| printf("\t\treceiverPort: Port that connected to receiver\n"); |
| printf("\t\tbaudrate: baudrate of receiverPort\n"); |
| } |
| |
| void printSendapUsage(char *app) |
| { |
| printf("\n%s sendap -d receiverPort [-b baudrate] [-h] -a apfile\n", app); |
| printf("\tfunction: send APData to receiver\n"); |
| printf("\tparas:\n"); |
| printf("\t\treceiverPort: Port that connected to receiver\n"); |
| printf("\t\tbaudrate: baudrate of receiverPort\n"); |
| } |
| |
| void printCheckapUsage(char *app) |
| { |
| printf("\n%s checkap -a apfile [-h]\n", app); |
| printf("\tfunction: check APData\n"); |
| printf("\tparas:\n"); |
| printf("\t\tapfile: APData file\n"); |
| } |
| |
| void printDownloadblUsage(char *app) |
| { |
| printf("\n%s downbl -d receiverPort [-b baudrate] -l bootloader [-h]\n", app); |
| printf("\tfunction: download bootloader to receiver\n"); |
| printf("\tparas:\n"); |
| printf("\t\treceiverPort: Port that connected to receiver\n"); |
| printf("\t\tbaudrate: baudrate of receiverPort\n"); |
| printf("\t\tbootloader: bootloader file\n"); |
| } |
| |
| void printDownloadfwUsage(char *app) |
| { |
| printf("\n%s downfw -d receiverPort [-b baudrate] -f firmware [-h]\n", app); |
| printf("\tfunction: download firmware to receiver\n"); |
| printf("\tparas:\n"); |
| printf("\t\treceiverPort: Port that connected to receiver\n"); |
| printf("\t\tbaudrate: baudrate of receiverPort\n"); |
| printf("\t\tfirmware: firmware file\n"); |
| } |
| |
| void printUsage(char *app) |
| { |
| printGetapUsage(app); |
| printSendapUsage(app); |
| printCheckapUsage(app); |
| printDownloadblUsage(app); |
| printDownloadfwUsage(app); |
| } |
| |
| #define GPS_DEV "/sys/devices/soc.0/d4000000.apb/mbtk-dev-op/gps_power" |
| |
| static int mopen_open_gps(int state) |
| { |
| int fd, ret; |
| char s[4] = "on"; |
| fd = open(GPS_DEV, O_RDWR | O_TRUNC, 0644); |
| if(fd < 0) { |
| printf("[%s] file [%s] open error\n", __FUNCTION__, GPS_DEV); |
| return -1; |
| } |
| if(0 == state) |
| { |
| memcpy(s, "off", 3); |
| } |
| ret = write(fd, s, 4); |
| if (ret < 0) { |
| printf("%s: error writing to file!\n", __FUNCTION__); |
| close(fd); |
| return -2; |
| } |
| |
| close(fd); |
| return 0; |
| } |
| |
| int main(int argc, char *argv[]) |
| { |
| int c; |
| int ret = 0; |
| int fd = -1; |
| int paraMask = 0; |
| int baud = 115200; |
| char devPort[200] = {0}; |
| char fw[200] = {0}; |
| char bl[200] = {0}; |
| char ap[200] = {0}; |
| int func = 0; // 1:getap, 2:sendap, 3:downbl, 4:downfw, 5:checkap |
| |
| // Verify arguments |
| if (argc < 2) { |
| printf("Usage:\n"); |
| printUsage(argv[0]); |
| exit(1); |
| } |
| |
| if(strcmp(argv[1], "getap") == 0) { |
| func = 1; |
| paraMask = 1; |
| } else if (strcmp(argv[1], "sendap") == 0) { |
| func = 2; |
| paraMask = 1; |
| } else if (strcmp(argv[1], "downbl") == 0) { |
| func = 3; |
| paraMask = 9; |
| } else if (strcmp(argv[1], "downfw") == 0) { |
| func = 4; |
| paraMask = 5; |
| } else if (strcmp(argv[1], "checkap") == 0) { |
| func = 5; |
| paraMask = 16; |
| } else { |
| printf("Usage:\n"); |
| printUsage(argv[0]); |
| exit(1); |
| } |
| |
| for(;;) { |
| opterr = 0; |
| c = getopt(argc, argv, "d:b:f:l:a:h"); |
| if(c < 0) |
| break; |
| switch(c) { |
| case 'd': |
| snprintf(devPort, 200, "%s", optarg); |
| printf("receiver port: %s\n", devPort); |
| paraMask &= ~1; |
| break; |
| case 'b': |
| baud = atoi(optarg); |
| printf("baud rate: %d\n", baud); |
| break; |
| case 'f': |
| snprintf(fw, 200, "%s", optarg); |
| printf("firmware: %s\n", fw); |
| paraMask &= ~4; |
| break; |
| case 'l': |
| snprintf(bl, 200, "%s", optarg); |
| printf("bootloader: %s\n", bl); |
| paraMask &= ~8; |
| break; |
| case 'a': |
| snprintf(ap, 200, "%s", optarg); |
| printf("apdata file: %s\n", ap); |
| paraMask &= ~16; |
| break; |
| case 'h': |
| default: |
| printf("Usage:\n"); |
| if (func == 1) |
| printGetapUsage(argv[0]); |
| else if (func == 2) |
| printSendapUsage(argv[0]); |
| else if (func == 3) |
| printDownloadblUsage(argv[0]); |
| else if (func == 4) |
| printDownloadfwUsage(argv[0]); |
| else if (func == 5) |
| printCheckapUsage(argv[0]); |
| else |
| printUsage(argv[0]); |
| exit(1); |
| } |
| } |
| if (paraMask) { |
| if (func == 1) |
| printGetapUsage(argv[0]); |
| else if (func == 2) |
| printSendapUsage(argv[0]); |
| else if (func == 3) |
| printDownloadblUsage(argv[0]); |
| else if (func == 4) |
| printDownloadfwUsage(argv[0]); |
| else if (func == 5) |
| printCheckapUsage(argv[0]); |
| else |
| printUsage(argv[0]); |
| exit(1); |
| } |
| |
| // Open serial port |
| if (func != 5) { |
| if ((fd = initial_serialPort(devPort)) == -1) |
| { |
| printf("Can't open COM\n"); |
| return UART_DEV_ERR; |
| } |
| if (baud == 115200) { |
| set_baudrate(fd, B115200); |
| } else if (baud == 921600) { |
| set_baudrate(fd, B921600); |
| } else if (baud == 1843200) { |
| set_baudrate(fd, B1500000); |
| } else { |
| printf("baudrate %d not supported\n", baud); |
| close(fd); |
| exit(1); |
| } |
| } |
| |
| // execute function |
| switch(func) { |
| case 1: |
| ret = getAPData(fd, ap); |
| break; |
| case 2: |
| ret = sendAPData(fd, ap); |
| break; |
| case 3: |
| ret = downloadBL(fd, bl); |
| break; |
| case 4: |
| ret = downloadFW(fd, fw); |
| break; |
| case 5: |
| ret = checkAPData(ap); |
| break; |
| default:break; |
| } |
| close(fd); |
| return ret; |
| |
| } |
| |
| int getAPData(int fd, char *file) |
| { |
| int rByte = 0; |
| char rbuf[4096]; |
| int ret = 0, i; |
| struct timeval time_m, time_n; |
| |
| if (NULL == file) { |
| printf("Please input file!! \n"); |
| return 1; |
| } |
| if (!fd) |
| return 1; |
| printf("Get apdata\n"); |
| gps_dev_send(fd, "$ReqRecvFlash\r\n"); |
| af_start_receive(); |
| GET_TIME(); |
| while(1) { |
| CHK_TIME(); |
| if(select_read(fd,1) > 0) |
| usleep(50000); |
| else |
| continue; |
| |
| rByte = deal_read(fd,&rbuf,sizeof(rbuf)); |
| if(rByte >= 1){ |
| if(af_is_start_receive()) { |
| for(i = 0; i < rByte; i++) |
| af_add_char(file, rbuf[i]); |
| } else { |
| break; |
| } |
| } |
| } |
| |
| checkAPData(file); |
| return 0; |
| } |
| |
| int sendAPData(int fd, char *apFile) |
| { |
| int rByte = 0; |
| char rbuf[4096]; |
| int ret = 0; |
| struct timeval time_m, time_n; |
| |
| if(access(apFile, F_OK) != -1) |
| { |
| // Download APData only if the file exits |
| printf("Download APData...\n"); |
| if(xmodem_send(fd, apFile)) |
| { |
| printf("xmodem error!\n"); |
| close(fd); |
| return ENTER_UPDATE_MODE_ERR; |
| } |
| // Waiting for 'C' |
| GET_TIME(); |
| while(1) |
| { |
| CHK_TIME(); |
| if(select_read(fd,1) > 0) |
| usleep(500000); |
| else |
| continue; |
| rByte = deal_read(fd,&rbuf,sizeof(rbuf)-1); |
| rbuf[rByte] = 0; |
| if(rByte > 0) |
| { |
| if(rbuf[rByte - 1] == 'C') |
| break; |
| } |
| } |
| printf("download APData success\n"); |
| } |
| else |
| { |
| printf("file err!\n"); |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| int checkAPData(char *apFile) |
| { |
| printf("Checking %s\n", apFile); |
| if(check_file(apFile)) |
| { |
| printf("file error!\n"); |
| return FILE_CHECK_ERR; |
| |
| } |
| else |
| { |
| printf("pass\r\n"); |
| } |
| return 0; |
| } |
| |
| int downloadFW(int fd, char *fw) |
| { |
| int ret; |
| struct timeval time_m, time_n; |
| char rbuf[512]; |
| |
| if(NULL == fw) { |
| printf("Error: Can't find firmware.\n"); |
| return -1; |
| } |
| printf("Download firmware...\n"); |
| if(xmodem_send(fd, fw) < 0) { |
| printf("xmodem error! send firmware failed!\n"); |
| close(fd); |
| return UPDATE_ERR; |
| } |
| |
| printf("Download firmware success\n"); |
| return 0; |
| } |
| |
| int downloadBL(int fd, char *bl) |
| { |
| int rByte = 0; |
| char rbuf[4096]; |
| char name[128]; |
| int ret = 0; |
| struct timeval time_m, time_n; |
| |
| if(NULL == bl) { |
| printf("Error: Can't find bootloader.\n"); |
| return -1; |
| } |
| printf("------Please Powerdown the receiver!\n"); |
| mopen_open_gps(0); |
| SET_TIME_OUT(3); |
| while(1) { |
| DELAY_TIME_BREAK(); // |
| if(select_read(fd,1) > 0) |
| usleep(50000); |
| else |
| continue; |
| |
| rByte = deal_read(fd,&rbuf,sizeof(rbuf)); |
| } |
| int start = 0,finish = 0; |
| |
| memset(name, 0, sizeof(name)); |
| sprintf(name,"M!T"); |
| printf("waiting for YC, timeout is %d s\n", TIMEOUT_SEC); |
| printf("-------Please Powerup the receiver!\n"); |
| mopen_open_gps(1); |
| // Waiting for 'YC' |
| GET_TIME(); |
| while(1) { |
| int finish = 0, i; |
| CHK_TIME_BREAK(); // |
| rByte = write( fd, name, strlen(name)); |
| rByte = select_read(fd,1); |
| if(rByte <= 0) |
| continue; |
| rByte = deal_read(fd, rbuf, sizeof(rbuf) - 1); |
| rbuf[rByte] = 0; |
| for (i = 0 ; i < rByte; i++) |
| { |
| if (check_YC(rbuf[i])) { |
| printf("Receive 'YC'\n"); |
| finish = 1; |
| break; |
| } |
| } |
| if (finish) |
| break; |
| } |
| //wait 'YC' timeout deal |
| if (timeout_sign == 1) |
| { |
| //wait NAK |
| GET_TIME(); |
| while(1) |
| { |
| CHK_TIME(); |
| if(select_read(fd,1) <= 0) |
| continue; |
| |
| rByte = deal_read(fd, rbuf,sizeof(rbuf)); |
| if (rbuf[rByte-1] == 'C') |
| { |
| printf("###read xmodem start character 'C'.\n"); |
| break; |
| } |
| } |
| } |
| use_select = 1; |
| printf("download bootloader...\n"); |
| |
| // Transfer bootloader via xmodem protocal |
| // if(xmodem_send(fd, "./bootloader.bin")) { |
| if(xmodem_send(fd, bl)) { |
| printf("xmodem error!\n"); |
| close(fd); |
| return ENTER_UPDATE_MODE_ERR; |
| } |
| printf("download bootloader success\n"); |
| return 0; |
| } |
| |
| int check_YC(char newchar) |
| { |
| int static state = 0; |
| int ret = 0; |
| switch (state) { |
| case 0: |
| if (newchar == 'Y') |
| state = 1; |
| break; |
| case 1: |
| if (newchar == 'C') { |
| state = 1; |
| ret = 1; |
| } |
| break; |
| default: |
| state = 0; |
| } |
| return ret; |
| } |
| |
| const unsigned short CRC16_Table[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 unsigned char *buf, int len) |
| { |
| register int counter; |
| register unsigned short crc = 0; |
| for (counter = 0; counter < len; counter++) |
| crc = (crc << 8) ^ CRC16_Table[((crc >> 8) ^ *(char *)buf++) & 0x00FF]; |
| return crc; |
| } |
| |
| |
| unsigned int checksum32(unsigned int * pbuf, unsigned int len) |
| { |
| unsigned int i, sumValue = 0; |
| len >>=2; |
| |
| for(i=0;i<len;i++) |
| { |
| sumValue += *pbuf++; |
| } |
| return sumValue; |
| } |
| |
| void af_start_receive() |
| { |
| recvStat = WAIT_FD; |
| isStartReceive = 1; |
| return; |
| } |
| |
| void af_stop_receive() |
| { |
| int i; |
| printf("%s:%d\r\n", __FUNCTION__, __LINE__); |
| printf("%s:%d recvStat = %d\r\n", __FUNCTION__, __LINE__, recvStat); |
| pbuf = (unsigned char *)recv_buf; |
| for(i = 0; i < 4636; i++){ |
| if(i % 32 == 0)printf("\r\n"); |
| printf("%02X ", pbuf[i]); |
| } |
| printf("\r\n"); |
| isStartReceive = 0; |
| return; |
| } |
| |
| int af_is_start_receive() |
| { |
| return isStartReceive; |
| } |
| |
| int af_check_header(unsigned char *pbuf, unsigned int len) |
| { |
| unsigned int crc = crc16_ccitt(pbuf, len-4); |
| |
| if(crc == *(unsigned int *)(pbuf + len - 4)) |
| return 1; |
| else |
| return 0; |
| } |
| |
| int af_check_data(unsigned int * pbuf, unsigned int len) |
| { |
| unsigned int cs = checksum32(pbuf + 8, len); |
| if(cs == pbuf[1]) |
| return 1; |
| else |
| return 0; |
| } |
| |
| int af_get_data_len() |
| { |
| int len = *(int *)(recv_buf+3); |
| return len; |
| } |
| |
| int af_add_char(char *file, unsigned char c) |
| { |
| int ret = 0; |
| switch(recvStat){ |
| case WAIT_FD: |
| if(c == 0xfd){ |
| pbuf = (unsigned char *)recv_buf; |
| pbuf[0] = c; |
| recvStat = WAIT_FC; |
| printf("------------received 0xfd\r\n"); |
| } |
| break; |
| case WAIT_FC: |
| if(c == 0xfc){ |
| pbuf[1] = c; |
| recvStat = WAIT_FB; |
| printf("------------received 0xfc\r\n"); |
| }else{ |
| af_stop_receive(); |
| } |
| break; |
| case WAIT_FB: |
| if(c == 0xfb){ |
| pbuf[2] = c; |
| recvStat = WAIT_FA; |
| printf("------------received 0xfb\r\n"); |
| }else{ |
| af_stop_receive(); |
| } |
| break; |
| case WAIT_FA: |
| if(c == 0xfa){ |
| pbuf[3] = c; |
| recvStat = RECE_HEADER; |
| pbuf += 4; |
| printf("------------received 0xfa\r\n"); |
| }else{ |
| af_stop_receive(); |
| } |
| break; |
| case RECE_HEADER: |
| *pbuf = c; |
| pbuf++; |
| if((pbuf - (unsigned char *)recv_buf) == HEADERLEN){ |
| if(af_check_header((unsigned char *)recv_buf, HEADERLEN)){ |
| recvStat = RECE_DATA; |
| data_len = af_get_data_len(); |
| }else{ |
| af_stop_receive(); |
| } |
| } |
| break; |
| case RECE_DATA: |
| *pbuf = c; |
| pbuf++; |
| if((pbuf - (unsigned char *)recv_buf) == data_len + HEADERLEN){ |
| if(af_check_data(recv_buf, recv_buf[3])){ |
| int fd = open(file, O_WRONLY|O_CREAT, S_IRWXU); |
| write(fd, recv_buf, pbuf - (unsigned char *)recv_buf); |
| printf("%s:%d rtm len = %ld\r\n", __FUNCTION__, __LINE__, pbuf-(unsigned char *)recv_buf); |
| close(fd); |
| printf("receive rtm\n"); |
| }else{ |
| printf("af_check_data false!"); |
| } |
| af_stop_receive(); |
| } |
| ret = 1; |
| break; |
| default: |
| printf("%s:recvStat = %d\r\n", __FUNCTION__, recvStat); |
| break; |
| } |
| return ret; |
| } |
| |
| |
| |
| ssize_t deal_read(int fd, void *buf, size_t count) |
| { |
| int ret = 0; |
| |
| while (1) |
| { |
| ret = read(fd, buf, count); |
| if (ret == 0) |
| { |
| printf("read serial return 0, please check serial device.\n"); |
| exit(UART_DEV_ERR); |
| } |
| if(ret < 0) |
| { |
| if ((errno == EAGAIN) || (errno == EINTR)) |
| { |
| printf("read serial return -1, errno = %d, retry.\n", errno); |
| continue; |
| } |
| else |
| { |
| printf("read serial return -1, errno = %d, please check serial device.\n", errno); |
| exit(UART_DEV_ERR); |
| } |
| } |
| return ret; |
| } |
| } |
| |
| 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); |
| } |
| |
| void dump_u(void *buf, int len) |
| { |
| unsigned char *p = (unsigned char *)buf; |
| int i; |
| |
| for(i = 0; i < len; i++) { |
| if(i % 16 == 0) printf("%04x:", i); |
| if(i % 16 == 8) printf(" -"); |
| printf(" %02x", p[i]); |
| if(i % 16 == 15) printf("\n"); |
| } |
| if(i % 16) printf("\n"); |
| } |
| |
| unsigned int get_file_size(const char * name) |
| { |
| struct stat statbuff; |
| //unsigned int size, checksum; |
| if(stat(name, &statbuff) < 0) |
| return -1; |
| else |
| return statbuff.st_size; |
| } |
| |
| |
| int check_file(char * fname) |
| { |
| FILE *fd; |
| uc_image_header_t header; |
| unsigned int buf[1024]; |
| unsigned int fsize, checksum, i; |
| unsigned int len; |
| unsigned short crc; |
| size_t rByte; |
| |
| if((fd=fopen(fname,"rb"))==NULL) |
| { |
| printf("\n can't open (%s) or not exist!(errno=%d:%s) \n", fname, errno, strerror(errno)); |
| return -1; |
| } |
| |
| fsize = get_file_size(fname); |
| |
| printf("file size [%d]\n",fsize); |
| |
| if(fsize == 0) |
| return -1; |
| |
| while(fsize > sizeof(header)) { |
| rByte = fread((char *)&header, sizeof(char), sizeof(header), fd); |
| |
| dump_u((char *)&header, sizeof(header)); |
| |
| crc = get_crc16 ( (char *) &header, sizeof(header)-4); |
| printf("crc16 [%08x]\n", crc); |
| |
| if((header.ih_hcrc & 0xFFFF) != crc) { |
| fclose(fd); |
| return -1; |
| } |
| |
| fsize -= sizeof(header); |
| fsize -= header.ih_size; |
| checksum = 0; |
| len = header.ih_size; |
| while(len > 0) |
| { |
| if(len >= 1024 ) |
| rByte = 1024; |
| else |
| rByte = len; |
| |
| memset(buf, 0, sizeof(buf)); |
| rByte = fread((char *)buf, 1, rByte, fd); |
| for(i = 0; i < (rByte+3)/4; i++) |
| checksum += buf[i]; |
| |
| len -= rByte; |
| } |
| printf("checksum [%08x]\n\n",checksum); |
| |
| if( checksum != header.ih_dcrc) { |
| fclose(fd); |
| return -1; |
| } |
| } |
| |
| fclose(fd); |
| return 0; |
| } |
| |
| static int select_read(int fd, int timeout) //1ms |
| { |
| fd_set set; |
| struct timeval t; |
| int ret; |
| int i = timeout; |
| |
| if(use_select) { |
| do { |
| FD_ZERO(&set); |
| FD_SET(fd, &set); |
| t.tv_sec = 0; |
| t.tv_usec = 100; |
| |
| ret = select(FD_SETSIZE, &set, NULL, NULL, &t ); |
| if(ret == 0) continue; |
| if(ret < 0 && errno == EINTR)continue; |
| else return ret; |
| } while(i--); |
| } else { |
| struct timeval t0, t1; |
| long dt = 0; |
| int c; |
| |
| gettimeofday(&t0, NULL); |
| do { |
| c = 0; |
| ret = ioctl(fd, FIONREAD, &c); |
| if(c > 0) { ret = c; break; } |
| |
| gettimeofday(&t1, NULL); |
| dt = t1.tv_usec - t0.tv_usec; |
| dt += (t1.tv_sec-t0.tv_sec)*1000*1000; |
| } while(dt/1000 < timeout); |
| } |
| |
| return ret; |
| } |
| |
| int set_baudrate(int fd, int baudrate) |
| { |
| struct termios options, oldtio; |
| |
| if(fcntl(fd, F_SETFL, 0) < 0) { |
| printf("fcntl failed!\n"); |
| return -1; |
| } |
| |
| if(tcgetattr(fd, &oldtio) != 0) { |
| printf("setup serial error!\n"); |
| return -1; |
| } |
| |
| /* Get the current options for the port... */ |
| tcgetattr(fd, &options); |
| |
| /* Set the baud rates to baudrate... */ |
| cfsetispeed(&options,baudrate); |
| cfsetospeed(&options,baudrate); |
| tcsetattr(fd, TCSANOW, &options); |
| |
| if (0 != tcgetattr(fd, &options)) |
| { |
| printf("get options error!\n"); |
| return -1; |
| } |
| |
| /* |
| * 8bit Data,no partity,1 stop bit... |
| */ |
| options.c_cflag &= ~PARENB;//无奇偶校验 |
| options.c_cflag &= ~CSTOPB;//停止位,1位 |
| options.c_cflag &= ~CSIZE; //数据位的位掩码 |
| options.c_cflag |= CS8; //数据位,8位 |
| |
| cfmakeraw(&options); |
| |
| /* |
| * Set the new options for the port... |
| */ |
| if (tcsetattr(fd, TCSANOW, &options) != 0) |
| { |
| printf("setup serial error!\n"); |
| return -1 ; |
| } |
| |
| return 0 ; |
| } |
| |
| int initial_serialPort(char * serial_device) |
| { |
| int fd; |
| fd = open( serial_device , O_RDWR ); |
| if ( fd == -1 ) |
| { |
| /* open error! */ |
| printf("Can't open serial port(%s)!(errno=%d:%s) \n", serial_device, errno, strerror(errno)); |
| return -1; |
| } |
| |
| set_baudrate(fd, B9600); |
| |
| return fd ; |
| } |
| |
| static void gps_dev_send(int fd, char *msg) |
| { |
| int i, n, ret; |
| |
| i = strlen(msg); |
| |
| n = 0; |
| |
| printf("function gps_dev_send: %s", msg); |
| do { |
| |
| ret = write(fd, msg + n, i - n); |
| |
| if (ret < 0 && errno == EINTR) { |
| continue; |
| } |
| |
| n += ret; |
| |
| } while (n < i); |
| |
| // drain cmd |
| tcdrain(fd); |
| |
| return; |
| } |
| |
| int xmodem_send(int fd, char *fname) |
| { |
| char packet_data[XMODEM_DATA_SIZE]; |
| char frame_data[XMODEM_DATA_SIZE + XMODEM_CRC_SIZE + XMODEM_FRAME_ID_SIZE + 1]; |
| int ret = -1; |
| |
| FILE *datafile; |
| int complete,retry_num,pack_counter,read_number,write_number,i; |
| unsigned short crc_value; |
| unsigned char ack_id = 'C'; |
| struct timeval time_m, time_n; |
| |
| datafile = NULL; |
| pack_counter = 0; // 包计数器清零 |
| complete = 0; |
| retry_num = 0; |
| |
| printf("[%s]\n",fname); |
| //只读方式打开一个准备发送的文件,如果不存在就报错,退出程序。 |
| if((datafile=fopen(fname,"rb"))==NULL) |
| { |
| printf("\n can't open (%s) or not exist!(errno=%d:%s) \n", fname, errno, strerror(errno)); |
| return -1; |
| } |
| else |
| { |
| printf("Ready to send the file:%s\n",fname); |
| } |
| |
| printf("Waiting for signal C/NAK!\n"); |
| GET_TIME(); |
| while(1) |
| { |
| CHK_TIME1(); |
| if(select_read(fd,1) > 0) |
| usleep(10000); |
| else |
| continue; |
| |
| //read(fd,&ack_id,1); |
| deal_read(fd,&ack_id,1); |
| if(ack_id == 'C') |
| break; |
| } |
| |
| printf("The signal NAK: %02x ok!!!\n",ack_id);//打印接收到的NAK信息 |
| |
| while(!complete) |
| { |
| switch(ack_id) |
| { |
| case XMODEM_CRC_CHR: // 接收到字符'C'开始启动传输,并使用CRC校验 |
| printf("begining to Send file %s...\n",fname); |
| |
| case XMODEM_ACK: //0x06 |
| retry_num = 0; |
| pack_counter++; |
| |
| read_number = fread(packet_data, sizeof(char), XMODEM_DATA_SIZE, datafile); |
| //从打开的datafile指向的文件中读取 |
| //XMODEM_DATA_SIZE 个(char)数据, |
| //放到packet_data这个数组中 |
| if(read_number > 0)//read_number为返回的读取实际字节数 |
| { |
| //printf("test:read_number:%d\n", read_number); |
| if(read_number < XMODEM_DATA_SIZE_STX) |
| { |
| printf("Start filling the last frame!\n"); |
| for(; read_number < XMODEM_DATA_SIZE; read_number++) |
| packet_data[read_number] = 0x1A; // 不足128字节用0x1A填充 |
| //printf("replenish data.\n"); |
| } |
| |
| 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] = (unsigned char)(crc_value >> 8);// 高八位数据 |
| frame_data[XMODEM_DATA_SIZE+4] = (unsigned char)(crc_value); //低八位数据 |
| |
| /* 发送133字节数据 */ |
| write_number = write( fd, frame_data, XMODEM_DATA_SIZE + 5);//向串口写一个包数据,即133字节数据 |
| printf("."); //ADD: process |
| fflush(stdout); |
| //printf("waiting for next ACK... \n......\n"); |
| |
| GET_TIME(); |
| while(1) |
| { |
| CHK_TIME1(); |
| if(select_read(fd,1) > 0) |
| usleep(10000); |
| else |
| continue; |
| |
| //read(fd,&ack_id,1); |
| deal_read(fd,&ack_id,1); |
| break; |
| } |
| |
| if(ack_id == XMODEM_ACK) { |
| //printf("ACK Ok!!Ready sending next pack!\n"); |
| ; |
| } |
| else |
| { |
| printf("ACK Error!\n"); |
| printf("0x%02X\n",ack_id); |
| //printf("pack_counter = %d\n", pack_counter); |
| } |
| } |
| |
| else // 文件发送完成 |
| { |
| ack_id = XMODEM_EOT; |
| complete = 1; |
| printf("Complete ACK\n"); |
| |
| GET_TIME(); |
| while(ack_id != XMODEM_ACK) |
| { |
| CHK_TIME1(); |
| ack_id = XMODEM_EOT; |
| write_number = write(fd,&ack_id,1); |
| while((deal_read(fd, &ack_id, 1)) <= 0); |
| } |
| printf("Send file successful!!!\n"); |
| fclose(datafile); |
| datafile = NULL; |
| } |
| break; |
| |
| case XMODEM_NAK: |
| if( retry_num++ > 10) |
| { |
| printf("Retry too many times,Quit!\n"); |
| complete = 1; |
| } |
| else //重试,发送 |
| { |
| write_number = write(fd, frame_data, XMODEM_DATA_SIZE + 5); |
| printf("Retry for ACK,%d,%d...", pack_counter, write_number); |
| |
| GET_TIME(); |
| while(1) |
| { |
| CHK_TIME1(); |
| if(select_read(fd,1) > 0) |
| usleep(100); |
| else |
| continue; |
| |
| //read(fd,&ack_id,1); |
| deal_read(fd,&ack_id,1); |
| break; |
| } |
| |
| if( ack_id == XMODEM_ACK ) |
| printf("OK\n"); |
| else |
| printf("Error!\n"); |
| } |
| break; |
| default: |
| printf("Fatal Error! %d\n", ack_id); |
| complete = 1; |
| return -1; |
| break; |
| } |
| } |
| |
| if( datafile != NULL ) |
| fclose(datafile); |
| |
| return 0; |
| } |