#include "port.h" | |
/** | |
* @brief Send Data to serial port | |
* @param fd:file desc | |
* @param cmd:data pointer | |
* @param cmd_len:data length | |
* @retval SUCCESS/FAIL | |
*/ | |
int uart_send(int fd, const uint8_t *cmd, int cmd_len) | |
{ | |
int ret = FAIL; | |
ret = write(fd, cmd, cmd_len); | |
if(ret < 0) | |
{ | |
HDBD_LOG("[%s %d]write port failed,ret: %d\n", __FUNCTION__, __LINE__, ret); | |
return FAIL; | |
} | |
return SUCCESS; | |
} | |
/** | |
* @brief Receive data from serial port0 | |
* @param fd:file desc | |
* @param buf:receive buffer | |
* @param actual_length:receive data length | |
* @param timeout:para of timeout | |
* @retval SUCCESS/FAIL | |
*/ | |
int uart_recv(int fd, uint8_t *buf, int *actual_length, int timeout) | |
{ | |
int ret; | |
int temp = 0; | |
int len = *actual_length; | |
uint8_t tempBuf[128] = {0}; | |
int errorCount = 0; | |
fd_set rd; | |
struct timeval tv; | |
tv.tv_sec = timeout; | |
tv.tv_usec = 0; | |
FD_ZERO(&rd); | |
FD_SET(fd, &rd); | |
*actual_length = 0; | |
HDBD_LOG("[%s %d] len:%d\n", __FUNCTION__, __LINE__, len); | |
while(1) | |
{ | |
ret = select(fd + 1, &rd, NULL, NULL, &tv); | |
if(ret > 0){ | |
if (FD_ISSET(fd, &rd)) { | |
temp = read(fd, tempBuf, 128); | |
if(temp > 0) | |
{ | |
errorCount = 0; | |
if((*actual_length + temp) <= len) | |
{ | |
memcpy(buf+*actual_length, tempBuf, temp); | |
*actual_length += temp; | |
} | |
else | |
{ | |
memcpy(buf+*actual_length, tempBuf, (len - *actual_length)); | |
*actual_length = len; | |
} | |
} | |
else | |
{ | |
errorCount++; | |
} | |
HDBD_LOG("[%s %d]len:%d, *actual_length:%d, temp:%d\n", __FUNCTION__, __LINE__, len, *actual_length, temp); | |
} | |
} | |
else if(ret == 0) | |
{ | |
HDBD_LOG("[%s %d]timeout\n", __FUNCTION__, __LINE__); | |
if(*actual_length <= 2) | |
{ | |
goto ERR1; | |
} | |
else | |
{ | |
break; | |
} | |
} | |
else | |
{ | |
HDBD_LOG("[%s %d] select error!\n", __FUNCTION__, __LINE__); | |
goto ERR1; | |
} | |
if((*actual_length >= len) || (errorCount >= 5)) | |
{ | |
HDBD_LOG("[%s %d]*actual_length:%d, recv sucess,break\n", __FUNCTION__, __LINE__, *actual_length); | |
break; | |
} | |
} | |
HDBD_LOG("[%s %d]*actual_length:%d, ret:%d\n", __FUNCTION__, __LINE__, *actual_length, ret); | |
return SUCCESS; | |
ERR1: | |
return FAIL; | |
} | |
int UartRead(int fd, uint8_t *RxBuff, long RxLen) | |
{ | |
#if 1 | |
int GetRxLen=0; | |
int index; | |
while(RxLen){ | |
//printf("RxLen=%d\r\n", RxLen); | |
index = read(fd, RxBuff+GetRxLen, 1); | |
//printf("index=%d\r\n", index); | |
GetRxLen += index; | |
//printf("GetRxLen=%d\r\n", GetRxLen); | |
RxLen--; | |
//printf("RxLen=%d\r\n", RxLen); | |
if(index == 0) | |
{ | |
return GetRxLen; | |
} | |
} | |
return GetRxLen ; | |
#else | |
int GetRxLen=0; | |
while(RxLen){ | |
//printf("[RxLen=%ld]\r\n", RxLen); | |
GetRxLen += read(fd, RxBuff+GetRxLen, 1); | |
RxLen--; | |
} | |
return GetRxLen ; | |
#endif | |
} | |
/** | |
* @brief Write gpio node | |
* @param path:path of gpio node | |
* @param value:'1' or '0' | |
* @retval SUCCESS/FAIL | |
*/ | |
int write_gpio(char const* path, int value) | |
{ | |
int fd = -1; | |
char buffer[20] = {0}; | |
int bytes = 0; | |
ssize_t amt = 0; | |
memset(buffer, 0x0, sizeof(buffer)); | |
fd = open(path, O_RDWR); | |
if (fd >= 0) | |
{ | |
bytes = snprintf(buffer, sizeof(buffer), "%d\n", value); | |
amt = write(fd, buffer, (size_t)bytes); | |
close(fd); | |
return amt == -1 ? -errno : 0; | |
} | |
else | |
{ | |
HDBD_LOG("[%s %d]write_int failed to open %s, errno is %d \n", __FUNCTION__, __LINE__, path, errno); | |
} | |
return -errno; | |
} | |
/** | |
* @brief Read gpio node | |
* @param path:path of gpio node | |
* @param value:'1' or '0' | |
* @retval SUCCESS/FAIL | |
*/ | |
int read_gpio(char const* path) | |
{ | |
int fd = -1; | |
char buffer[20] = {0}; | |
ssize_t amt = 0; | |
memset(buffer, 0x0, sizeof(buffer)); | |
fd = open(path, O_RDWR); | |
if (fd >= 0) | |
{ | |
amt = read(fd, buffer, 1); | |
close(fd); | |
HDBD_LOG("[%s %d]read to <%s>, value is <%zd> \n", __FUNCTION__, __LINE__, path, amt); | |
return 0; | |
} | |
else | |
{ | |
HDBD_LOG("[%s %d]read failed to open <%s>, errno is <%d> \n", __FUNCTION__, __LINE__, path, errno); | |
} | |
return -1; | |
} | |
/** | |
* @brief Set serial port Para | |
* @param fd:file desc | |
* @param speed:baudrate | |
* @param flow_ctrl:flow control flag | |
* @param databits:data bits | |
* @param stopbits:stop bits | |
* @param parity:parity flag | |
* @retval SUCCESS/FAIL | |
*/ | |
int uart_set(int fd, int speed, int flow_ctrl, int databits, int stopbits, int parity) | |
{ | |
int i; | |
int speed_arr[11] = {B921600, B576000, B460800,B230400, B115200, B19200, B9600, B4800, B2400, B1200, B300}; | |
int name_arr[11] = {921600,576000,460800,230400, 115200, 19200, 9600, 4800, 2400, 1200, 300}; | |
struct termios options; | |
if ( tcgetattr( fd, &options) != 0) | |
{ | |
HDBD_LOG("[%s %d]get serial options Fail\n", __FUNCTION__, __LINE__); | |
return FAIL; | |
} | |
for ( i = 0; i < 11; i++) /* sizeof(speed_arr) / sizeof(int) */ | |
{ | |
if (speed == name_arr[i]) | |
{ | |
cfsetispeed(&options, speed_arr[i]); | |
cfsetospeed(&options, speed_arr[i]); | |
break; | |
} | |
} | |
options.c_cflag |= CLOCAL; | |
options.c_cflag |= CREAD; | |
switch (flow_ctrl) | |
{ | |
case 0 : | |
options.c_cflag &= ~CRTSCTS; | |
break; | |
case 1 : | |
options.c_cflag |= CRTSCTS; | |
break; | |
case 2 : | |
options.c_cflag |= IXON | IXOFF | IXANY; | |
break; | |
} | |
options.c_cflag &= ~CSIZE; | |
switch (databits) | |
{ | |
case 5 : | |
options.c_cflag |= CS5; | |
break; | |
case 6 : | |
options.c_cflag |= CS6; | |
break; | |
case 7 : | |
options.c_cflag |= CS7; | |
break; | |
case 8: | |
options.c_cflag |= CS8; | |
break; | |
default: | |
HDBD_LOG("[%s %d] Unsupported data size\n", __FUNCTION__, __LINE__); | |
return FAIL; | |
} | |
switch (parity) | |
{ | |
case 'n': | |
case 'N': | |
options.c_cflag &= ~PARENB; | |
options.c_iflag &= ~INPCK; | |
break; | |
case 'o': | |
case 'O': | |
options.c_cflag |= (PARODD | PARENB); | |
options.c_iflag |= INPCK; | |
break; | |
case 'e': | |
case 'E': | |
options.c_cflag |= PARENB; | |
options.c_cflag &= ~PARODD; | |
options.c_iflag |= INPCK; | |
break; | |
case 's': | |
case 'S': | |
options.c_cflag &= ~PARENB; | |
options.c_cflag &= ~CSTOPB; | |
break; | |
default: | |
HDBD_LOG("[%s %d] Unsupported parity\n", __FUNCTION__, __LINE__); | |
return FAIL; | |
} | |
switch (stopbits) | |
{ | |
case 1: | |
options.c_cflag &= ~CSTOPB; break; | |
case 2: | |
options.c_cflag |= CSTOPB; break; | |
default: | |
HDBD_LOG("[%s %d] Unsupported stop bits\n", __FUNCTION__, __LINE__); | |
return FAIL; | |
} | |
options.c_oflag &= ~OPOST; | |
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); | |
//options.c_lflag &= ~(ISIG | ICANON); | |
options.c_cc[VTIME] = 1; | |
options.c_cc[VMIN] = 1; | |
tcflush(fd, TCIFLUSH); | |
if (tcsetattr(fd, TCSANOW, &options) != 0) | |
{ | |
HDBD_LOG("[%s %d] com set error!\n", __FUNCTION__, __LINE__); | |
return FAIL; | |
} | |
return SUCCESS; | |
} | |
/** | |
* @brief Init serial port | |
* @param fd:file desc | |
* @param speed:baudrate | |
* @param flow_ctrl:flow control flag | |
* @param databits:data bits | |
* @param stopbits:stop bits | |
* @param parity:parity flag | |
* @retval SUCCESS/FAIL | |
*/ | |
int uart_init(int fd, int speed, int flow_ctrl, int databits, int stopbits, int parity) | |
{ | |
if (uart_set(fd, speed, flow_ctrl, databits, stopbits, parity) == FAIL) | |
{ | |
HDBD_LOG("[%s %d] Uart init false\n", __FUNCTION__, __LINE__); | |
return FAIL; | |
} | |
else | |
{ | |
return SUCCESS; | |
} | |
} | |
/** | |
* @brief Init serial port | |
* @param fd:uart fd | |
* @param selector:TCIOFLUSH/TCIFLUSH | |
*/ | |
void clearBuffer(int fd, int selector) | |
{ | |
tcflush(fd, selector); | |
} | |
/** | |
* @brief open serial port | |
* @param GPS_DEVICE:uart port | |
* @retval SUCCESS/FAIL | |
*/ | |
int uart_open(unsigned char * GPS_DEVICE) | |
{ | |
int fd = -1; | |
int uart_init_ret = -1; | |
//***************************************************************************** | |
fd = open((char *)GPS_DEVICE, O_RDWR|O_NOCTTY|O_NDELAY); | |
if( fd < 0) | |
{ | |
HDBD_LOG("[%s %d] : open port ERROR..state->fd=%d, errno=%d\n",__FUNCTION__, __LINE__, fd, errno); | |
return -1; | |
} | |
HDBD_LOG("[%s %d] : open port succceed..state->fd=%d OK\n", __FUNCTION__, __LINE__, fd); | |
/* set port */ | |
if(fcntl( fd,F_SETFL,0)<0) | |
{ | |
HDBD_LOG("[%s %d] : fcntl F_SETFL Fail\n", __FUNCTION__, __LINE__); | |
return -1; | |
} | |
tcflush(fd, TCIOFLUSH); | |
uart_init_ret = uart_init(fd, 115200, 0, 8, 1, 'N'); | |
if (-1 == uart_init_ret) | |
{ | |
HDBD_LOG("[%s %d] : uart_init_ret is <%d>, return -1\n", __FUNCTION__, __LINE__, uart_init_ret); | |
return -1; | |
} | |
HDBD_LOG("[%s %d] : Port setup finished..OK\n", __FUNCTION__, __LINE__); | |
//********************************************************************** | |
return fd; | |
} | |
int uart_close(int fd) | |
{ | |
close(fd); | |
return 0; | |
} | |
void SetOpt(int fd) | |
{ | |
static struct termios termold, termnew; | |
tcgetattr(fd, &termold); | |
bzero(&termnew, sizeof(termnew)); | |
termnew.c_iflag &= ~(ICRNL | IGNCR); | |
termnew.c_cflag |= CLOCAL | CREAD; //CLOCAL:忽略modem控制线 CREAD:打开接受者 | |
termnew.c_cflag &= ~CSIZE; | |
termnew.c_cflag |= CS8; | |
termnew.c_cflag &= ~CRTSCTS; | |
termnew.c_cflag &= ~PARENB; | |
cfsetispeed(&termnew, B115200); | |
cfsetospeed(&termnew, B115200); | |
termnew.c_cflag &= ~CSTOPB; | |
termnew.c_cc[VTIME] = 1; //VTIME:非cannoical模式读时的延时,以十分之一秒位单位 | |
termnew.c_cc[VMIN] = 0; //VMIN:非canonical模式读到最小字符数 | |
tcflush(fd, TCIFLUSH); | |
tcsetattr(fd, TCSANOW, &termnew); | |
} | |
/* | |
* band : 0->460800, 1->115200, 2->9600, other->115200 | |
*/ | |
int set_baudrate(int fd, uint8_t baud) | |
{ | |
static struct termios termold, termnew; | |
tcgetattr(fd, &termold); | |
bzero(&termnew, sizeof(termnew)); | |
termnew.c_iflag &= ~(ICRNL | IGNCR); | |
termnew.c_cflag |= CLOCAL | CREAD; //CLOCAL:忽略modem控制线 CREAD:打开接受者 | |
termnew.c_cflag &= ~CSIZE; | |
termnew.c_cflag |= CS8; | |
termnew.c_cflag &= ~CRTSCTS; | |
termnew.c_cflag &= ~PARENB; | |
if(baud == 1) | |
{ | |
cfsetispeed(&termnew, B460800); | |
cfsetospeed(&termnew, B460800); | |
} | |
else if(baud == 2) | |
{ | |
cfsetispeed(&termnew, B115200); | |
cfsetospeed(&termnew, B115200); | |
} | |
else if(baud) | |
{ | |
cfsetispeed(&termnew, B9600); | |
cfsetospeed(&termnew, B9600); | |
} | |
else | |
{ | |
cfsetispeed(&termnew, B115200); | |
cfsetospeed(&termnew, B115200); | |
} | |
termnew.c_cflag &= ~CSTOPB; | |
termnew.c_cc[VTIME] = 1; //VTIME:非cannoical模式读时的延时,以十分之一秒位单位 | |
termnew.c_cc[VMIN] = 0; //VMIN:非canonical模式读到最小字符数 | |
tcflush(fd, TCIFLUSH); | |
tcsetattr(fd, TCSANOW, &termnew); | |
return 0; | |
} | |
int OpenUart(const char* UART_DEV) | |
{ | |
int fd=0; | |
/*第1个参数:想要打开的文件路径名,或者文件名 | |
*第2个参数:open_Status:文件打开方式,可采用下面的文件打开模式: | |
O_RDONLY:以只读方式打开文件 | |
O_WRONLY:以只写方式打开文件 | |
O_RDWR:以读写方式打开文件 | |
O_APPEND:写入数据时添加到文件末尾 | |
O_CREATE:如果文件不存在则产生该文件,使用该标志需要设置访问权限位mode_t | |
O_EXCL:指定该标志,并且指定了O_CREATE标志,如果打开的文件存在则会产生一个错误 | |
O_TRUNC:如果文件存在并且成功以写或者只写方式打开,则清除文件所有内容,使得文件长度变为0 | |
O_NOCTTY:如果打开的是一个终端设备,这个程序不会成为对应这个端口的控制终端,如果没有该标志,任何一个输入,例如键盘中止信号等,都将影响进程。 | |
O_NONBLOCK:该标志与早期使用的O_NDELAY标志作用差不多。程序不关心DCD信号线的状态,如果指定该标志,进程将一直在休眠状态,直到DCD信号线为0。 | |
O_NONBLOCK和O_NDELAY所产生的结果都是使I/O变成非搁置模式(non-blocking),在读取不到数据或是写入缓冲区已满会马上return,而不会搁置程序动作,直到有数据或写入完成; | |
它们的差别在于设立O_NDELAY会使I/O函式马上回传0,但是又衍生出一个问题,因为读取到档案结尾时所回传的也是0,这样无法得知是哪中情况;因此,O_NONBLOCK就产生出来,它在读取不到数据时会回传-1,并且设置errno为EAGAIN。 | |
第3个参数:设置文件访问权限的初始值 | |
*/ | |
fd = open(UART_DEV , O_RDWR|O_NOCTTY); | |
if (fd < 0) | |
{ | |
return -1; | |
} | |
SetOpt(fd); | |
return fd; | |
} |