您的位置:首页 > 运维架构 > Linux

linux串口通信协议编程详解

2016-10-26 21:28 92 查看
1.串口通信协议拟定;

2.通信校验--CRC;

3.Linux多线程编程;

1.串口通信协议;

1.1协议拟定:

项目

长度

定义

备注

帧头(head)

1

0xf4

恒不变

流水号(serial _num)

2

消息的流水号

累加(先低8位后高8位)

长度

1

Length

帧总长(含前3字节,最大255)

属性

2

设备通信类型或数据类型、数据加密、校验方式、是否分包、数据类型、数据发送方式

低位对齐

数据包

PackageLength=Length-7

Package

承载的数据

校验

2

CRC16

使用CRC16算法对前面所有内容进行

帧尾

1

0x4f

恒不变

示例数据:

0xf4,0x00,0x17,0x03,0x00,0x11,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x78,0x67,0x4f

黑色部分为桢头

蓝色部分为流水号

紫色部分为长度

灰色部分是属性

红色部分为数据(可以将你们的数据放在此部分,长度最大64字节)

金色部分为校验(CRC16,具体算法参考后面提供的代码)

棕色部分尾帧尾

协议的初始化关于head(标示头)、serial_num(流水号)、length(数据长度)、properity(属性)、CRC(校验码)和tail(标示尾);

属性里包括:


5

4

3

2

1

0

定义通信的属性 比如设备类型

数据加密类型

校验方式

00 ->

01 -> D5

10 ->

11 -> others

00 - none

00 -> none

01 -> CRC

10 ->

11 ->

默认00 01 00 01 (low 8 bit)

15

14

13

12

11

10

9

8

7

6

是否采用分包

分包总长(0标示未分包 其他他数据标示包总长)

子包ID

(总共分为9包)

协议类型ID

000 - 111

000 - 111

0000 -> 1111

1.2系统框架图

发送端主要完成数据组包,转义和发送,组包需要设置数据长度、数据是否加密、使用什么样的校验方式、发送的类型、是否需要分包、设置分包ID;
从缓存区读取数据并解析,拿到一包数据之后:
1.通过CRC校验判断数据是否有错,如果出错返回流水号(分包的话还要返回子包ID);
2.通过分析属性里的各个参数判断是否分包、数据类型、是否加密等属性然后解析出发送端数据;

1.3重点简介

接收端的处理:
1.在接收端设置一个缓存区,将从发送端的数据存放在缓存区内,接受的策略是当read函数返回的值为0时处理和当缓存区存满的时候处理,当缓存区满了的时候我们就从头开始继续写,覆盖原来的数据;
2.如何从读到的数据中分离出每包数据,通过我们设计的标示头和尾,当读到一个头这是头标记置为1,如果有连续的头,就舍弃前面的,当读到尾标识的时候,判断前面的头标记是否为1,若为1则说明找到了完整的一包数据,若果不为1直接舍弃。
数据分包处理:
1.发送端:当需要发送的数据大于协议拟定的长度的时候我们就需要进行分包操作,在属性里定义了分包总长和子包ID,方便我们在解析端进行接收和重组;
2.接收端:我们通过判断包总长确定接收的数据是否分包,因为分包的时候都是在数据满足协议数据最大长度的时候才进行分包,所以,在接收端的缓存我们可以通过子包ID来判断包的顺序和应该写入的位置,再出现丢包的时候,我们通过设置时间间隔判断是否丢包,每次接收到子包数据这时会获取系统的当前时间,当下次再接收到这个数据的时候进行判断,如果间隔大于一个阈值(自己设定)我们可以判定接受的数据出错,将原来的数据全部丢掉,重新接收。

2.CRC校验算法

关于错误校验常用三种就是奇偶校验、累加和校验和CRC校验;前两种校验方法相信大家有有所了解,所以这里重点介绍一下CRC算法;
CRC(循环冗余校验码):CRC 算法的基本思想是将传输的数据当做一个位数很长的数。将这个数除以另一个数。得到的余数作为校验数据附加到原数据后面。传输的时候将传输的数据和校验数据一块发送这个,在接收端我们利用接收到的数据利用“模二除法”除以利用的多项式,如果余数为0说明传输过程中没有差错,如果不为0表明传输过程中有错误。

step1:确认使用的多项式,通常我们会采用固定的多项式,常见的几种生成多项式如:

CRC8=X8+X5+X4+X0

CRC-CCITT=X16+X12+X5+X0

CRC16=X16+X15+X2+X0

CRC12=X12+X11+X3+X2+X0

CRC32=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+X0
生成多项式确定之后我们就可以进行算法编程:从前面的介绍我们知道CRC校验核心就是实现无借位的除法运算(即模二除法)。下面还是通过一个例子来说明如何实现CRC校验。

假设我们的生成多项式为:100110001(简记为0x31),也就是CRC-8

则计算步骤如下:

(1) 将CRC寄存器(8-bits,比生成多项式少1bit)赋初值0

(2) 在待传输信息流后面加入8个0

(3) While (数据未处理完)

(4) Begin

(5) If (CRC寄存器首位是1)

(6) reg = reg XOR 0x31

(7) CRC寄存器左移一位,读入一个新的数据于CRC寄存器的0 bit的位置。

(8) End

(9) CRC寄存器就是我们所要求的余数。

实际上,真正的CRC 计算通常与上面描述的还有些出入。这是因为这种最基本的CRC除法有个很明显的缺陷,就是数据流的开头添加一些0并不影响最后校验字的结果。这个问题很让人恼火啊,因此真正应用的CRC 算法基本都在原始的CRC算法的基础上做了些小的改动。

所谓的改动,也就是增加了两个概念,第一个是“余数初始值”,第二个是“结果异或值”。

所谓的“余数初始值”就是在计算CRC值的开始,给CRC寄存器一个初始值。“结果异或值”是在其余计算完成后将CRC寄存器的值在与这个值进行一下异或操作作为最后的校验值。

常见的三种CRC 标准用到个各个参数如下表。
CCITT
CRC16
CRC32
校验和位宽W
16
16
32
生成多项式
x16+x12+x5+1
x16+x15+x2+1
x32+x26+x23+x22+x16+

x12+x11+x10+x8+x7+x5+

x4+x2+x1+1
除数(多项式)
0x1021
0x8005
0x04C11DB7
余数初始值
0xFFFF
0x0000
0xFFFFFFFF
结果异或值
0x0000
0x0000
0xFFFFFFFF
加入这些变形后,常见的算法描述形式就成了这个样子了:

(1) 设置CRC寄存器,并给其赋值为“余数初始值”。

(2) 将数据的第一个8-bit字符与CRC寄存器进行异或,并把结果存入CRC寄存器。

(3) CRC寄存器向右移一位,MSB补零,移出并检查LSB。

(4) 如果LSB为0,重复第三步;若LSB为1,CRC寄存器与0x31相异或。

(5) 重复第3与第4步直到8次移位全部完成。此时一个8-bit数据处理完毕。

(6) 重复第2至第5步直到所有数据全部处理完成。

(7) 最终CRC寄存器的内容与“结果异或值”进行或非操作后即为CRC值。

(代码实现)

[cpp]
view plain
copy
print?

U16 crc16_check(U8 *data_ptr, U8 data_length)

{
/*polynomial*/

U16 crc_gen = 0xa001;
U16 crc;
U8 i, j;

/*init value of crc*/

crc = 0xffff;
if (data_length != 0)

{
for (i = 0; i < data_length; i++)

{
crc ^= (U16)(data_ptr[i]);
for (j = 0; j < 8; j++)

{
if ((crc & 0x01) == 0x01)

{
crc >>= 1;
crc ^= crc_gen;
}
else

{
crc >>= 1;
}
}/*end for*/

}/*end for*/
}/*end if*/

return crc;
}



U16 crc16_check(U8 *data_ptr, U8 data_length)
{
/*polynomial*/
U16 crc_gen = 0xa001;
U16 crc;
U8 i, j;

/*init value of crc*/
crc = 0xffff;
if (data_length != 0)
{
for (i = 0; i < data_length; i++)
{
crc ^= (U16)(data_ptr[i]);
for (j = 0; j < 8; j++)
{
if ((crc & 0x01)  == 0x01)
{
crc >>= 1;
crc ^= crc_gen;
}
else
{
crc >>= 1;
}
}/*end for*/
}/*end for*/
}/*end if*/
return crc;
}

3.Linux多线程编程;

在任务实现的时候,我们通过多线程实现数据的接受和任务的执行,线程之间通过消息队列来进行通信;在接收端我们创建一个线程用于接收数据和预处理,这里的预处理主要是从接收得到的数据中解析出整包的数据并完成校验,确定得到一包正确的数据,然后将这个数据放在消息队列里;这个时候我们的接受线程就可以不断的接受和往消息队列里发送数据,在任务执行段再创建一个线程,用于任务处理,这里面主要实现的是从消息队列里面读取数据并解析。在消息队列创建的时候出现了一个消息队列ID为0的现象,不知道是什么原因。

这个实现的源代码如下:

[cpp]
view plain
copy
print?

/*************************************************************************

> Copyright (C), 2014,
> File Name: scom_protocal.h

> Author: xhniu
> Mail:
> Created Time: Fri 22 Aug 2014 04:45:03 PM CST

> Description: define the scom protocal,realize the data send/recv

escape_character/anti_escape_character data_process

multi thread program and inter thread communication with

message queue;

> Version: V0.1
> Function List:
1.U8 serialport_init(INT8 port_fd, U32 baud_rate,

2.U8 data_bits, U8 parity, U8 stop_bit);

3.void scom_protocal_init(scom_protocal *protocal_info_ptr);

4.INT8 open_port(void);
5.U16 crc16_check(U8 *data_ptr, U8 data_length);

6.U8 escape_character(U8 *package_data_ptr, U8 data_length,

U8 *buffer_ptr);

7.U8 anti_escape_character(U8 *buffer_ptr, U8 *package_data_ptr,

U8 data_length);

8.void *tsk_run(INT8 *param_ptr);

9.U8 data_process(U8 *data_proc_ptr, U8 data_start_pos,

U8 data_end_pos);
10.U8 data_package(scom_protocal *protocal_info_ptr,

U8 *package_data_ptr, U8 data_length);

11.U8 data_send(INT8 port_fd, scom_protocal *protocal_info_ptr,

U8 *data_send_ptr, U8 data_send_length);

12.void *data_recv(recv_param *data_recv_info_ptr);

13.U8 close_port(INT8 port_fd);

> History: <author> <date> <version> <desc>

xhniu 14.09.12 V0.1 Completion of

multi-threaded programming

xhniu 14.09.14 V0.1 add the msg_que

xhniu 16.09.14 V0.1 add the tsk delete function

and free the system resource

xhniu 18.09.14 V0.1

> Others: naming rules is UNIX

m_ member variable g_ globe variable

************************************************************************/

#include<stdlib.h>

#include<math.h>
#include<stdio.h>

#include<fcntl.h> /*File control*/

#include<unistd.h> /**/

#include<errno.h>
#include<string.h>

#include<termio.h> /*provide the common interface*/

#include<sys/types.h>

#include<sys/stat.h>
#include<pthread.h>

#include<sys/ipc.h>
#include<sys/msg.h>

/* To prevent repeated variables defined */

#ifndef _SCOM_PROTOCAL_H_

#define _SCOM_PROTOCAL_H_

typedef unsigned char U8;

typedef unsigned
short U16;
typedef unsigned long U32;

typedef signed
char INT8;
typedef unsigned int UINT16;

typedef signed
int INT16;

/*
* define the macro to set the
* init_value of the property

*/
#define PROPERTY_INIT 0x11

#define PROPERTY_0x01 0x51

#define PROPERTY_0x02 0x91

#define PROPERTY_0x03 0xd1

#define PROPERTY_0x04 0x111

#define PROPERTY_0x05 0x151

#define PROPERTY_OTHER 0x155

#ifndef NULL

#define NULL ((void*) 0)

#endif

#define DEBUG 1

#ifdef DEBUG

#else
#endif

#define HEAD 0xf4

#define TAIL 0x4f

#define FALSE -1
#define TRUE 0

/*define the device port*/
#if 1
#define DEV_PORT "/dev/pts/4"

#else
#define DEV_PORT "/dev/ttyAMA2"

#endif
/*define the flag to cancel the thread*/

U8 g_exit_flag = 0;

#define DATA_LENGTH_MAX 8

#define PROTOCAL_LENGTH 9

#define BUFFER_SIZE 72

#define BAUDRATE 115200

/* */
#endif

#define MSG_QUE_KEY 1024

/*define the struct of the mes_que*/

#define MSG_TYPE 17

typedef struct

{
INT8 msg_type;
U8 msg_len;
/*exclude the head and tail*/

U8 msg_buf[DATA_LENGTH_MAX + PROTOCAL_LENGTH - 2];

}msg_que;

typedef struct

{
INT8 port_fd;
U8 buf[BUFFER_SIZE];
}recv_param;
#if 0
typedef struct

{
U8 package_data_length;
/*exclude the head and tail*/

U8 buf[DATA_LENGTH_MAX + PROTOCAL_LENGTH - 2];
}tsk_param;
#endif

/*self define the protocal of the serial com*/

typedef struct

{
U8 head[1];
U16 serial_num;
U8 length[1]; /*data_length + PROTOCAL_LENGTH*/

U16 property;
U8 package_data[DATA_LENGTH_MAX];
U16 crc_check;
U8 tail[1];
}scom_protocal;

/*function declaration*/
U8 serialport_init(INT8 port_fd, U32 baud_rate,
U8 data_bits, U8 parity, U8 stop_bit);
void scom_protocal_init(scom_protocal *protocal_info_ptr);

INT8 open_port(void);
U16 crc16_check(U8 *data_ptr, U8 data_length);
U8 escape_character(U8 *package_data_ptr, U8 data_length,
U8 *buffer_ptr);
U8 anti_escape_character(U8 *buffer_ptr, U8 *package_data_ptr,

U8 data_length);
void *tsk_run(INT8 *param_ptr);

U8 data_process(U8 *data_proc_ptr, U8 data_start_pos,

U8 data_end_pos);
U8 data_package(scom_protocal *protocal_info_ptr,
U8 *package_data_ptr, U8 data_length);
U8 data_send(INT8 port_fd, scom_protocal *protocal_info_ptr,

U8 *data_send_ptr, U8 data_send_length);
void *data_recv(recv_param *data_recv_info_ptr);

U8 close_port(INT8 port_fd);
/*************************************************

* Function: void serialport_init()

* Description: init the serialport

* Calls: none
* Called By: main
* Input: port_fd baud_rate data_bits parity stop_bit

* Output: print the error info

* Return: none
* Author: xhniu
* History: <author> <date> <desc>

*
* Others: none
*************************************************/

U8 serialport_init(INT8 port_fd, U32 baud_rate,
U8 data_bits, U8 parity, U8 stop_bit)
{
struct termios newtio, oldtio;

/*save the primary params of the serial port stop_bit*/

if (tcgetattr(port_fd, &oldtio )!= 0)

{
perror("setup serial failed!!!\n");

return -1;

}

bzero(&newtio, sizeof(newtio));

/*set the data_bits stop_bit parity*/

newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;

switch (data_bits)

{
case 7:

newtio.c_cflag |= CS7;
break;

case 8:
newtio.c_cflag |= CS8;
break;
default:

break;
}

switch (parity)

{
case 'O':/*odd number*/

newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;

case 'E':/*even number*/

newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'N':

newtio.c_cflag &= ~PARENB;
break;

default:
break;

}

switch (baud_rate)
{
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;

case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;

default:
break;

}

if (1 == stop_bit)
{
newtio.c_cflag &= ~CSTOPB;
}
else if (2 == stop_bit)

{
newtio.c_cflag |= CSTOPB;
}

/*active the newtio*/

if ((tcsetattr(port_fd, TCSANOW, &newtio)) != 0)

{
perror("serial port set error!!!\n");

return -1;

}

printf("serial port set done!!!\n");

return 0;
}
/*************************************************

* Function: scom_protocal_init()
* Description: init the params of the protocal

* Calls: none
* Called By: none
* Input: the struct of the scom_protocal

* Output: none
* Return: none
* Author: xhniu
* History: <author> <date> <desc>

* Others: none
*************************************************/

void scom_protocal_init(scom_protocal *protocal_info_ptr)

{
protocal_info_ptr->head[0] = HEAD;
protocal_info_ptr->serial_num = 0x0000;
/*init length is data_length + PROTOCAL_LENGTH*/

protocal_info_ptr->length[0] = 0x11;
protocal_info_ptr->property = PROPERTY_INIT;

memset(protocal_info_ptr->package_data, 0,
sizeof(U8) * 8);

protocal_info_ptr->crc_check = 0x0000;
protocal_info_ptr->tail[0] = 0x4f;
}
/*************************************************

* Function: open_port()

* Description: open the DEV_PORT
* Calls: none
* Called By: none
* Input: none
* Output: none
* Return: port_fd
* Author: xhniu
* History: <author> <date> <desc>

* Others: none
*************************************************/

INT8 open_port(void)
{
INT8 port_fd;

/* */
port_fd = open(DEV_PORT,
O_RDWR | O_NOCTTY | O_NONBLOCK);
if (-1 == port_fd)

{
perror("open the serial port failed!!!\n");

return -1;
}

/*set the serial port is block and waitting*/

if (fcntl(port_fd, F_SETFL, 0) < 0)

{
printf("fcntl failed!\n");

}
else
{
printf("fcntl = %d \n", fcntl(port_fd, F_SETFL, 0));

}/*end if*/

return port_fd;

}

/*************************************************

* Function: crc16_check()

* Description: genetrate the check data

* Calls: none
* Called By: data_package()
* Input: data need check and length of data

* Output: none
* Return: crc check data

* Author: xhniu
* History: <author> <date> <desc>

* Others: none
*************************************************/

U16 crc16_check(U8 *data_ptr, U8 data_length)
{
/*polynomial*/
U16 crc_gen = 0xa001;
U16 crc;
U8 i, j;

/*init value of crc*/

crc = 0xffff;
if (data_length != 0)

{
for (i = 0; i < data_length; i++)

{
crc ^= (U16)(data_ptr[i]);
for (j = 0; j < 8; j++)

{
if ((crc & 0x01) == 0x01)

{
crc >>= 1;
crc ^= crc_gen;
}
else

{
crc >>= 1;
}
}/*end for*/

}/*end for*/
}/*end if*/

return crc;
}

/*************************************************

* Function: escape_character()
* Description: f4 -- ff 01, ff -- ff 02, 4f -- ff 03

* Calls: none
* Called By: data_send

* Input: package_data, data_length, buffer

* Output: none
* Return: TRUE or FALSE
* Author: xhniu
* History: <author> <date> <desc>

* Others: none
*************************************************/

U8 escape_character(U8 *package_data_ptr, U8 data_length, U8 *buffer)

{
if ((NULL == package_data_ptr) | (0 == data_length))

{
printf("input error!!!\n");

return FALSE;
}

U8 count = 1;

buffer[0] = package_data_ptr[0];
buffer++;
/*except the head and the tail*/

for (; count < (data_length -1); count++)

{
if (0xf4 == package_data_ptr[count])

{
*buffer++ = 0xff;
*buffer++ = 0x01;
}
else if (0xff == package_data_ptr[count])

{
*buffer++ = 0xff;
*buffer++ = 0x02;
}
else if (0x4f == package_data_ptr[count])

{
*buffer++ = 0xff;
*buffer++ = 0x03;
}
else
{
*buffer++ = package_data_ptr[count];
}/*end if*/
}/*end for*/

*buffer++ = 0x4f;
*buffer = '\0';

return TRUE;

}
/*************************************************

* Function: anti_escape_character()

* Description: ff 01 -- f4, ff 02 -- ff, ff 03 -- 4f

* Calls: none
* Called By:
* Input: buffer, package_data, data_length

* Output:
* Return:
* Author: xhniu
* History: <author> <date> <desc>

* Others: none
*************************************************/

U8 anti_escape_character(U8 *buffer_ptr, U8 *package_data_ptr,

U8 data_length)
{
if ((NULL == package_data_ptr) | (0 == data_length))

{
printf("input data error!\n");

return FALSE;

}

U8 flag = 0;
U8 count = 0;

package_data_ptr[0] = buffer_ptr[0];
package_data_ptr++;
buffer_ptr++;
/*exclude the tail 0x4f*/

while (TAIL != *buffer_ptr)

{
if (0xff == *buffer_ptr)

{
flag = 1;
buffer_ptr++;

if ((0x01 == *buffer_ptr) && (1 == flag))

{
*package_data_ptr++ = 0xf4;
}
else if ((0x02 == *buffer_ptr) && (1 == flag))

{
*package_data_ptr++ = 0xff;
}
else if ((0x03 == *buffer_ptr) && (1 == flag))

{
*package_data_ptr++ = 0x4f;
}
else if (1 == flag)

{
*package_data_ptr++ = 0xff;
*package_data_ptr++ = *buffer_ptr++;

}
buffer_ptr++;
}
else
{
*package_data_ptr++ = *buffer_ptr++;
flag = 0;
}/*end if*/

}/*end while*/

return TRUE;

}

/*************************************************

* Function: tsk_run()
* Description: receive a package data and execute a tsk

* Calls: none
* Called By: data_recv()
* Input: data_proc_ptr

* Output: none
* Return:
* Author: xhniu
* History: <author> <date> <desc>

* Others: none
************************************************/

void *tsk_run(INT8 *param_ptr)

{
INT8 port_fd = *param_ptr;
U8 *exit_ptr = "exit";

#if DEBUG
printf("in tsk_run,port_fd is %4d\n", port_fd);

#endif
/*use to data send*/

scom_protocal scom_protocal_info;
memset(&scom_protocal_info, 0, sizeof(scom_protocal_info));

scom_protocal_init(&scom_protocal_info);
U8 data_send_length = 0;
U8 data_send_array[32] = {0};
U8 num = 0;
/*use to data proc*/
U8 package_data_ptr[DATA_LENGTH_MAX + PROTOCAL_LENGTH - 2] = {0};

U8 data_ptr[DATA_LENGTH_MAX] = {0};
U8 package_data_length = 0;
/*define the var to recv msg form msg_que*/

INT16 msg_que_id;
INT8 ret;
msg_que msg_que_info;
memset(&msg_que_info, 0, sizeof(msg_que_info));

/*proc the sub package*/

U8 sub_package_num = 0;
U8 sub_package_flag = 0;
U8 sub_package_ID = 0;
U8 sub_package_count = 0;
U8 sub_package_buf[DATA_LENGTH_MAX * 8] = {0};
INT16 cur_time = 0;
INT16 last_time = 0;

while (1)
{
/*judge the exit flag*/

if(1 == g_exit_flag)

{
printf("int tsk_run,g_exit_flag is:%4d\n", g_exit_flag);

break;
}

/*check the msg que is exist*/

msg_que_id = msgget(MSG_QUE_KEY, IPC_EXCL);
if (msg_que_id <= 0)

{
printf("msg que is not exist!\n");

sleep(1);
continue;

}
else
{
printf("\nin tsk_run,msg_que_id is %4d\n", msg_que_id);

}
/*start to recv data from the msg que*/

ret = msgrcv(msg_que_id, &msg_que_info, sizeof(msg_que_info), 0, 0);

if (ret < 0)

{
printf("recv data from the msg que failed!\n");

continue;
}
else
{
printf("recv data from the msg que success!\n");

}/*end if*/

/*get the cur time*/

if (0 != last_time)

{
printf("*****last_time is %4d*****\n", last_time);

cur_time = time((time_t*)NULL);

printf("cur_time is :%4d\n", cur_time);

if (cur_time - last_time > 10)

{
printf("cannot get the complete package_data!!!\n");

memset(sub_package_buf, 0, DATA_LENGTH_MAX * 8);

sub_package_count = 0;
last_time = 0;
continue;

}
}/*end if*/

package_data_length = msg_que_info.msg_len;

memcpy(package_data_ptr, msg_que_info.msg_buf, msg_que_info.msg_len);

#if DEBUG
printf("package_data_length is %4d\n", package_data_length);

U8 i = 0;
while (i < package_data_length)

{
printf("%02x ", package_data_ptr[i++]);

}
printf("\n");
#endif
U16 property = 0;
property = package_data_ptr[4];
property = property << 8;
property = (property | package_data_ptr[3]);

#if DEBUG
printf("property is:%04x\n", property);

#endif
/*judging whethre the data sub*/

sub_package_num = (property >> 13);
sub_package_ID = (property >> 10);
sub_package_ID &= 0x07;
printf("the sub_package_ID is %4d\n", sub_package_ID);

if (0 != sub_package_num)

{
sub_package_flag = 1;
sub_package_count++;
memcpy(&sub_package_buf[ sub_package_ID * DATA_LENGTH_MAX],

&package_data_ptr[5],package_data_ptr[2] - PROTOCAL_LENGTH);

printf("sub_package_count is %4d subpackage_num is %4d\n", sub_package_count, sub_package_num);

/*recv the complete package*/

if(sub_package_count == (sub_package_num + 1))

{
#if DEBUG
U8 i = 0;
for (; i < 28; i++)

{
printf("%c",sub_package_buf[i]);

}
printf("\n");

#endif
system(sub_package_buf);
memset(sub_package_buf, 0, DATA_LENGTH_MAX * 8);

sub_package_count = 0;
last_time = 0;
continue;

}
else

{
last_time = time((time_t*)NULL);

printf("last_time is:%4d\n",last_time);

}/*end if*/

continue;
}/*end if*/

memcpy(data_ptr, &package_data_ptr[5], package_data_ptr[2] - PROTOCAL_LENGTH);

property &= 0x3ff;
switch (property)

{
case PROPERTY_INIT:

{
printf("The receive cmd is linux system cmd:%s\n", data_ptr);

if (0 == strcmp(exit_ptr, data_ptr))

{
g_exit_flag = 1;
}
else

{
system(data_ptr);
}
break;

}
case PROPERTY_0x01:

{
#if DEBUG
printf("The receive cmd is get the GPS data:\n");

#endif

printf("GPS:longitude :%04x, latitude :%04x, height :%04x, time :%04x\n",

0xf101,0xf202, 0xf123, 0xffff);

num = 0;
data_send_array[num++] = 0x01;
data_send_array[num++] = 0xf1;

data_send_array[num++] = 0x02;
data_send_array[num++] = 0xf2;

data_send_array[num++] = 0x23;
data_send_array[num++] = 0xf1;

data_send_array[num++] = 0xff;
data_send_array[num++] = 0xff;

scom_protocal_info.property = PROPERTY_0x01;

data_send(port_fd, &scom_protocal_info, data_send_array, 8);

break;

}
case PROPERTY_0x02:

{
printf("The receive cmd is get the gyroscope data:\n");

printf("gyroscope:\ncabrage:%04x, yaw:%04x, roll;%04x\n",

0xf1f2, 0xf3f4, 0xf5f6);
num = 0;
data_send_array[num++] = 0xf2;
data_send_array[num++] = 0xf1;

data_send_array[num++] = 0xf4;
data_send_array[num++] = 0xf3;

data_send_array[num++] = 0xf6;
data_send_array[num++] = 0xf5;

scom_protocal_info.property = PROPERTY_0x02;

data_send(port_fd, &scom_protocal_info, data_send_array, num);

break;

}
case PROPERTY_0x03:

{
printf("The receive cm d is get the accelerometer data:\n");

printf("accelerometer:\nX:%04x, Y:%04x, Z:%04x\n",

0x0102, 0x0304, 0x0506);

num = 0;
data_send_array[num++] = 0x02;

data_send_array[num++] = 0x01;
data_send_array[num++] = 0x04;

data_send_array[num++] = 0x03;
data_send_array[num++] = 0x06;

data_send_array[num++] = 0x05;

scom_protocal_info.property = PROPERTY_0x03;

data_send(port_fd, &scom_protocal_info, data_send_array, num);

break;

}
case PROPERTY_0x04:

{
printf("The receive cmd is get th e target info:\n");

num = 0;
data_send_array[num++] = 0x01;

data_send_array[num++] = 0x34;
data_send_array[num++] = 0x12;

data_send_array[num++] = 0x21;
data_send_array[num++] = 0x43;

data_send_array[num++] = 0x02;
data_send_array[num++] = 0x78;

data_send_array[num++] = 0x56;
data_send_array[num++] = 0x65;

data_send_array[num++] = 0x87;
data_send_array[num++] = 0x03;

data_send_array[num++] = 0x14;
data_send_array[num++] = 0x23;

data_send_array[num++] = 0x21;
data_send_array[num++] = 0x34;

scom_protocal_info.property = PROPERTY_0x04;

data_send(port_fd, &scom_protocal_info, data_send_array, num);

break;

}
case PROPERTY_0x05:

{
printf("the cmd is get the D5 info:\n");

num = 0;
data_send_array[num++] = 0x01;
data_send_array[num++] = 0x34;

data_send_array[num++] = 0x12;
data_send_array[num++] = 0x21;

data_send_array[num++] = 0x43;
data_send_array[num++] = 0x02;

data_send_array[num++] = 0x78;
data_send_array[num++] = 0x56;

data_send_array[num++] = 0x65;
data_send_array[num++] = 0x87;

data_send_array[num++] = 0x03;
data_send_array[num++] = 0x14;

data_send_array[num++] = 0x23;
data_send_array[num++] = 0x21;

break;

}
default:
{
printf("cannot discrimate the cmd:\n");

U8 i = 0;
for (; i < package_data_ptr[2] - PROTOCAL_LENGTH; i++)

{
printf("%02x ", data_ptr[i]);

}
printf("\n");

break;

}
}/*end switch*/
}/*end ehile*/

}

/*************************************************

* Function: data_process()

* Description: process the data form the bufer_recv

* Calls: none
* Called By: data_recv()
* Input: data_proc_ptr

* Output: none
* Return:
* Author: xhniu
* History: <author> <date> <desc>

* Others: none
************************************************/

U8 data_process(U8 *data_proc_ptr,
U8 data_start_pos,
U8 data_end_pos)
{
if ((NULL == data_proc_ptr) || (data_start_pos >= data_end_pos))

{
printf("input data error!\n");

return 0;

}

/*use msg_que to do the ipc*/

msg_que msg_que_info;
INT8 ret = 0;
INT16 msg_que_id;
memset(&msg_que_info, 0, sizeof(msg_que_info));

msg_que_id = msgget((key_t)MSG_QUE_KEY, IPC_EXCL);

#if DEBUG
printf("the msg_que_id is:%4d\n", msg_que_id);

#endif

/*process data buffer*/

U8 buffer[(DATA_LENGTH_MAX + PROTOCAL_LENGTH) * 2 - 2] = {0};

U8 package_data[(DATA_LENGTH_MAX + PROTOCAL_LENGTH) * 2] = {0};

/* */
U8 head_flag = 0;
U8 tail_flag = 0;
U8 pos = 0;
U8 package_data_length = 0;

for (; data_start_pos < data_end_pos; data_start_pos++)

{
/*find the head */
if ((HEAD == data_proc_ptr[data_start_pos])

&& (0 == head_flag))
{
head_flag = 1;
pos = data_start_pos;
continue;
}
/*avoid the double head or triple head*/

if ((HEAD == data_proc_ptr[data_start_pos])

&& (1 == head_flag))
{
pos = data_start_pos;
}

if ((TAIL == data_proc_ptr[data_start_pos])

&& (0 == tail_flag))
{
if(1 == head_flag)

{
tail_flag = 1;
}
else
{
tail_flag = 0;
}
}

/*process a packaged data*/

if ((1 == head_flag) && (1 == tail_flag))

{
printf("data_start_pos is %2d, pos is %2d ", data_start_pos, pos);

memset(buffer, 0x00, (DATA_LENGTH_MAX + PROTOCAL_LENGTH) * 2 - 2);

memcpy(buffer, &data_proc_ptr[pos],
(data_start_pos - pos + 1));

/*anti escape character*/

printf("\nanti escape character! data_start_pos is %4d pos is %4d\n",

data_start_pos, pos);
memset(package_data, 0x00,
(DATA_LENGTH_MAX + PROTOCAL_LENGTH) * 2);
anti_escape_character(buffer, package_data,

(data_start_pos - pos + 1));

/*data length exclude head and tail*/

#if DEBUG
printf("data length is: package[3] = %2d\n", package_data[3] - 2);

#endif
package_data_length = package_data[3] - 2;
printf("crc16_check is 0x%04x\n",

crc16_check(&package_data[1], package_data_length));

if (0x00 == crc16_check(&package_data[1], package_data_length))

{
printf("crc16_check success!\n");

}
else

{
printf("crc16_ check error!\n");

/*
* theoretically,it will return the serial_num

* and the sub_package_ID

*/

return 0;
}
/*get a complete package data and send it to the msg_que*/

msg_que_info.msg_type = MSG_TYPE;
msg_que_info.msg_len = package_data_length;
#if DEBUG
printf("msg_que_info.msg_len is %4d\n",

msg_que_info.msg_len);
#endif
memcpy(&(msg_que_info.msg_buf), &package_data[1],

package_data_length);
/*send the msg*/

ret = msgsnd(msg_que_id, &msg_que_info, package_data_length, IPC_NOWAIT);

if (ret < 0)

{
printf("msg send failed!\n");

return 0;
}
else
{
printf("send msg success! ret is %4d\n", ret);

sleep(2);
}

head_flag = 0;
tail_flag = 0;
pos = 0;
}
}
#if 0
printf("\nreturn data is: %4d\n", pos);

#endif
return pos;
}
/*************************************************

* Function: data_package()

* Description: package the data with the scom_protocal

* Calls:
* Called By: data_send
* Input: protocal_info_ptr, package_data, data_length

* Output:
* Return: TRUE/FALSE
* Author: xhniu
* History: <author> <date> <desc>

* Others: none
*************************************************/

U8 data_package(scom_protocal *protocal_info_ptr,
U8 *package_data_ptr, U8 data_length)
{
/*decide whether need subpackage*/

if (data_length > DATA_LENGTH_MAX)

{
printf("input valid!!!\n");

return -1;

}

U8 len = 0;

package_data_ptr[0] = protocal_info_ptr->head[0];
/*U16 to U8 low 8 bit*/

package_data_ptr[1] = (U8)(protocal_info_ptr->serial_num);

package_data_ptr[2] = (U8)((protocal_info_ptr->serial_num)

>> 8);

package_data_ptr[3] = data_length + PROTOCAL_LENGTH;

/*U16 to U8 low 8 bit*/

package_data_ptr[4] = (U8)(protocal_info_ptr->property);

/*high 8 bit*/
package_data_ptr[5] = (U8)((protocal_info_ptr->property)

>> 8);

for (; len < data_length; len++)

{
package_data_ptr[len + 6] =
protocal_info_ptr->package_data[len];
}
/*
*generate the CRC16 check data

* U16 to U8
*/
U16 check_code;
/*data_length + property(2 byte) + length(1 byte) +

* serial_num(2 byte)

*/
U8 *ptr = malloc(sizeof(U8) * (data_length + 5));

memcpy(ptr, package_data_ptr + 1, data_length + 5);
check_code = crc16_check(ptr, data_length + 5);

/*free the ptr*/
free(ptr);
ptr = NULL;

/*low 8 bit*/
package_data_ptr[len + 6] = (U8)(check_code);
/*high 8 bie*/
package_data_ptr[len + 7] = (U8)(check_code >> 8);

package_data_ptr[len + 8] = protocal_info_ptr->tail[0];

return TRUE;
}
/*************************************************

* Function: data_send()

* Description: read the data and
* Calls: none
* Called By: none
* Input: none
* Output: none
* Return:
* Author: xhniu
* History: <author> <date> <desc>

* Others: none
*************************************************/

U8 data_send(INT8 port_fd, scom_protocal *protocal_info_ptr,
U8 *data_send_ptr, U8 data_send_length)
{
if (NULL == data_send_ptr)

{
printf("input data error!!!\n");

return FALSE;
}

/*number of the char need escape*/

U8 num_escape_char = 0;
U8 num_escape_char_temp = 0;

U8 *package_data = NULL;
U8 *escape_char_ptr = NULL;

/*when send new data, the serial num will plus 1*/

(protocal_info_ptr->serial_num)++;

if (data_send_length > DATA_LENGTH_MAX)

{
/*need the subpackage calculate the sun_package_num

* set the flag of the subpackage*/

int sub_package_num = 0, count = 0;

if (0 != data_send_length % DATA_LENGTH_MAX)

{
sub_package_num = (data_send_length / DATA_LENGTH_MAX) + 1;

}
else
{
sub_package_num = (data_send_length / DATA_LENGTH_MAX);

}

/*3 byte of the sub_package_num the data area is

*1 ~ 7
*/
if (sub_package_num > 8)

{
return FALSE;
}
protocal_info_ptr->property &= 0x1fff;
protocal_info_ptr->property |= ((sub_package_num - 1) << 13);

#if DEBUG
printf("sub_package_num is:%4x\n",sub_package_num);

#endif
/*
* sub_package_num - 1
* the length of the last sub_package is not sure

*/
for (; count < (sub_package_num - 1); count++)

{
/*set the length of the protcal_info_ptr->length[0]*/

protocal_info_ptr->length[0] =
DATA_LENGTH_MAX + PROTOCAL_LENGTH;

/*set the ID of the subpackage*/

protocal_info_ptr->property &= 0xe3ff;

protocal_info_ptr->property |= (count << 10);

memcpy(protocal_info_ptr->package_data,
(data_send_ptr + count * DATA_LENGTH_MAX ),

DATA_LENGTH_MAX);
#if 0
U8 m = 0;
for (; m < protocal_info_ptr->length[0]; m++)

{
printf("%02x ", protocal_info_ptr->package_data[m]);

}
printf("\n");

#endif
/*malloc a mem to restore the packaged data

*plus the head(1),tail(1),length(1),property(2),crc(2),serial_num(2),

*/

package_data = (U8 *)malloc(sizeof(U8) *

(DATA_LENGTH_MAX + PROTOCAL_LENGTH));

if (NULL == package_data)

{
printf("malloc failed\n");

return FALSE;

}

data_package(protocal_info_ptr, package_data,
DATA_LENGTH_MAX);
#if DEBUG
U8 m = 0;
for (; m < 17; m++)

{
printf("%02x ", package_data[m]);

}
printf("\n");
#endif
/* malloc a buffer use to send data

* character transfer

*/
num_escape_char = 0;
num_escape_char_temp = 0;
/*count the num of the 0xff 0xf4 0x4f except tail and head*/

num_escape_char_temp = protocal_info_ptr->length[0] - 2;

while ((num_escape_char_temp--) > 1)

{
if ((0xff == package_data[num_escape_char_temp])

| (0xf4 == package_data[num_escape_char_temp])

| (0x4f == package_data[num_escape_char_temp]))

{
num_escape_char++;
}
}
#if DEBUG
printf("num_escape_char is %4d\n", num_escape_char);

#endif
if(0 == num_escape_char)

{
/*no escape characters send data diretly*/

if (write(port_fd, package_data,

(protocal_info_ptr->length[0])) < 0)
{
printf("write data error! \n");

return FALSE;

}
else

{
printf("write data success!\n");

}
}
else
{
escape_char_ptr = (U8 *)malloc(sizeof(U8)

* (protocal_info_ptr->length[0] + num_escape_char));

#if DEBUG
printf("%4d \n", protocal_info_ptr->length[0]);

#endif
escape_character(package_data,
protocal_info_ptr->length[0], escape_char_ptr);

#if DEBUG
U8 k = 0;
for (; k < protocal_info_ptr->length[0]

+ num_escape_char; k++)
{
printf("%04x ", escape_char_ptr[k]);

}
#endif
/*send data*/

if (write(port_fd, escape_char_ptr,

(protocal_info_ptr->length[0] + num_escape_char)) < 0)

{
printf("write data error! \n");

return FALSE;

}
else
{
printf("write data success!\n");

}

/*free the memory*/

free(escape_char_ptr);
escape_char_ptr = NULL;
}

free(package_data);
package_data = NULL;

}/*end for*/

if (data_send_length - count * DATA_LENGTH_MAX > 0)

{
protocal_info_ptr->length[0] = data_send_length
- count * DATA_LENGTH_MAX + PROTOCAL_LENGTH;

protocal_info_ptr->property &= 0xe3ff;

protocal_info_ptr->property |= (count << 10);
memcpy(protocal_info_ptr->package_data,

(data_send_ptr + count * DATA_LENGTH_MAX),

(data_send_length - count * DATA_LENGTH_MAX));

/*malloc a mem to restore the packaged data*/

package_data = (U8 *)malloc(sizeof(U8) * (data_send_length

- count * DATA_LENGTH_MAX + PROTOCAL_LENGTH));

if (NULL == package_data)

{
printf("malloc failed \n");

}
#if DEBUG
printf("the rest data length is %4d\n",

data_send_length - count * DATA_LENGTH_MAX );

#endif

data_package(protocal_info_ptr, package_data,
data_send_length - count * DATA_LENGTH_MAX);

#if DEBUG
U8 n = 0;
for (; n < protocal_info_ptr->length[0]; n++)

{
printf("%02x ", package_data
);

}
printf("\n");
#endif
/* malloc a buffer use to send data

* character transfer

*/
num_escape_char = 0;
num_escape_char_temp = 0;
/*count the num of the 0xff 0xf4 0x4f except tail and head*/

num_escape_char_temp = protocal_info_ptr->length[0] - 2;

while ((num_escape_char_temp--) > 1)

{
if ((0xff == package_data[num_escape_char_temp])

| (0xf4 == package_data[num_escape_char_temp])

| (0x4f == package_data[num_escape_char_temp]))

{
num_escape_char++;
}
}
#if DEBUG
printf("num_escape_char is %4d\n", num_escape_char);

#endif
if(0 == num_escape_char)

{
/*no escape characters send data diretly*/

if (write(port_fd, package_data,

(protocal_info_ptr->length[0])) < 0)
{
printf("write data error! \n");

return FALSE;

}
else

{
printf("write data success!\n");

}
}
else
{
escape_char_ptr = (U8 *)malloc(sizeof(U8)

* (protocal_info_ptr->length[0] + num_escape_char));

#if DEBUG
printf("%4d \n", protocal_info_ptr->length[0]);

#endif
escape_character(package_data,
protocal_info_ptr->length[0], escape_char_ptr);

#if DEBUG
U8 k = 0;
for (; k < protocal_info_ptr->length[0]

+ num_escape_char; k++)
{
printf("%04x ", escape_char_ptr[k]);

}
#endif
/*send data*/

#if 1
if (write(port_fd, escape_char_ptr,

(protocal_info_ptr->length[0] + num_escape_char)) < 0)

{
printf("write data error!\n");

return FALSE;

}
#endif
free(escape_char_ptr);
escape_char_ptr = NULL;
/*send data*/

}

/*free the memory*/

free(package_data);
package_data = NULL;

return TRUE;

/**/
}
else/* data_send_length - count * DATA_LENGTH_MAX = 0 */

{
return TRUE;
}/*end if*/

}
else /*data_send_length <= DATA_LENGTH_MAX no subpackage*/

{
/*set the length of tht protocal_info_ptr->length[0]*/

protocal_info_ptr->length[0] = data_send_length + PROTOCAL_LENGTH;

memcpy(protocal_info_ptr->package_data, data_send_ptr, data_send_length);

/*malloc a mem to restore the packaged data*/

package_data = (U8 *)malloc(sizeof(U8)

* (data_send_length + PROTOCAL_LENGTH));

#if DEBUG
printf("data_send_length is %4d\n", data_send_length);

#endif
if (NULL == package_data)

{
printf("malloc failed!!!\n");

return FALSE;
}
#if DEBUG
printf("data_send_length + PROTOCAL_LENGTH is %4d \n",

data_send_length + PROTOCAL_LENGTH);
#endif
data_package(protocal_info_ptr, package_data, data_send_length);

#if DEBUG
printf("protocal_info_ptr_length[0] is %4d \n", protocal_info_ptr->length[0]);

U8 j = 0;
for (; j < data_send_length + PROTOCAL_LENGTH; j++)

{
printf("%02x ", package_data[j]);

}
printf("\n");

#endif
/* malloc a buffer use to send data

* character transfer
*/
U8 num_escape_char = 0;
U8 num_escape_char_temp = 0;
/*count the num of the 0xff 0xf4 0x4f except tail and head*/

num_escape_char_temp = protocal_info_ptr->length[0] - 2;

#if 0
printf("%4d\n", num_escape_char_temp);

#endif
while ((num_escape_char_temp--) > 1)

{
if ((0xff == package_data[num_escape_char_temp])

| (0xf4 == package_data[num_escape_char_temp])

| (0x4f == package_data[num_escape_char_temp]))

{
num_escape_char++;
}/*end if*/
}/*end while*/

#if DEBUG
printf("num_escape_char is %4d\n", num_escape_char);

#endif
if(0 == num_escape_char)

{
/*no escape characters send data diretly*/

if (write(port_fd, package_data,

protocal_info_ptr->length[0]) < 0)

{
printf("write data error!!!\n");

return FALSE;

}
else
{
printf("write to port_fd data success!\n");

}

/*free the malloc*/

free(package_data);
package_data = NULL;
}/*end if*/
else
{
escape_char_ptr = (U8 *)malloc(sizeof(U8)

* (protocal_info_ptr->length[0] + num_escape_char));

#if DEBUG
printf("%4d \n", protocal_info_ptr->length[0]);

#endif
escape_character(package_data,
protocal_info_ptr->length[0], escape_char_ptr);

#if DEBUG
U8 k = 0;
for (; k < protocal_info_ptr->length[0]

+ num_escape_char; k++)
{
printf("%04x ", escape_char_ptr[k]);

}
printf("\nport_fd is %4d\n", port_fd);

#endif
/*send data*/

INT8 res = 0;
#if 1

printf("writing data......\n");

/*escape_char_ptr */

res = write(port_fd, escape_char_ptr,
(protocal_info_ptr->length[0] + num_escape_char));

#if DEBUG
printf("res is %2d\n", res);

#endif
if (res < 0)

{
printf("write data error!\n");

return FALSE;

}
printf("write data end!!!\n");

#endif
free(escape_char_ptr);
escape_char_ptr = NULL;
}/*end else*/

/*free the memory*/

free(package_data);
package_data = NULL;
}/*end else*/

return TRUE;

}
/*************************************************

* Function: data_recv()
* Description: the data and
* Calls: none
* Called By: none
* Input: none
* Output: none
* Return:
* Author: xhniu
* History: <author> <date> <desc>

* Others: none
************************************************/

void *data_recv(recv_param *data_recv_info_ptr)

{
INT8 port_fd = data_recv_info_ptr->port_fd;
U8 *data_recv_buf_ptr = data_recv_info_ptr->buf;
#if DEBUG
printf("port_fd is %4d\n", data_recv_info_ptr->port_fd);

#endif
U8 pos = 0;
U8 len = 0;
U8 data_proc_pos = 0;
U8 data_start_pos = 0;
U8 data_new_flag = 0;
#if DEBUG
printf("start to read data!\n");

#endif
while(1)
{
/*judge the exit flag*/

if (1 == g_exit_flag)

{
printf("in data_recv thread,g_exit_flag%4d\n", g_exit_flag);

break;
}
sleep(1);
#if DEBUG
printf("pos is %4dlen is %4d\n", pos, len);

#endif
len = read(port_fd, &data_recv_buf_ptr[pos], (BUFFER_SIZE - pos));

printf("len is %4d\n", len);

if (len > 0)
{
printf("len is %4d ", len);

pos += len;
data_new_flag = 1;
continue;

}
else if (0 == data_new_flag && 0 == len)

{
printf("no new data come......\n");

continue;
}/*end if*/

/* receiving data */

if ((0 == len) && (pos < BUFFER_SIZE) &&(1 == data_new_flag))

{
/*start to process data*/

#if DEBUG
printf("data_start_pos is%2d pos is %3d\n", data_start_pos, pos);

#endif
data_proc_pos = data_process(data_recv_buf_ptr, data_start_pos, pos);

if (data_proc_pos > 0)

{
data_start_pos = data_proc_pos;
}
else

{
data_start_pos = pos;
}
printf("data_proc_pos is %3d\n", data_proc_pos);

data_new_flag = 0;
}

if (BUFFER_SIZE == pos)

{
#if DEBUG
printf("stop recv data, data_start_pos is %2d pos is %4d\n",

data_start_pos, pos);
#endif
data_proc_pos = data_process(data_recv_buf_ptr, data_start_pos, pos);

printf("data_proc_pos is %4d\n", data_proc_pos);

memcpy(&data_recv_buf_ptr[0], &data_recv_buf_ptr[data_proc_pos],

(BUFFER_SIZE - data_proc_pos));

pos = (BUFFER_SIZE - data_proc_pos);
data_start_pos = 0;
}/*end if*/

}/*end while*/
}/*end function*/

/*************************************************

* Function: tsk_thread_create()

* Description: create a thread for a tsk

* Calls: main
* Called By: pthread_create
* Input: task
* Output: error infomation
* Return: TURE?FALSE
* Author: xhniu
* History: <author> <date> <desc>

* Others:
************************************************/

pthread_t tsk_thread_create(void *(*start_routine)(void *),void *arg)

{
INT8 ret = 0;
/*create a msg_que*/

msg_que msg_que_info;
INT16 msg_que_id;
key_t key;
key = (key_t)MSG_QUE_KEY;
/*judge the msg que is exist*/

msg_que_id = msgget(MSG_QUE_KEY, IPC_EXCL);
#if 1
printf("%4d\n", msg_que_id);

#endif
if (msg_que_id <= 0)

{
/*create the msg_que*/

printf("the msg que is not exist!\n");

msg_que_id = msgget(key, IPC_CREAT | 0666);

if (msg_que_id < 0)

{
printf("create the msg que failed!\n");

return FALSE;

}
else
{
printf("create the msg que success,and the msg_que_id is:%4d\n",

msg_que_id);
}
}
else
{
printf("the msg_que is exist the msg_que_id is:%4d\n", msg_que_id);

}/*end if*/
pthread_t thread_id;

ret = pthread_create(&thread_id, NULL, (void *)*start_routine, arg);

if (FALSE == ret)
{
perror("cannot create a tsk!!!\n");

return FALSE;

}
else
{
printf("new tsk create success! thread_id is %4d\n", (U16)thread_id);

}

return thread_id;
}
/*************************************************

* Function: tsk_thread_delete()

* Description: delete a thread
* Calls: main
* Called By: pthread_exit()
* Input:
* Output: none
* Return:
* Author: xhniu
* History: <author> <date> <desc>

* Others: none
************************************************/

U8 tsk_thread_delete(void)
{
/*free the related system resource*/

INT16 msg_que_id = 0;
msg_que_id = msgget(MSG_QUE_KEY, IPC_EXCL);
if (msg_que_id < 0)

{
printf("msg que is not exist!\n");

return TRUE;
}
else
{
if(msgctl(msg_que_id, IPC_RMID, 0) < 0)

{
printf("delete msg_que failed!\n");

return FALSE;

}
else
{
printf("delete msg_que: %4d success\n",msg_que_id);

return TRUE;
}/*end if*/

}/*end if*/
}
/*************************************************

* Function: close_port(INT8 port_fd)

* Description: close the serial port

* Calls: none
* Called By: main
* Input: port_fd
* Output: none
* Return: TURE/FALSE
* Author: xhniu
* History: <author> <date> <desc>

* Others: none
************************************************/

U8 close_port(INT8 port_fd)
{
if (close(port_fd) < 0)

{
printf("close the serial port failed!\n");

return FALSE;

}
else
{
printf("close the serial port success\n");

return TRUE;
}/*end if*/

}



/*************************************************************************
> Copyright (C), 2014,
> File Name: scom_protocal.h
> Author: xhniu
> Mail:
> Created Time: Fri 22 Aug 2014 04:45:03 PM CST
> Description: define the scom protocal,realize the data send/recv
escape_character/anti_escape_character data_process
multi thread program and inter thread communication with
message queue;
> Version: V0.1
> Function List:
1.U8 serialport_init(INT8 port_fd, U32 baud_rate,
2.U8 data_bits, U8 parity, U8 stop_bit);
3.void scom_protocal_init(scom_protocal *protocal_info_ptr);
4.INT8 open_port(void);
5.U16 crc16_check(U8 *data_ptr, U8 data_length);
6.U8 escape_character(U8 *package_data_ptr, U8 data_length,
U8 *buffer_ptr);
7.U8 anti_escape_character(U8 *buffer_ptr, U8 *package_data_ptr,
U8 data_length);
8.void *tsk_run(INT8 *param_ptr);
9.U8 data_process(U8 *data_proc_ptr, U8 data_start_pos,
U8 data_end_pos);
10.U8 data_package(scom_protocal *protocal_info_ptr,
U8 *package_data_ptr, U8 data_length);
11.U8 data_send(INT8 port_fd, scom_protocal *protocal_info_ptr,
U8 *data_send_ptr, U8 data_send_length);
12.void *data_recv(recv_param *data_recv_info_ptr);
13.U8 close_port(INT8 port_fd);
> History: <author> <date> <version> <desc>
xhniu 14.09.12 V0.1 Completion of
multi-threaded programming
xhniu 14.09.14 V0.1 add the msg_que
xhniu 16.09.14 V0.1 add the tsk delete function
and free the system resource
xhniu 18.09.14 V0.1
> Others: naming rules is UNIX
m_ member variable g_ globe variable
************************************************************************/
#include<stdlib.h>
#include<math.h>
#include<stdio.h>
#include<fcntl.h> /*File control*/
#include<unistd.h> /**/
#include<errno.h>
#include<string.h>
#include<termio.h> /*provide the common interface*/
#include<sys/types.h>
#include<sys/stat.h>
#include<pthread.h>
#include<sys/ipc.h>
#include<sys/msg.h>
/* To prevent repeated variables defined */
#ifndef _SCOM_PROTOCAL_H_
#define _SCOM_PROTOCAL_H_

typedef unsigned char U8;
typedef unsigned short U16;
typedef unsigned long U32;
typedef signed char INT8;
typedef unsigned int UINT16;
typedef signed int INT16;

/*
* define the macro to set the
* init_value of the property
*/
#define PROPERTY_INIT 0x11
#define PROPERTY_0x01 0x51
#define PROPERTY_0x02 0x91
#define PROPERTY_0x03 0xd1
#define PROPERTY_0x04 0x111
#define PROPERTY_0x05 0x151
#define PROPERTY_OTHER 0x155

#ifndef NULL
#define NULL ((void*) 0)
#endif

#define DEBUG 1

#ifdef DEBUG
#else
#endif

#define HEAD 0xf4
#define TAIL 0x4f

#define FALSE -1
#define TRUE 0
/*define the device port*/
#if 1
#define DEV_PORT "/dev/pts/4"
#else
#define DEV_PORT "/dev/ttyAMA2"
#endif
/*define the flag to cancel the thread*/
U8 g_exit_flag = 0;

#define DATA_LENGTH_MAX 8
#define PROTOCAL_LENGTH 9
#define BUFFER_SIZE 72
#define BAUDRATE 115200
/* */
#endif

#define MSG_QUE_KEY 1024
/*define the struct of the mes_que*/
#define MSG_TYPE 17

typedef struct
{
INT8 msg_type;
U8 msg_len;
/*exclude the head and tail*/
U8 msg_buf[DATA_LENGTH_MAX + PROTOCAL_LENGTH - 2];
}msg_que;

typedef struct
{
INT8 port_fd;
U8 buf[BUFFER_SIZE];
}recv_param;
#if 0
typedef struct
{
U8 package_data_length;
/*exclude the head and tail*/
U8 buf[DATA_LENGTH_MAX + PROTOCAL_LENGTH - 2];
}tsk_param;
#endif

/*self define the protocal of the serial com*/
typedef struct
{
U8 head[1];
U16 serial_num;
U8 length[1]; /*data_length + PROTOCAL_LENGTH*/
U16 property;
U8 package_data[DATA_LENGTH_MAX];
U16 crc_check;
U8 tail[1];
}scom_protocal;

/*function declaration*/
U8 serialport_init(INT8 port_fd, U32 baud_rate,
U8 data_bits, U8 parity, U8 stop_bit);
void scom_protocal_init(scom_protocal *protocal_info_ptr);
INT8 open_port(void);
U16 crc16_check(U8 *data_ptr, U8 data_length);
U8 escape_character(U8 *package_data_ptr, U8 data_length,
U8 *buffer_ptr);
U8 anti_escape_character(U8 *buffer_ptr, U8 *package_data_ptr,
U8 data_length);
void *tsk_run(INT8 *param_ptr);
U8 data_process(U8 *data_proc_ptr, U8 data_start_pos,
U8 data_end_pos);
U8 data_package(scom_protocal *protocal_info_ptr,
U8 *package_data_ptr, U8 data_length);
U8 data_send(INT8 port_fd, scom_protocal *protocal_info_ptr,
U8 *data_send_ptr, U8 data_send_length);
void *data_recv(recv_param *data_recv_info_ptr);
U8 close_port(INT8 port_fd);
/*************************************************
* Function: void serialport_init()
* Description: init the serialport
* Calls: none
* Called By: main
* Input: port_fd baud_rate data_bits parity stop_bit
* Output: print the error info
* Return: none
* Author: xhniu
* History: <author> <date> <desc>
*
* Others: none
*************************************************/
U8 serialport_init(INT8 port_fd, U32 baud_rate,
U8 data_bits, U8 parity, U8 stop_bit)
{
struct termios newtio, oldtio;

/*save the primary params of the serial port stop_bit*/
if (tcgetattr(port_fd, &oldtio )!= 0)
{
perror("setup serial failed!!!\n");
return -1;
}

bzero(&newtio, sizeof(newtio));
/*set the data_bits stop_bit parity*/
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;

switch (data_bits)
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
default:
break;
}

switch (parity)
{
case 'O':/*odd number*/
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E':/*even number*/
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'N':
newtio.c_cflag &= ~PARENB;
break;
default:
break;
}

switch (baud_rate)
{
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
default:
break;
}

if (1 == stop_bit)
{
newtio.c_cflag &= ~CSTOPB;
}
else if (2 == stop_bit)
{
newtio.c_cflag |= CSTOPB;
}

/*active the newtio*/
if ((tcsetattr(port_fd, TCSANOW, &newtio)) != 0)
{
perror("serial port set error!!!\n");
return -1;
}

printf("serial port set done!!!\n");
return 0;
}
/*************************************************
* Function: scom_protocal_init()
* Description: init the params of the protocal
* Calls: none
* Called By: none
* Input: the struct of the scom_protocal
* Output: none
* Return: none
* Author: xhniu
* History: <author> <date> <desc>
* Others: none
*************************************************/
void scom_protocal_init(scom_protocal *protocal_info_ptr)
{
protocal_info_ptr->head[0] = HEAD;
protocal_info_ptr->serial_num = 0x0000;
/*init length is data_length + PROTOCAL_LENGTH*/
protocal_info_ptr->length[0] = 0x11;
protocal_info_ptr->property = PROPERTY_INIT;

memset(protocal_info_ptr->package_data, 0, sizeof(U8) * 8);

protocal_info_ptr->crc_check = 0x0000;
protocal_info_ptr->tail[0] = 0x4f;
}
/*************************************************
* Function: open_port()
* Description: open the DEV_PORT
* Calls: none
* Called By: none
* Input: none
* Output: none
* Return: port_fd
* Author: xhniu
* History: <author> <date> <desc>
* Others: none
*************************************************/
INT8 open_port(void)
{
INT8 port_fd;

/* */
port_fd = open(DEV_PORT,
O_RDWR | O_NOCTTY | O_NONBLOCK);
if (-1 == port_fd)
{
perror("open the serial port failed!!!\n");
return -1;
}

/*set the serial port is block and waitting*/
if (fcntl(port_fd, F_SETFL, 0) < 0)
{
printf("fcntl failed!\n");
}
else
{
printf("fcntl = %d \n", fcntl(port_fd, F_SETFL, 0));
}/*end if*/

return port_fd;
}

/*************************************************
* Function: crc16_check()
* Description: genetrate the check data
* Calls: none
* Called By: data_package()
* Input: data need check and length of data
* Output: none
* Return: crc check data
* Author: xhniu
* History: <author> <date> <desc>
* Others: none
*************************************************/
U16 crc16_check(U8 *data_ptr, U8 data_length) { /*polynomial*/ U16 crc_gen = 0xa001; U16 crc; U8 i, j; /*init value of crc*/ crc = 0xffff; if (data_length != 0) { for (i = 0; i < data_length; i++) { crc ^= (U16)(data_ptr[i]); for (j = 0; j < 8; j++) { if ((crc & 0x01) == 0x01) { crc >>= 1; crc ^= crc_gen; } else { crc >>= 1; } }/*end for*/ }/*end for*/ }/*end if*/ return crc; }

/*************************************************
* Function: escape_character()
* Description: f4 -- ff 01, ff -- ff 02, 4f -- ff 03
* Calls: none
* Called By: data_send
* Input: package_data, data_length, buffer
* Output: none
* Return: TRUE or FALSE
* Author: xhniu
* History: <author> <date> <desc>
* Others: none
*************************************************/
U8 escape_character(U8 *package_data_ptr, U8 data_length, U8 *buffer)
{
if ((NULL == package_data_ptr) | (0 == data_length))
{
printf("input error!!!\n");
return FALSE;
}

U8 count = 1;

buffer[0] = package_data_ptr[0];
buffer++;
/*except the head and the tail*/
for (; count < (data_length -1); count++)
{
if (0xf4 == package_data_ptr[count])
{
*buffer++ = 0xff;
*buffer++ = 0x01;
}
else if (0xff == package_data_ptr[count])
{
*buffer++ = 0xff;
*buffer++ = 0x02;
}
else if (0x4f == package_data_ptr[count])
{
*buffer++ = 0xff;
*buffer++ = 0x03;
}
else
{
*buffer++ = package_data_ptr[count];
}/*end if*/
}/*end for*/
*buffer++ = 0x4f;
*buffer = '\0';

return TRUE;
}
/*************************************************
* Function: anti_escape_character()
* Description: ff 01 -- f4, ff 02 -- ff, ff 03 -- 4f
* Calls: none
* Called By:
* Input: buffer, package_data, data_length
* Output:
* Return:
* Author: xhniu
* History: <author> <date> <desc>
* Others: none
*************************************************/
U8 anti_escape_character(U8 *buffer_ptr, U8 *package_data_ptr,
U8 data_length)
{
if ((NULL == package_data_ptr) | (0 == data_length))
{
printf("input data error!\n");
return FALSE;
}

U8 flag = 0;
U8 count = 0;

package_data_ptr[0] = buffer_ptr[0];
package_data_ptr++;
buffer_ptr++;
/*exclude the tail 0x4f*/
while (TAIL != *buffer_ptr)
{
if (0xff == *buffer_ptr)
{
flag = 1;
buffer_ptr++;

if ((0x01 == *buffer_ptr) && (1 == flag))
{
*package_data_ptr++ = 0xf4;
}
else if ((0x02 == *buffer_ptr) && (1 == flag))
{
*package_data_ptr++ = 0xff;
}
else if ((0x03 == *buffer_ptr) && (1 == flag))
{
*package_data_ptr++ = 0x4f;
}
else if (1 == flag)
{
*package_data_ptr++ = 0xff;
*package_data_ptr++ = *buffer_ptr++;
}
buffer_ptr++;
}
else
{
*package_data_ptr++ = *buffer_ptr++;
flag = 0;
}/*end if*/

}/*end while*/

return TRUE;
}

/*************************************************
* Function: tsk_run()
* Description: receive a package data and execute a tsk
* Calls: none
* Called By: data_recv()
* Input: data_proc_ptr
* Output: none
* Return:
* Author: xhniu
* History: <author> <date> <desc>
* Others: none
************************************************/
void *tsk_run(INT8 *param_ptr)
{
INT8 port_fd = *param_ptr;
U8 *exit_ptr = "exit";
#if DEBUG
printf("in tsk_run,port_fd is %4d\n", port_fd);
#endif
/*use to data send*/
scom_protocal scom_protocal_info;
memset(&scom_protocal_info, 0, sizeof(scom_protocal_info));
scom_protocal_init(&scom_protocal_info);
U8 data_send_length = 0;
U8 data_send_array[32] = {0};
U8 num = 0;
/*use to data proc*/
U8 package_data_ptr[DATA_LENGTH_MAX + PROTOCAL_LENGTH - 2] = {0};
U8 data_ptr[DATA_LENGTH_MAX] = {0};
U8 package_data_length = 0;
/*define the var to recv msg form msg_que*/
INT16 msg_que_id;
INT8 ret;
msg_que msg_que_info;
memset(&msg_que_info, 0, sizeof(msg_que_info));
/*proc the sub package*/
U8 sub_package_num = 0;
U8 sub_package_flag = 0;
U8 sub_package_ID = 0;
U8 sub_package_count = 0;
U8 sub_package_buf[DATA_LENGTH_MAX * 8] = {0};
INT16 cur_time = 0;
INT16 last_time = 0;

while (1)
{
/*judge the exit flag*/
if(1 == g_exit_flag)
{
printf("int tsk_run,g_exit_flag is:%4d\n", g_exit_flag);
break;
}

/*check the msg que is exist*/
msg_que_id = msgget(MSG_QUE_KEY, IPC_EXCL);
if (msg_que_id <= 0)
{
printf("msg que is not exist!\n");
sleep(1);
continue;
}
else
{
printf("\nin tsk_run,msg_que_id is %4d\n", msg_que_id);
}
/*start to recv data from the msg que*/
ret = msgrcv(msg_que_id, &msg_que_info, sizeof(msg_que_info), 0, 0);
if (ret < 0)
{
printf("recv data from the msg que failed!\n");
continue;
}
else
{
printf("recv data from the msg que success!\n");
}/*end if*/

/*get the cur time*/
if (0 != last_time)
{
printf("*****last_time is %4d*****\n", last_time);
cur_time = time((time_t*)NULL);
printf("cur_time is :%4d\n", cur_time);
if (cur_time - last_time > 10)
{
printf("cannot get the complete package_data!!!\n");
memset(sub_package_buf, 0, DATA_LENGTH_MAX * 8);
sub_package_count = 0;
last_time = 0;
continue;
}
}/*end if*/

package_data_length = msg_que_info.msg_len;
memcpy(package_data_ptr, msg_que_info.msg_buf, msg_que_info.msg_len);
#if DEBUG
printf("package_data_length is %4d\n", package_data_length);
U8 i = 0;
while (i < package_data_length)
{
printf("%02x ", package_data_ptr[i++]);
}
printf("\n");
#endif
U16 property = 0;
property = package_data_ptr[4];
property = property << 8;
property = (property | package_data_ptr[3]);
#if DEBUG
printf("property is:%04x\n", property);
#endif
/*judging whethre the data sub*/
sub_package_num = (property >> 13);
sub_package_ID = (property >> 10);
sub_package_ID &= 0x07;
printf("the sub_package_ID is %4d\n", sub_package_ID);

if (0 != sub_package_num)
{
sub_package_flag = 1;
sub_package_count++;
memcpy(&sub_package_buf[ sub_package_ID * DATA_LENGTH_MAX],
&package_data_ptr[5],package_data_ptr[2] - PROTOCAL_LENGTH);
printf("sub_package_count is %4d subpackage_num is %4d\n", sub_package_count, sub_package_num);
/*recv the complete package*/
if(sub_package_count == (sub_package_num + 1))
{
#if DEBUG
U8 i = 0;
for (; i < 28; i++)
{
printf("%c",sub_package_buf[i]);
}
printf("\n");
#endif
system(sub_package_buf);
memset(sub_package_buf, 0, DATA_LENGTH_MAX * 8);
sub_package_count = 0;
last_time = 0;
continue;
}
else
{
last_time = time((time_t*)NULL);
printf("last_time is:%4d\n",last_time);
}/*end if*/
continue;
}/*end if*/

memcpy(data_ptr, &package_data_ptr[5], package_data_ptr[2] - PROTOCAL_LENGTH);
property &= 0x3ff;
switch (property)
{
case PROPERTY_INIT:
{
printf("The receive cmd is linux system cmd:%s\n", data_ptr);

if (0 == strcmp(exit_ptr, data_ptr))
{
g_exit_flag = 1;
}
else
{
system(data_ptr);
}
break;
}
case PROPERTY_0x01:
{
#if DEBUG
printf("The receive cmd is get the GPS data:\n");
#endif
printf("GPS:longitude :%04x, latitude :%04x, height :%04x, time :%04x\n",
0xf101,0xf202, 0xf123, 0xffff);

num = 0;
data_send_array[num++] = 0x01;
data_send_array[num++] = 0xf1;
data_send_array[num++] = 0x02;
data_send_array[num++] = 0xf2;
data_send_array[num++] = 0x23;
data_send_array[num++] = 0xf1;
data_send_array[num++] = 0xff;
data_send_array[num++] = 0xff;
scom_protocal_info.property = PROPERTY_0x01;
data_send(port_fd, &scom_protocal_info, data_send_array, 8);
break;
}
case PROPERTY_0x02:
{
printf("The receive cmd is get the gyroscope data:\n");
printf("gyroscope:\ncabrage:%04x, yaw:%04x, roll;%04x\n",
0xf1f2, 0xf3f4, 0xf5f6);
num = 0;
data_send_array[num++] = 0xf2;
data_send_array[num++] = 0xf1;
data_send_array[num++] = 0xf4;
data_send_array[num++] = 0xf3;
data_send_array[num++] = 0xf6;
data_send_array[num++] = 0xf5;

scom_protocal_info.property = PROPERTY_0x02;
data_send(port_fd, &scom_protocal_info, data_send_array, num);
break;
}
case PROPERTY_0x03:
{
printf("The receive cm d is get the accelerometer data:\n");
printf("accelerometer:\nX:%04x, Y:%04x, Z:%04x\n",
0x0102, 0x0304, 0x0506);
num = 0;
data_send_array[num++] = 0x02;
data_send_array[num++] = 0x01;
data_send_array[num++] = 0x04;
data_send_array[num++] = 0x03;
data_send_array[num++] = 0x06;
data_send_array[num++] = 0x05;

scom_protocal_info.property = PROPERTY_0x03;
data_send(port_fd, &scom_protocal_info, data_send_array, num);
break;
}
case PROPERTY_0x04:
{
printf("The receive cmd is get th e target info:\n");

num = 0;
data_send_array[num++] = 0x01;
data_send_array[num++] = 0x34;
data_send_array[num++] = 0x12;
data_send_array[num++] = 0x21;
data_send_array[num++] = 0x43;
data_send_array[num++] = 0x02;
data_send_array[num++] = 0x78;
data_send_array[num++] = 0x56;
data_send_array[num++] = 0x65;
data_send_array[num++] = 0x87;
data_send_array[num++] = 0x03;
data_send_array[num++] = 0x14;
data_send_array[num++] = 0x23;
data_send_array[num++] = 0x21;
data_send_array[num++] = 0x34;

scom_protocal_info.property = PROPERTY_0x04;
data_send(port_fd, &scom_protocal_info, data_send_array, num);
break;
}
case PROPERTY_0x05:
{
printf("the cmd is get the D5 info:\n");

num = 0;
data_send_array[num++] = 0x01;
data_send_array[num++] = 0x34;
data_send_array[num++] = 0x12;
data_send_array[num++] = 0x21;
data_send_array[num++] = 0x43;
data_send_array[num++] = 0x02;
data_send_array[num++] = 0x78;
data_send_array[num++] = 0x56;
data_send_array[num++] = 0x65;
data_send_array[num++] = 0x87;
data_send_array[num++] = 0x03;
data_send_array[num++] = 0x14;
data_send_array[num++] = 0x23;
data_send_array[num++] = 0x21;
break;
}
default:
{
printf("cannot discrimate the cmd:\n");

U8 i = 0;
for (; i < package_data_ptr[2] - PROTOCAL_LENGTH; i++)
{
printf("%02x ", data_ptr[i]);
}
printf("\n");
break;
}
}/*end switch*/
}/*end ehile*/
}

/*************************************************
* Function: data_process()
* Description: process the data form the bufer_recv
* Calls: none
* Called By: data_recv()
* Input: data_proc_ptr
* Output: none
* Return:
* Author: xhniu
* History: <author> <date> <desc>
* Others: none
************************************************/
U8 data_process(U8 *data_proc_ptr,
U8 data_start_pos,
U8 data_end_pos)
{
if ((NULL == data_proc_ptr) || (data_start_pos >= data_end_pos))
{
printf("input data error!\n");
return 0;
}

/*use msg_que to do the ipc*/
msg_que msg_que_info;
INT8 ret = 0;
INT16 msg_que_id;
memset(&msg_que_info, 0, sizeof(msg_que_info));
msg_que_id = msgget((key_t)MSG_QUE_KEY, IPC_EXCL);
#if DEBUG
printf("the msg_que_id is:%4d\n", msg_que_id);
#endif

/*process data buffer*/
U8 buffer[(DATA_LENGTH_MAX + PROTOCAL_LENGTH) * 2 - 2] = {0};
U8 package_data[(DATA_LENGTH_MAX + PROTOCAL_LENGTH) * 2] = {0};

/* */
U8 head_flag = 0;
U8 tail_flag = 0;
U8 pos = 0;
U8 package_data_length = 0;

for (; data_start_pos < data_end_pos; data_start_pos++)
{
/*find the head */
if ((HEAD == data_proc_ptr[data_start_pos])
&& (0 == head_flag))
{
head_flag = 1;
pos = data_start_pos;
continue;
}
/*avoid the double head or triple head*/
if ((HEAD == data_proc_ptr[data_start_pos])
&& (1 == head_flag))
{
pos = data_start_pos;
}

if ((TAIL == data_proc_ptr[data_start_pos])
&& (0 == tail_flag))
{
if(1 == head_flag)
{
tail_flag = 1;
}
else
{
tail_flag = 0;
}
}

/*process a packaged data*/
if ((1 == head_flag) && (1 == tail_flag))
{
printf("data_start_pos is %2d, pos is %2d ", data_start_pos, pos);
memset(buffer, 0x00, (DATA_LENGTH_MAX + PROTOCAL_LENGTH) * 2 - 2);
memcpy(buffer, &data_proc_ptr[pos],
(data_start_pos - pos + 1));

/*anti escape character*/
printf("\nanti escape character! data_start_pos is %4d pos is %4d\n",
data_start_pos, pos);
memset(package_data, 0x00,
(DATA_LENGTH_MAX + PROTOCAL_LENGTH) * 2);
anti_escape_character(buffer, package_data,
(data_start_pos - pos + 1));

/*data length exclude head and tail*/
#if DEBUG
printf("data length is: package[3] = %2d\n", package_data[3] - 2);
#endif
package_data_length = package_data[3] - 2;
printf("crc16_check is 0x%04x\n",
crc16_check(&package_data[1], package_data_length));
if (0x00 == crc16_check(&package_data[1], package_data_length))
{
printf("crc16_check success!\n");
}
else
{
printf("crc16_ check error!\n");
/*
* theoretically,it will return the serial_num
* and the sub_package_ID
*/
return 0;
}
/*get a complete package data and send it to the msg_que*/
msg_que_info.msg_type = MSG_TYPE;
msg_que_info.msg_len = package_data_length;
#if DEBUG
printf("msg_que_info.msg_len is %4d\n",
msg_que_info.msg_len);
#endif
memcpy(&(msg_que_info.msg_buf), &package_data[1],
package_data_length);
/*send the msg*/
ret = msgsnd(msg_que_id, &msg_que_info, package_data_length, IPC_NOWAIT);
if (ret < 0)
{
printf("msg send failed!\n");
return 0;
}
else
{
printf("send msg success! ret is %4d\n", ret);
sleep(2);
}

head_flag = 0;
tail_flag = 0;
pos = 0;
}
}
#if 0
printf("\nreturn data is: %4d\n", pos);
#endif
return pos;
}
/*************************************************
* Function: data_package()
* Description: package the data with the scom_protocal
* Calls:
* Called By: data_send
* Input: protocal_info_ptr, package_data, data_length
* Output:
* Return: TRUE/FALSE
* Author: xhniu
* History: <author> <date> <desc>
* Others: none
*************************************************/
U8 data_package(scom_protocal *protocal_info_ptr,
U8 *package_data_ptr, U8 data_length)
{
/*decide whether need subpackage*/
if (data_length > DATA_LENGTH_MAX)
{
printf("input valid!!!\n");
return -1;
}

U8 len = 0;

package_data_ptr[0] = protocal_info_ptr->head[0];
/*U16 to U8 low 8 bit*/
package_data_ptr[1] = (U8)(protocal_info_ptr->serial_num);
package_data_ptr[2] = (U8)((protocal_info_ptr->serial_num)
>> 8);

package_data_ptr[3] = data_length + PROTOCAL_LENGTH;

/*U16 to U8 low 8 bit*/
package_data_ptr[4] = (U8)(protocal_info_ptr->property);
/*high 8 bit*/
package_data_ptr[5] = (U8)((protocal_info_ptr->property)
>> 8);

for (; len < data_length; len++)
{
package_data_ptr[len + 6] =
protocal_info_ptr->package_data[len];
}
/*
*generate the CRC16 check data
* U16 to U8
*/
U16 check_code;
/*data_length + property(2 byte) + length(1 byte) +
* serial_num(2 byte)
*/
U8 *ptr = malloc(sizeof(U8) * (data_length + 5));
memcpy(ptr, package_data_ptr + 1, data_length + 5);
check_code = crc16_check(ptr, data_length + 5);
/*free the ptr*/
free(ptr);
ptr = NULL;

/*low 8 bit*/
package_data_ptr[len + 6] = (U8)(check_code);
/*high 8 bie*/
package_data_ptr[len + 7] = (U8)(check_code >> 8);
package_data_ptr[len + 8] = protocal_info_ptr->tail[0];

return TRUE;
}
/*************************************************
* Function: data_send()
* Description: read the data and
* Calls: none
* Called By: none
* Input: none
* Output: none
* Return:
* Author: xhniu
* History: <author> <date> <desc>
* Others: none
*************************************************/
U8 data_send(INT8 port_fd, scom_protocal *protocal_info_ptr,
U8 *data_send_ptr, U8 data_send_length)
{
if (NULL == data_send_ptr)
{
printf("input data error!!!\n");
return FALSE;
}

/*number of the char need escape*/
U8 num_escape_char = 0;
U8 num_escape_char_temp = 0;

U8 *package_data = NULL;
U8 *escape_char_ptr = NULL;

/*when send new data, the serial num will plus 1*/
(protocal_info_ptr->serial_num)++;

if (data_send_length > DATA_LENGTH_MAX)
{
/*need the subpackage calculate the sun_package_num
* set the flag of the subpackage*/
int sub_package_num = 0, count = 0;
if (0 != data_send_length % DATA_LENGTH_MAX)
{
sub_package_num = (data_send_length / DATA_LENGTH_MAX) + 1;
}
else
{
sub_package_num = (data_send_length / DATA_LENGTH_MAX);
}

/*3 byte of the sub_package_num the data area is
*1 ~ 7
*/
if (sub_package_num > 8)
{
return FALSE;
}
protocal_info_ptr->property &= 0x1fff;
protocal_info_ptr->property |= ((sub_package_num - 1) << 13);
#if DEBUG
printf("sub_package_num is:%4x\n",sub_package_num);
#endif
/*
* sub_package_num - 1
* the length of the last sub_package is not sure
*/
for (; count < (sub_package_num - 1); count++)
{
/*set the length of the protcal_info_ptr->length[0]*/
protocal_info_ptr->length[0] =
DATA_LENGTH_MAX + PROTOCAL_LENGTH;
/*set the ID of the subpackage*/
protocal_info_ptr->property &= 0xe3ff;
protocal_info_ptr->property |= (count << 10);

memcpy(protocal_info_ptr->package_data,
(data_send_ptr + count * DATA_LENGTH_MAX ),
DATA_LENGTH_MAX);
#if 0
U8 m = 0;
for (; m < protocal_info_ptr->length[0]; m++)
{
printf("%02x ", protocal_info_ptr->package_data[m]);
}
printf("\n");
#endif
/*malloc a mem to restore the packaged data
*plus the head(1),tail(1),length(1),property(2),crc(2),serial_num(2),
*/
package_data = (U8 *)malloc(sizeof(U8) *
(DATA_LENGTH_MAX + PROTOCAL_LENGTH));
if (NULL == package_data)
{
printf("malloc failed\n");
return FALSE;
}

data_package(protocal_info_ptr, package_data,
DATA_LENGTH_MAX);
#if DEBUG
U8 m = 0;
for (; m < 17; m++)
{
printf("%02x ", package_data[m]);
}
printf("\n");
#endif
/* malloc a buffer use to send data
* character transfer
*/
num_escape_char = 0;
num_escape_char_temp = 0;
/*count the num of the 0xff 0xf4 0x4f except tail and head*/
num_escape_char_temp = protocal_info_ptr->length[0] - 2;

while ((num_escape_char_temp--) > 1)
{
if ((0xff == package_data[num_escape_char_temp])
| (0xf4 == package_data[num_escape_char_temp])
| (0x4f == package_data[num_escape_char_temp]))
{
num_escape_char++;
}
}
#if DEBUG
printf("num_escape_char is %4d\n", num_escape_char);
#endif
if(0 == num_escape_char)
{
/*no escape characters send data diretly*/
if (write(port_fd, package_data,
(protocal_info_ptr->length[0])) < 0)
{
printf("write data error! \n");
return FALSE;
}
else
{
printf("write data success!\n");
}
}
else
{
escape_char_ptr = (U8 *)malloc(sizeof(U8)
* (protocal_info_ptr->length[0] + num_escape_char));
#if DEBUG
printf("%4d \n", protocal_info_ptr->length[0]);
#endif
escape_character(package_data,
protocal_info_ptr->length[0], escape_char_ptr);
#if DEBUG
U8 k = 0;
for (; k < protocal_info_ptr->length[0]
+ num_escape_char; k++)
{
printf("%04x ", escape_char_ptr[k]);
}
#endif
/*send data*/
if (write(port_fd, escape_char_ptr,
(protocal_info_ptr->length[0] + num_escape_char)) < 0)
{
printf("write data error! \n");
return FALSE;
}
else
{
printf("write data success!\n");
}

/*free the memory*/
free(escape_char_ptr);
escape_char_ptr = NULL;
}

free(package_data);
package_data = NULL;

}/*end for*/
if (data_send_length - count * DATA_LENGTH_MAX > 0)
{
protocal_info_ptr->length[0] = data_send_length
- count * DATA_LENGTH_MAX + PROTOCAL_LENGTH;

protocal_info_ptr->property &= 0xe3ff;
protocal_info_ptr->property |= (count << 10);
memcpy(protocal_info_ptr->package_data,
(data_send_ptr + count * DATA_LENGTH_MAX),
(data_send_length - count * DATA_LENGTH_MAX));
/*malloc a mem to restore the packaged data*/
package_data = (U8 *)malloc(sizeof(U8) * (data_send_length
- count * DATA_LENGTH_MAX + PROTOCAL_LENGTH));
if (NULL == package_data)
{
printf("malloc failed \n");
}
#if DEBUG
printf("the rest data length is %4d\n",
data_send_length - count * DATA_LENGTH_MAX );
#endif

data_package(protocal_info_ptr, package_data,
data_send_length - count * DATA_LENGTH_MAX);
#if DEBUG
U8 n = 0;
for (; n < protocal_info_ptr->length[0]; n++)
{
printf("%02x ", package_data
);
}
printf("\n");
#endif
/* malloc a buffer use to send data
* character transfer
*/
num_escape_char = 0;
num_escape_char_temp = 0;
/*count the num of the 0xff 0xf4 0x4f except tail and head*/
num_escape_char_temp = protocal_info_ptr->length[0] - 2;

while ((num_escape_char_temp--) > 1)
{
if ((0xff == package_data[num_escape_char_temp])
| (0xf4 == package_data[num_escape_char_temp])
| (0x4f == package_data[num_escape_char_temp]))
{
num_escape_char++;
}
}
#if DEBUG
printf("num_escape_char is %4d\n", num_escape_char);
#endif
if(0 == num_escape_char)
{
/*no escape characters send data diretly*/
if (write(port_fd, package_data,
(protocal_info_ptr->length[0])) < 0)
{
printf("write data error! \n");
return FALSE;
}
else
{
printf("write data success!\n");
}
}
else
{
escape_char_ptr = (U8 *)malloc(sizeof(U8)
* (protocal_info_ptr->length[0] + num_escape_char));
#if DEBUG
printf("%4d \n", protocal_info_ptr->length[0]);
#endif
escape_character(package_data,
protocal_info_ptr->length[0], escape_char_ptr);
#if DEBUG
U8 k = 0;
for (; k < protocal_info_ptr->length[0]
+ num_escape_char; k++)
{
printf("%04x ", escape_char_ptr[k]);
}
#endif
/*send data*/
#if 1
if (write(port_fd, escape_char_ptr,
(protocal_info_ptr->length[0] + num_escape_char)) < 0)
{
printf("write data error!\n");
return FALSE;
}
#endif
free(escape_char_ptr);
escape_char_ptr = NULL;
/*send data*/
}

/*free the memory*/
free(package_data);
package_data = NULL;

return TRUE;
/**/
}
else/* data_send_length - count * DATA_LENGTH_MAX = 0 */
{
return TRUE;
}/*end if*/
}
else /*data_send_length <= DATA_LENGTH_MAX no subpackage*/
{
/*set the length of tht protocal_info_ptr->length[0]*/
protocal_info_ptr->length[0] = data_send_length + PROTOCAL_LENGTH;

memcpy(protocal_info_ptr->package_data, data_send_ptr, data_send_length);
/*malloc a mem to restore the packaged data*/
package_data = (U8 *)malloc(sizeof(U8)
* (data_send_length + PROTOCAL_LENGTH));
#if DEBUG
printf("data_send_length is %4d\n", data_send_length);
#endif
if (NULL == package_data)
{
printf("malloc failed!!!\n");
return FALSE;
}
#if DEBUG
printf("data_send_length + PROTOCAL_LENGTH is %4d \n",
data_send_length + PROTOCAL_LENGTH);
#endif
data_package(protocal_info_ptr, package_data, data_send_length);

#if DEBUG
printf("protocal_info_ptr_length[0] is %4d \n", protocal_info_ptr->length[0]);
U8 j = 0;
for (; j < data_send_length + PROTOCAL_LENGTH; j++)
{
printf("%02x ", package_data[j]);
}
printf("\n");
#endif
/* malloc a buffer use to send data
* character transfer
*/
U8 num_escape_char = 0;
U8 num_escape_char_temp = 0;
/*count the num of the 0xff 0xf4 0x4f except tail and head*/
num_escape_char_temp = protocal_info_ptr->length[0] - 2;
#if 0
printf("%4d\n", num_escape_char_temp);
#endif
while ((num_escape_char_temp--) > 1)
{
if ((0xff == package_data[num_escape_char_temp])
| (0xf4 == package_data[num_escape_char_temp])
| (0x4f == package_data[num_escape_char_temp]))
{
num_escape_char++;
}/*end if*/
}/*end while*/
#if DEBUG
printf("num_escape_char is %4d\n", num_escape_char);
#endif
if(0 == num_escape_char)
{
/*no escape characters send data diretly*/
if (write(port_fd, package_data,
protocal_info_ptr->length[0]) < 0)
{
printf("write data error!!!\n");
return FALSE;
}
else
{
printf("write to port_fd data success!\n");
}

/*free the malloc*/
free(package_data);
package_data = NULL;
}/*end if*/
else
{
escape_char_ptr = (U8 *)malloc(sizeof(U8)
* (protocal_info_ptr->length[0] + num_escape_char));
#if DEBUG
printf("%4d \n", protocal_info_ptr->length[0]);
#endif
escape_character(package_data,
protocal_info_ptr->length[0], escape_char_ptr);
#if DEBUG
U8 k = 0;
for (; k < protocal_info_ptr->length[0]
+ num_escape_char; k++)
{
printf("%04x ", escape_char_ptr[k]);
}
printf("\nport_fd is %4d\n", port_fd);
#endif
/*send data*/
INT8 res = 0;
#if 1
printf("writing data......\n");
/*escape_char_ptr */
res = write(port_fd, escape_char_ptr,
(protocal_info_ptr->length[0] + num_escape_char));
#if DEBUG
printf("res is %2d\n", res);
#endif
if (res < 0)
{
printf("write data error!\n");
return FALSE;
}
printf("write data end!!!\n");
#endif
free(escape_char_ptr);
escape_char_ptr = NULL;
}/*end else*/

/*free the memory*/
free(package_data);
package_data = NULL;
}/*end else*/

return TRUE;
}
/*************************************************
* Function: data_recv()
* Description: the data and
* Calls: none
* Called By: none
* Input: none
* Output: none
* Return:
* Author: xhniu
* History: <author> <date> <desc>
* Others: none
************************************************/
void *data_recv(recv_param *data_recv_info_ptr)
{
INT8 port_fd = data_recv_info_ptr->port_fd;
U8 *data_recv_buf_ptr = data_recv_info_ptr->buf;
#if DEBUG
printf("port_fd is %4d\n", data_recv_info_ptr->port_fd);
#endif
U8 pos = 0;
U8 len = 0;
U8 data_proc_pos = 0;
U8 data_start_pos = 0;
U8 data_new_flag = 0;
#if DEBUG
printf("start to read data!\n");
#endif
while(1)
{
/*judge the exit flag*/
if (1 == g_exit_flag)
{
printf("in data_recv thread,g_exit_flag%4d\n", g_exit_flag);
break;
}
sleep(1);
#if DEBUG
printf("pos is %4dlen is %4d\n", pos, len);
#endif
len = read(port_fd, &data_recv_buf_ptr[pos], (BUFFER_SIZE - pos));
printf("len is %4d\n", len);
if (len > 0)
{
printf("len is %4d ", len);
pos += len;
data_new_flag = 1;
continue;
}
else if (0 == data_new_flag && 0 == len)
{
printf("no new data come......\n");
continue;
}/*end if*/

/* receiving data */
if ((0 == len) && (pos < BUFFER_SIZE) &&(1 == data_new_flag))
{
/*start to process data*/
#if DEBUG
printf("data_start_pos is%2d pos is %3d\n", data_start_pos, pos);
#endif
data_proc_pos = data_process(data_recv_buf_ptr, data_start_pos, pos);
if (data_proc_pos > 0)
{
data_start_pos = data_proc_pos;
}
else
{
data_start_pos = pos;
}
printf("data_proc_pos is %3d\n", data_proc_pos);
data_new_flag = 0;
}

if (BUFFER_SIZE == pos)
{
#if DEBUG
printf("stop recv data, data_start_pos is %2d pos is %4d\n",
data_start_pos, pos);
#endif
data_proc_pos = data_process(data_recv_buf_ptr, data_start_pos, pos);

printf("data_proc_pos is %4d\n", data_proc_pos);

memcpy(&data_recv_buf_ptr[0], &data_recv_buf_ptr[data_proc_pos],
(BUFFER_SIZE - data_proc_pos));

pos = (BUFFER_SIZE - data_proc_pos);
data_start_pos = 0;
}/*end if*/

}/*end while*/
}/*end function*/
/*************************************************
* Function: tsk_thread_create()
* Description: create a thread for a tsk
* Calls: main
* Called By: pthread_create
* Input: task
* Output: error infomation
* Return: TURE?FALSE
* Author: xhniu
* History: <author> <date> <desc>
* Others:
************************************************/
pthread_t tsk_thread_create(void *(*start_routine)(void *),void *arg)
{
INT8 ret = 0;
/*create a msg_que*/
msg_que msg_que_info;
INT16 msg_que_id;
key_t key;
key = (key_t)MSG_QUE_KEY;
/*judge the msg que is exist*/
msg_que_id = msgget(MSG_QUE_KEY, IPC_EXCL);
#if 1
printf("%4d\n", msg_que_id);
#endif
if (msg_que_id <= 0)
{
/*create the msg_que*/
printf("the msg que is not exist!\n");
msg_que_id = msgget(key, IPC_CREAT | 0666);
if (msg_que_id < 0)
{
printf("create the msg que failed!\n");
return FALSE;
}
else
{
printf("create the msg que success,and the msg_que_id is:%4d\n",
msg_que_id);
}
}
else
{
printf("the msg_que is exist the msg_que_id is:%4d\n", msg_que_id);
}/*end if*/
pthread_t thread_id;

ret = pthread_create(&thread_id, NULL, (void *)*start_routine, arg);
if (FALSE == ret)
{
perror("cannot create a tsk!!!\n");
return FALSE;
}
else
{
printf("new tsk create success! thread_id is %4d\n", (U16)thread_id);
}

return thread_id;
}
/*************************************************
* Function: tsk_thread_delete()
* Description: delete a thread
* Calls: main
* Called By: pthread_exit()
* Input:
* Output: none
* Return:
* Author: xhniu
* History: <author> <date> <desc>
* Others: none
************************************************/
U8 tsk_thread_delete(void)
{
/*free the related system resource*/
INT16 msg_que_id = 0;
msg_que_id = msgget(MSG_QUE_KEY, IPC_EXCL);
if (msg_que_id < 0)
{
printf("msg que is not exist!\n");
return TRUE;
}
else
{
if(msgctl(msg_que_id, IPC_RMID, 0) < 0)
{
printf("delete msg_que failed!\n");
return FALSE;
}
else
{
printf("delete msg_que: %4d success\n",msg_que_id);
return TRUE;
}/*end if*/
}/*end if*/
}
/*************************************************
* Function: close_port(INT8 port_fd)
* Description: close the serial port
* Calls: none
* Called By: main
* Input: port_fd
* Output: none
* Return: TURE/FALSE
* Author: xhniu
* History: <author> <date> <desc>
* Others: none
************************************************/
U8 close_port(INT8 port_fd)
{
if (close(port_fd) < 0)
{
printf("close the serial port failed!\n");
return FALSE;
}
else
{
printf("close the serial port success\n");
return TRUE;
}/*end if*/
}


转:http://blog.csdn.net/niuxuheng/article/details/39345241

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: