blob: d797f0490836980d237768fe5efc5ade4c6d2f9e [file] [log] [blame]
#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);
// 设置串口波特率
int set_baudrate(int fd, int baudrate);
// 检测串口数据
static int select_read(int fd, int timeout);
// 读取串口数据
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;
}