b.liu | 778645e | 2024-06-21 16:47:42 +0800 | [diff] [blame] | 1 |
|
| 2 | #include "port.h"
|
| 3 |
|
| 4 | /**
|
| 5 | * @brief Send Data to serial port
|
| 6 | * @param fd:file desc
|
| 7 | * @param cmd:data pointer
|
| 8 | * @param cmd_len:data length
|
| 9 | * @retval SUCCESS/FAIL
|
| 10 | */
|
| 11 | int uart_send(int fd, const uint8_t *cmd, int cmd_len)
|
| 12 | {
|
| 13 | int ret = FAIL;
|
| 14 |
|
| 15 | ret = write(fd, cmd, cmd_len);
|
| 16 | if(ret < 0)
|
| 17 | {
|
| 18 | HDBD_LOG("[%s %d]write port failed,ret: %d\n", __FUNCTION__, __LINE__, ret);
|
| 19 | return FAIL;
|
| 20 | }
|
| 21 |
|
| 22 | return SUCCESS;
|
| 23 | }
|
| 24 |
|
| 25 |
|
| 26 | /**
|
| 27 | * @brief Receive data from serial port0
|
| 28 | * @param fd:file desc
|
| 29 | * @param buf:receive buffer
|
| 30 | * @param actual_length:receive data length
|
| 31 | * @param timeout:para of timeout
|
| 32 | * @retval SUCCESS/FAIL
|
| 33 | */
|
| 34 | int uart_recv(int fd, uint8_t *buf, int *actual_length, int timeout)
|
| 35 | {
|
| 36 | int ret;
|
| 37 | int temp = 0;
|
| 38 | int len = *actual_length;
|
| 39 | uint8_t tempBuf[128] = {0};
|
| 40 | int errorCount = 0;
|
| 41 | fd_set rd;
|
| 42 | struct timeval tv;
|
| 43 | tv.tv_sec = timeout;
|
| 44 | tv.tv_usec = 0;
|
| 45 |
|
| 46 | FD_ZERO(&rd);
|
| 47 | FD_SET(fd, &rd);
|
| 48 | *actual_length = 0;
|
| 49 | HDBD_LOG("[%s %d] len:%d\n", __FUNCTION__, __LINE__, len);
|
| 50 | while(1)
|
| 51 | {
|
| 52 | ret = select(fd + 1, &rd, NULL, NULL, &tv);
|
| 53 | if(ret > 0){
|
| 54 | if (FD_ISSET(fd, &rd)) {
|
| 55 | temp = read(fd, tempBuf, 128);
|
| 56 | if(temp > 0)
|
| 57 | {
|
| 58 | errorCount = 0;
|
| 59 | if((*actual_length + temp) <= len)
|
| 60 | {
|
| 61 | memcpy(buf+*actual_length, tempBuf, temp);
|
| 62 | *actual_length += temp;
|
| 63 | }
|
| 64 | else
|
| 65 | {
|
| 66 | memcpy(buf+*actual_length, tempBuf, (len - *actual_length));
|
| 67 | *actual_length = len;
|
| 68 | }
|
| 69 | }
|
| 70 | else
|
| 71 | {
|
| 72 | errorCount++;
|
| 73 | }
|
| 74 | HDBD_LOG("[%s %d]len:%d, *actual_length:%d, temp:%d\n", __FUNCTION__, __LINE__, len, *actual_length, temp);
|
| 75 | }
|
| 76 | }
|
| 77 | else if(ret == 0)
|
| 78 | {
|
| 79 | HDBD_LOG("[%s %d]timeout\n", __FUNCTION__, __LINE__);
|
| 80 | if(*actual_length <= 2)
|
| 81 | {
|
| 82 | goto ERR1;
|
| 83 | }
|
| 84 | else
|
| 85 | {
|
| 86 | break;
|
| 87 | }
|
| 88 | }
|
| 89 | else
|
| 90 | {
|
| 91 | HDBD_LOG("[%s %d] select error!\n", __FUNCTION__, __LINE__);
|
| 92 | goto ERR1;
|
| 93 | }
|
| 94 |
|
| 95 | if((*actual_length >= len) || (errorCount >= 5))
|
| 96 | {
|
| 97 | HDBD_LOG("[%s %d]*actual_length:%d, recv sucess,break\n", __FUNCTION__, __LINE__, *actual_length);
|
| 98 | break;
|
| 99 | }
|
| 100 |
|
| 101 | }
|
| 102 |
|
| 103 | HDBD_LOG("[%s %d]*actual_length:%d, ret:%d\n", __FUNCTION__, __LINE__, *actual_length, ret);
|
| 104 | return SUCCESS;
|
| 105 |
|
| 106 | ERR1:
|
| 107 | return FAIL;
|
| 108 | }
|
| 109 |
|
| 110 | int UartRead(int fd, uint8_t *RxBuff, long RxLen)
|
| 111 | {
|
| 112 | #if 1
|
| 113 | int GetRxLen=0;
|
| 114 | int index;
|
| 115 | while(RxLen){
|
| 116 | //printf("RxLen=%d\r\n", RxLen);
|
| 117 | index = read(fd, RxBuff+GetRxLen, 1);
|
| 118 | //printf("index=%d\r\n", index);
|
| 119 | GetRxLen += index;
|
| 120 | //printf("GetRxLen=%d\r\n", GetRxLen);
|
| 121 | RxLen--;
|
| 122 | //printf("RxLen=%d\r\n", RxLen);
|
| 123 | if(index == 0)
|
| 124 | {
|
| 125 | return GetRxLen;
|
| 126 | }
|
| 127 | }
|
| 128 |
|
| 129 | return GetRxLen ;
|
| 130 | #else
|
| 131 | int GetRxLen=0;
|
| 132 | while(RxLen){
|
| 133 | //printf("[RxLen=%ld]\r\n", RxLen);
|
| 134 | GetRxLen += read(fd, RxBuff+GetRxLen, 1);
|
| 135 | RxLen--;
|
| 136 | }
|
| 137 |
|
| 138 | return GetRxLen ;
|
| 139 | #endif
|
| 140 | }
|
| 141 |
|
| 142 | /**
|
| 143 | * @brief Write gpio node
|
| 144 | * @param path:path of gpio node
|
| 145 | * @param value:'1' or '0'
|
| 146 | * @retval SUCCESS/FAIL
|
| 147 | */
|
| 148 | int write_gpio(char const* path, int value)
|
| 149 | {
|
| 150 | int fd = -1;
|
| 151 | char buffer[20] = {0};
|
| 152 | int bytes = 0;
|
| 153 | ssize_t amt = 0;
|
| 154 |
|
| 155 | memset(buffer, 0x0, sizeof(buffer));
|
| 156 | fd = open(path, O_RDWR);
|
| 157 |
|
| 158 | if (fd >= 0)
|
| 159 | {
|
| 160 | bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);
|
| 161 | amt = write(fd, buffer, (size_t)bytes);
|
| 162 | close(fd);
|
| 163 | return amt == -1 ? -errno : 0;
|
| 164 | }
|
| 165 | else
|
| 166 | {
|
| 167 | HDBD_LOG("[%s %d]write_int failed to open %s, errno is %d \n", __FUNCTION__, __LINE__, path, errno);
|
| 168 | }
|
| 169 |
|
| 170 | return -errno;
|
| 171 | }
|
| 172 |
|
| 173 | /**
|
| 174 | * @brief Read gpio node
|
| 175 | * @param path:path of gpio node
|
| 176 | * @param value:'1' or '0'
|
| 177 | * @retval SUCCESS/FAIL
|
| 178 | */
|
| 179 | int read_gpio(char const* path)
|
| 180 | {
|
| 181 | int fd = -1;
|
| 182 | char buffer[20] = {0};
|
| 183 | ssize_t amt = 0;
|
| 184 |
|
| 185 | memset(buffer, 0x0, sizeof(buffer));
|
| 186 | fd = open(path, O_RDWR);
|
| 187 |
|
| 188 | if (fd >= 0)
|
| 189 | {
|
| 190 | amt = read(fd, buffer, 1);
|
| 191 | close(fd);
|
| 192 | HDBD_LOG("[%s %d]read to <%s>, value is <%zd> \n", __FUNCTION__, __LINE__, path, amt);
|
| 193 | return 0;
|
| 194 | }
|
| 195 | else
|
| 196 | {
|
| 197 | HDBD_LOG("[%s %d]read failed to open <%s>, errno is <%d> \n", __FUNCTION__, __LINE__, path, errno);
|
| 198 | }
|
| 199 |
|
| 200 | return -1;
|
| 201 | }
|
| 202 |
|
| 203 | /**
|
| 204 | * @brief Set serial port Para
|
| 205 | * @param fd:file desc
|
| 206 | * @param speed:baudrate
|
| 207 | * @param flow_ctrl:flow control flag
|
| 208 | * @param databits:data bits
|
| 209 | * @param stopbits:stop bits
|
| 210 | * @param parity:parity flag
|
| 211 | * @retval SUCCESS/FAIL
|
| 212 | */
|
| 213 | int uart_set(int fd, int speed, int flow_ctrl, int databits, int stopbits, int parity)
|
| 214 | {
|
| 215 | int i;
|
| 216 | int speed_arr[11] = {B921600, B576000, B460800,B230400, B115200, B19200, B9600, B4800, B2400, B1200, B300};
|
| 217 | int name_arr[11] = {921600,576000,460800,230400, 115200, 19200, 9600, 4800, 2400, 1200, 300};
|
| 218 |
|
| 219 | struct termios options;
|
| 220 |
|
| 221 | if ( tcgetattr( fd, &options) != 0)
|
| 222 | {
|
| 223 | HDBD_LOG("[%s %d]get serial options Fail\n", __FUNCTION__, __LINE__);
|
| 224 | return FAIL;
|
| 225 | }
|
| 226 |
|
| 227 | for ( i = 0; i < 11; i++) /* sizeof(speed_arr) / sizeof(int) */
|
| 228 | {
|
| 229 | if (speed == name_arr[i])
|
| 230 | {
|
| 231 | cfsetispeed(&options, speed_arr[i]);
|
| 232 | cfsetospeed(&options, speed_arr[i]);
|
| 233 | break;
|
| 234 | }
|
| 235 | }
|
| 236 |
|
| 237 | options.c_cflag |= CLOCAL;
|
| 238 | options.c_cflag |= CREAD;
|
| 239 |
|
| 240 | switch (flow_ctrl)
|
| 241 | {
|
| 242 |
|
| 243 | case 0 :
|
| 244 | options.c_cflag &= ~CRTSCTS;
|
| 245 | break;
|
| 246 |
|
| 247 | case 1 :
|
| 248 | options.c_cflag |= CRTSCTS;
|
| 249 | break;
|
| 250 | case 2 :
|
| 251 | options.c_cflag |= IXON | IXOFF | IXANY;
|
| 252 | break;
|
| 253 | }
|
| 254 |
|
| 255 | options.c_cflag &= ~CSIZE;
|
| 256 | switch (databits)
|
| 257 | {
|
| 258 | case 5 :
|
| 259 | options.c_cflag |= CS5;
|
| 260 | break;
|
| 261 | case 6 :
|
| 262 | options.c_cflag |= CS6;
|
| 263 | break;
|
| 264 | case 7 :
|
| 265 | options.c_cflag |= CS7;
|
| 266 | break;
|
| 267 | case 8:
|
| 268 | options.c_cflag |= CS8;
|
| 269 | break;
|
| 270 | default:
|
| 271 | HDBD_LOG("[%s %d] Unsupported data size\n", __FUNCTION__, __LINE__);
|
| 272 | return FAIL;
|
| 273 | }
|
| 274 |
|
| 275 | switch (parity)
|
| 276 | {
|
| 277 | case 'n':
|
| 278 | case 'N':
|
| 279 | options.c_cflag &= ~PARENB;
|
| 280 | options.c_iflag &= ~INPCK;
|
| 281 | break;
|
| 282 | case 'o':
|
| 283 | case 'O':
|
| 284 | options.c_cflag |= (PARODD | PARENB);
|
| 285 | options.c_iflag |= INPCK;
|
| 286 | break;
|
| 287 | case 'e':
|
| 288 | case 'E':
|
| 289 | options.c_cflag |= PARENB;
|
| 290 | options.c_cflag &= ~PARODD;
|
| 291 | options.c_iflag |= INPCK;
|
| 292 | break;
|
| 293 | case 's':
|
| 294 | case 'S':
|
| 295 | options.c_cflag &= ~PARENB;
|
| 296 | options.c_cflag &= ~CSTOPB;
|
| 297 | break;
|
| 298 | default:
|
| 299 | HDBD_LOG("[%s %d] Unsupported parity\n", __FUNCTION__, __LINE__);
|
| 300 | return FAIL;
|
| 301 | }
|
| 302 |
|
| 303 | switch (stopbits)
|
| 304 | {
|
| 305 | case 1:
|
| 306 | options.c_cflag &= ~CSTOPB; break;
|
| 307 | case 2:
|
| 308 | options.c_cflag |= CSTOPB; break;
|
| 309 | default:
|
| 310 | HDBD_LOG("[%s %d] Unsupported stop bits\n", __FUNCTION__, __LINE__);
|
| 311 | return FAIL;
|
| 312 | }
|
| 313 |
|
| 314 | options.c_oflag &= ~OPOST;
|
| 315 | options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
|
| 316 | //options.c_lflag &= ~(ISIG | ICANON);
|
| 317 | options.c_cc[VTIME] = 1;
|
| 318 | options.c_cc[VMIN] = 1;
|
| 319 | tcflush(fd, TCIFLUSH);
|
| 320 |
|
| 321 | if (tcsetattr(fd, TCSANOW, &options) != 0)
|
| 322 | {
|
| 323 | HDBD_LOG("[%s %d] com set error!\n", __FUNCTION__, __LINE__);
|
| 324 | return FAIL;
|
| 325 | }
|
| 326 |
|
| 327 | return SUCCESS;
|
| 328 | }
|
| 329 |
|
| 330 | /**
|
| 331 | * @brief Init serial port
|
| 332 | * @param fd:file desc
|
| 333 | * @param speed:baudrate
|
| 334 | * @param flow_ctrl:flow control flag
|
| 335 | * @param databits:data bits
|
| 336 | * @param stopbits:stop bits
|
| 337 | * @param parity:parity flag
|
| 338 | * @retval SUCCESS/FAIL
|
| 339 | */
|
| 340 | int uart_init(int fd, int speed, int flow_ctrl, int databits, int stopbits, int parity)
|
| 341 | {
|
| 342 | if (uart_set(fd, speed, flow_ctrl, databits, stopbits, parity) == FAIL)
|
| 343 | {
|
| 344 | HDBD_LOG("[%s %d] Uart init false\n", __FUNCTION__, __LINE__);
|
| 345 | return FAIL;
|
| 346 | }
|
| 347 | else
|
| 348 | {
|
| 349 | return SUCCESS;
|
| 350 | }
|
| 351 | }
|
| 352 |
|
| 353 | /**
|
| 354 | * @brief Init serial port
|
| 355 | * @param fd:uart fd
|
| 356 | * @param selector:TCIOFLUSH/TCIFLUSH
|
| 357 | */
|
| 358 | void clearBuffer(int fd, int selector)
|
| 359 | {
|
| 360 | tcflush(fd, selector);
|
| 361 | }
|
| 362 |
|
| 363 | /**
|
| 364 | * @brief open serial port
|
| 365 | * @param GPS_DEVICE:uart port
|
| 366 | * @retval SUCCESS/FAIL
|
| 367 | */
|
| 368 | int uart_open(unsigned char * GPS_DEVICE)
|
| 369 | {
|
| 370 | int fd = -1;
|
| 371 | int uart_init_ret = -1;
|
| 372 | //*****************************************************************************
|
| 373 | fd = open((char *)GPS_DEVICE, O_RDWR|O_NOCTTY|O_NDELAY);
|
| 374 |
|
| 375 | if( fd < 0)
|
| 376 | {
|
| 377 | HDBD_LOG("[%s %d] : open port ERROR..state->fd=%d, errno=%d\n",__FUNCTION__, __LINE__, fd, errno);
|
| 378 | return -1;
|
| 379 | }
|
| 380 |
|
| 381 | HDBD_LOG("[%s %d] : open port succceed..state->fd=%d OK\n", __FUNCTION__, __LINE__, fd);
|
| 382 |
|
| 383 | /* set port */
|
| 384 | if(fcntl( fd,F_SETFL,0)<0)
|
| 385 | {
|
| 386 | HDBD_LOG("[%s %d] : fcntl F_SETFL Fail\n", __FUNCTION__, __LINE__);
|
| 387 | return -1;
|
| 388 | }
|
| 389 |
|
| 390 | tcflush(fd, TCIOFLUSH);
|
| 391 |
|
| 392 | uart_init_ret = uart_init(fd, 115200, 0, 8, 1, 'N');
|
| 393 | if (-1 == uart_init_ret)
|
| 394 | {
|
| 395 | HDBD_LOG("[%s %d] : uart_init_ret is <%d>, return -1\n", __FUNCTION__, __LINE__, uart_init_ret);
|
| 396 | return -1;
|
| 397 | }
|
| 398 |
|
| 399 | HDBD_LOG("[%s %d] : Port setup finished..OK\n", __FUNCTION__, __LINE__);
|
| 400 | //**********************************************************************
|
| 401 | return fd;
|
| 402 | }
|
| 403 |
|
| 404 | int uart_close(int fd)
|
| 405 | {
|
| 406 | close(fd);
|
| 407 | return 0;
|
| 408 | }
|
| 409 |
|
| 410 |
|
| 411 | void SetOpt(int fd)
|
| 412 | {
|
| 413 | static struct termios termold, termnew;
|
| 414 | tcgetattr(fd, &termold);
|
| 415 | bzero(&termnew, sizeof(termnew));
|
| 416 |
|
| 417 | termnew.c_iflag &= ~(ICRNL | IGNCR);
|
| 418 | termnew.c_cflag |= CLOCAL | CREAD; //CLOCAL:忽略modem控制线 CREAD:打开接受者
|
| 419 | termnew.c_cflag &= ~CSIZE;
|
| 420 | termnew.c_cflag |= CS8;
|
| 421 | termnew.c_cflag &= ~CRTSCTS;
|
| 422 | termnew.c_cflag &= ~PARENB;
|
| 423 |
|
| 424 | cfsetispeed(&termnew, B115200);
|
| 425 | cfsetospeed(&termnew, B115200);
|
| 426 |
|
| 427 | termnew.c_cflag &= ~CSTOPB;
|
| 428 | termnew.c_cc[VTIME] = 1; //VTIME:非cannoical模式读时的延时,以十分之一秒位单位
|
| 429 | termnew.c_cc[VMIN] = 0; //VMIN:非canonical模式读到最小字符数
|
| 430 | tcflush(fd, TCIFLUSH);
|
| 431 | tcsetattr(fd, TCSANOW, &termnew);
|
| 432 | }
|
| 433 |
|
| 434 | /*
|
| 435 | * band : 0->460800, 1->115200, 2->9600, other->115200
|
| 436 | */
|
| 437 | int set_baudrate(int fd, uint8_t baud)
|
| 438 | {
|
| 439 | static struct termios termold, termnew;
|
| 440 | tcgetattr(fd, &termold);
|
| 441 | bzero(&termnew, sizeof(termnew));
|
| 442 |
|
| 443 | termnew.c_iflag &= ~(ICRNL | IGNCR);
|
| 444 | termnew.c_cflag |= CLOCAL | CREAD; //CLOCAL:忽略modem控制线 CREAD:打开接受者
|
| 445 | termnew.c_cflag &= ~CSIZE;
|
| 446 | termnew.c_cflag |= CS8;
|
| 447 | termnew.c_cflag &= ~CRTSCTS;
|
| 448 | termnew.c_cflag &= ~PARENB;
|
| 449 |
|
| 450 | if(baud == 1)
|
| 451 | {
|
| 452 | cfsetispeed(&termnew, B460800);
|
| 453 | cfsetospeed(&termnew, B460800);
|
| 454 | }
|
| 455 | else if(baud == 2)
|
| 456 | {
|
| 457 | cfsetispeed(&termnew, B115200);
|
| 458 | cfsetospeed(&termnew, B115200);
|
| 459 | }
|
| 460 | else if(baud)
|
| 461 | {
|
| 462 | cfsetispeed(&termnew, B9600);
|
| 463 | cfsetospeed(&termnew, B9600);
|
| 464 | }
|
| 465 | else
|
| 466 | {
|
| 467 | cfsetispeed(&termnew, B115200);
|
| 468 | cfsetospeed(&termnew, B115200);
|
| 469 | }
|
| 470 | termnew.c_cflag &= ~CSTOPB;
|
| 471 | termnew.c_cc[VTIME] = 1; //VTIME:非cannoical模式读时的延时,以十分之一秒位单位
|
| 472 | termnew.c_cc[VMIN] = 0; //VMIN:非canonical模式读到最小字符数
|
| 473 | tcflush(fd, TCIFLUSH);
|
| 474 | tcsetattr(fd, TCSANOW, &termnew);
|
| 475 | return 0;
|
| 476 | }
|
| 477 |
|
b.liu | 9e8584b | 2024-11-06 19:21:28 +0800 | [diff] [blame^] | 478 | int OpenUart(const char* UART_DEV)
|
b.liu | 778645e | 2024-06-21 16:47:42 +0800 | [diff] [blame] | 479 | {
|
| 480 | int fd=0;
|
| 481 |
|
| 482 | /*第1个参数:想要打开的文件路径名,或者文件名
|
| 483 | *第2个参数:open_Status:文件打开方式,可采用下面的文件打开模式:
|
| 484 | O_RDONLY:以只读方式打开文件
|
| 485 | O_WRONLY:以只写方式打开文件
|
| 486 | O_RDWR:以读写方式打开文件
|
| 487 | O_APPEND:写入数据时添加到文件末尾
|
| 488 | O_CREATE:如果文件不存在则产生该文件,使用该标志需要设置访问权限位mode_t
|
| 489 | O_EXCL:指定该标志,并且指定了O_CREATE标志,如果打开的文件存在则会产生一个错误
|
| 490 | O_TRUNC:如果文件存在并且成功以写或者只写方式打开,则清除文件所有内容,使得文件长度变为0
|
| 491 | O_NOCTTY:如果打开的是一个终端设备,这个程序不会成为对应这个端口的控制终端,如果没有该标志,任何一个输入,例如键盘中止信号等,都将影响进程。
|
| 492 | O_NONBLOCK:该标志与早期使用的O_NDELAY标志作用差不多。程序不关心DCD信号线的状态,如果指定该标志,进程将一直在休眠状态,直到DCD信号线为0。
|
| 493 | O_NONBLOCK和O_NDELAY所产生的结果都是使I/O变成非搁置模式(non-blocking),在读取不到数据或是写入缓冲区已满会马上return,而不会搁置程序动作,直到有数据或写入完成;
|
| 494 | 它们的差别在于设立O_NDELAY会使I/O函式马上回传0,但是又衍生出一个问题,因为读取到档案结尾时所回传的也是0,这样无法得知是哪中情况;因此,O_NONBLOCK就产生出来,它在读取不到数据时会回传-1,并且设置errno为EAGAIN。
|
| 495 | 第3个参数:设置文件访问权限的初始值
|
| 496 | */
|
| 497 | fd = open(UART_DEV , O_RDWR|O_NOCTTY);
|
| 498 | if (fd < 0)
|
| 499 | {
|
| 500 | return -1;
|
| 501 | }
|
| 502 | SetOpt(fd);
|
| 503 | return fd;
|
| 504 | }
|