123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- /*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2017-12-06 JasonJia first version
- */
- #include <rtthread.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <string.h>
- #include <sys/time.h>
- #if defined (RT_USING_POSIX)
- #include <dfs_posix.h>
- #include <dfs_select.h>
- #if defined (RT_USING_POSIX_TERMIOS)
- #include <termios.h>
- #else
- #error "TERMIOS need RT_USING_POSIX_TERMIOS"
- #endif
- #else
- #error "POSIX poll/select need RT_USING_POSIX"
- #endif
- #define JOINT(x,y) x##y
- #define B(x) JOINT(B,x)
- #define Default_baud_rate 115200
- #define Default_parity 'n'
- #define BUFFER_SIZE 64
- struct termios_test_s
- {
- int baud_rate;
- const char *dev;
- };
- static struct termios_test_s term_param;
- static int _check_baud_rate(int baud_rate)
- {
- #define BAUD_RATE(x) \
- {\
- if(x==baud_rate) \
- {\
- rt_kprintf("%d baud rate\n",baud_rate);\
- return JOINT(B,x);\
- }\
- }
- BAUD_RATE(110);
- BAUD_RATE(200);
- BAUD_RATE(300);
- BAUD_RATE(600);
- BAUD_RATE(1200);
- BAUD_RATE(1800);
- BAUD_RATE(2400);
- BAUD_RATE(4800);
- BAUD_RATE(9600);
- BAUD_RATE(19200);
- BAUD_RATE(38400);
- BAUD_RATE(57600);
- BAUD_RATE(115200);
- BAUD_RATE(230400);
- BAUD_RATE(460800);
- BAUD_RATE(921600);
- rt_kprintf("%d is not support,use default %d value.\n",baud_rate,Default_baud_rate);
- return B(Default_baud_rate);
- }
- int open_comm(const char *name)
- {
- int fd;
- fd = open(name, O_RDWR | O_NOCTTY | O_NONBLOCK, 0);
- if(fd == -1)
- {
- rt_kprintf("Open %s fail.\n",name);
- return -1;
- }
- else
- {
- rt_kprintf("Open %s success,fd:%d\n",name,fd);
- }
- return fd;
- }
- void close_comm(int fd)
- {
- if(fd != -1)
- {
- close(fd);
- }
- }
- void config_comm(int fd, int speed_baud_rate, char parity, int data_bits, int stop_bits)
- {
- int valid_baud_rate = 0;
- struct termios new_tc;
- memset(&new_tc, 0x00, sizeof(struct termios));
- valid_baud_rate = _check_baud_rate(speed_baud_rate);
- new_tc.c_cflag |= (CLOCAL | CREAD);//Enable in default.
- /*
- *Set baud rate. e.g B115200 is 115200 bauds.
- */
- cfsetispeed(&new_tc, valid_baud_rate);//input speed
- cfsetospeed(&new_tc, valid_baud_rate);//output speed
- /*
- *Set parity.
- */
- switch(parity)
- {
- case 'n':
- case 'N':
- new_tc.c_cflag &= ~PARENB; //Disable parity.
- break;
- case 'o':
- case 'O':
- new_tc.c_cflag |= PARENB; //Enable parity.
- new_tc.c_cflag |= PARODD; //Odd parity.
- break;
- case 'e':
- case 'E':
- new_tc.c_cflag |= PARENB; //Enable parity.
- new_tc.c_cflag &= ~PARODD; //even parity.
- break;
- }
- /*
- *Set data bits.
- */
- new_tc.c_cflag &= ~CSIZE;
- switch(data_bits)
- {
- case 5:
- break;
- case 6:
- break;
- case 7:
- new_tc.c_cflag |= CS7;
- break;
- case 8:
- new_tc.c_cflag |= CS8;
- break;
- }
- /*
- *Set stop bits.
- */
- (stop_bits == 2)?(new_tc.c_cflag |= CSTOPB):(new_tc.c_cflag &= ~ CSTOPB);
- tcflush(fd,TCIFLUSH);
- //new_tc.c_cc[VTIME] = 0;
- //new_tc.c_cc[VMIN] = 1;
- if( tcsetattr(fd, TCSANOW, &new_tc) != 0)
- {
- rt_kprintf("Set port config fail!\n");
- }
- }
- int recv_comm(int fd, unsigned char *buffer, rt_size_t size, struct timeval *timeout)
- {
- struct timeval t;
- int ret = 0;
- rt_size_t drv_recved = 0;
- int recved = 0, need = size;
- int timeout_cnt = 0;
- unsigned char *c = RT_NULL;
- fd_set readSet;
- RT_ASSERT(RT_NULL != buffer);
- if(fd == -1)
- {
- return -1;
- }
- t.tv_sec = 0;
- t.tv_usec = 100000;
- if(RT_NULL == timeout)
- {
- /* Wait forever approximate, it's a large time. */
- timeout_cnt = 0xffffffff;
- }
- else
- {
- timeout_cnt = (timeout->tv_sec * 1000 * 1000 + timeout->tv_usec)/(t.tv_sec * 1000 * 1000 + t.tv_usec);
- }
- while(1)
- {
- FD_ZERO(&readSet);
- FD_SET(fd, &readSet);
- ret = select(fd+1,&readSet,RT_NULL,RT_NULL,&t);
- if(ret < 0)
- {
- rt_kprintf("select error %d\n",ret);
- break;
- }
- else if(ret == 0)
- {
- /* timeout */
- timeout_cnt--;
- if(timeout_cnt == 0)
- {
- rt_kprintf("need %d data in timeout %d ms,but only %d recved.\n",
- size,
- timeout->tv_sec * 1000 + timeout->tv_usec / 1000,
- recved);
- recved = 0;
- break;
- }
- }
- else
- {
- if(FD_ISSET(fd, &readSet))
- {
- c = &buffer[size - need];
- ioctl(fd, FIONREAD, &drv_recved);
- /* check poll and ioctl */
- RT_ASSERT(drv_recved != 0);
- drv_recved = (drv_recved > need ? need : drv_recved);
- recved = read(fd, c, drv_recved);
- if(recved != drv_recved)
- {
- rt_kprintf("fatal error %s(%d).\n",__FUNCTION__,__LINE__);
- RT_ASSERT(0);
- recved = 0;
- break;
- }
- need -= recved;
- if(need)
- {
- continue;
- }
- else if (need == 0)
- {
- recved = size;
- break;
- }
- else
- {
- rt_kprintf("fatal error %s(%d).\n",__FUNCTION__,__LINE__);
- RT_ASSERT(0);
- }
- }
- }
- }
- return recved;
- }
- int send_comm(int fd, const unsigned char *buffer, rt_size_t size)
- {
- RT_ASSERT(RT_NULL != buffer);
- if(fd == -1)
- {
- return -1;
- }
- //serial framework does not support poll out now
- write(fd, buffer, size);
- return 0;
- }
- int flush_comm(int fd)
- {
- if(fd == -1)
- {
- return -1;
- }
- tcflush(fd,TCIFLUSH);
- return 0;
- }
- void termios_test_entry(void *p)
- {
- int len = 0;
- int fd = -1;
- unsigned char *pBuf = RT_NULL;
- struct termios_test_s *pTerm = (struct termios_test_s *)p;
- if((fd = open_comm(pTerm->dev)) == -1)
- {
- rt_kprintf("Check the device name...\n");
- return;
- }
- pBuf = (unsigned char *)rt_malloc(BUFFER_SIZE);
- RT_ASSERT(pBuf != RT_NULL);
- memset(pBuf, 0x00, BUFFER_SIZE);
- config_comm(fd, pTerm->baud_rate, Default_parity, 8, 1);
- flush_comm(fd);
- rt_kprintf("Block recv 10 bytes.\n");
- /* Block recv 10 bytes */
- len = recv_comm(fd, pBuf, 10, RT_NULL);
- rt_kprintf("Recv:%s\n", pBuf);
- send_comm(fd, pBuf, len);
- rt_kprintf("Termios test exit.\n");
- close_comm(fd);
- rt_free(pBuf);
- pBuf = RT_NULL;
- }
- int termios_test(int argc, char **argv)
- {
- rt_thread_t tid;
- if(argc < 2)
- {
- rt_kprintf("Please input device name...\n");
- return -1;
- }
- term_param.dev = argv[1];
- term_param.baud_rate = ((argc >= 3) ? atoi(argv[2]) : Default_baud_rate);
- tid = rt_thread_create("termtest",
- termios_test_entry, (void *)&term_param,
- 512, RT_THREAD_PRIORITY_MAX/3, 20);
- if (tid != RT_NULL)
- rt_thread_startup(tid);
- return 0;
- }
- #ifdef RT_USING_FINSH
- #include <finsh.h>
- #ifdef FINSH_USING_MSH
- MSH_CMD_EXPORT_ALIAS(termios_test, termtest, e.g: termtest /dev/uart4 115200);
- #endif /* FINSH_USING_MSH */
- #endif /* RT_USING_FINSH */
|