1 /* 2 * termios_test.c 3 * 4 * Created on: 2017-12-06 5 * Author: JasonJia 6 */ 7 8 #include <rtthread.h> 9 #include <unistd.h> 10 #include <fcntl.h> 11 #include <string.h> 12 #include <sys/time.h> 13 14 #if defined (RT_USING_POSIX) 15 #include <dfs_posix.h> 16 #include <dfs_select.h> 17 #if defined (RT_USING_POSIX_TERMIOS) 18 #include <termios.h> 19 #else 20 #error "TERMIOS need RT_USING_POSIX_TERMIOS" 21 #endif 22 #else 23 #error "POSIX poll/select need RT_USING_POSIX" 24 #endif 25 26 #define JOINT(x,y) x##y 27 #define B(x) JOINT(B,x) 28 #define Default_baud_rate 115200 29 #define Default_parity 'n' 30 #define BUFFER_SIZE 64 31 32 struct termios_test_s 33 { 34 int baud_rate; 35 const char *dev; 36 }; 37 38 static struct termios_test_s term_param; 39 40 static int _check_baud_rate(int baud_rate) 41 { 42 #define BAUD_RATE(x) \ 43 {\ 44 if(x==baud_rate) \ 45 {\ 46 rt_kprintf("%d baud rate\n",baud_rate);\ 47 return JOINT(B,x);\ 48 }\ 49 } 50 BAUD_RATE(110); 51 BAUD_RATE(200); 52 BAUD_RATE(300); 53 BAUD_RATE(600); 54 BAUD_RATE(1200); 55 BAUD_RATE(1800); 56 BAUD_RATE(2400); 57 BAUD_RATE(4800); 58 BAUD_RATE(9600); 59 BAUD_RATE(19200); 60 BAUD_RATE(38400); 61 BAUD_RATE(57600); 62 BAUD_RATE(115200); 63 BAUD_RATE(230400); 64 BAUD_RATE(460800); 65 BAUD_RATE(921600); 66 67 rt_kprintf("%d is not support,use default %d value.\n",baud_rate,Default_baud_rate); 68 return B(Default_baud_rate); 69 } 70 71 int open_comm(const char *name) 72 { 73 int fd; 74 fd = open(name, O_RDWR | O_NOCTTY | O_NONBLOCK, 0); 75 if(fd == -1) 76 { 77 rt_kprintf("Open %s fail.\n",name); 78 return -1; 79 } 80 else 81 { 82 rt_kprintf("Open %s success,fd:%d\n",name,fd); 83 } 84 85 return fd; 86 } 87 88 void close_comm(int fd) 89 { 90 if(fd != -1) 91 { 92 close(fd); 93 } 94 } 95 96 void config_comm(int fd, int speed_baud_rate, char parity, int data_bits, int stop_bits) 97 { 98 int valid_baud_rate = 0; 99 struct termios new_tc; 100 101 memset(&new_tc, 0x00, sizeof(struct termios)); 102 103 valid_baud_rate = _check_baud_rate(speed_baud_rate); 104 105 new_tc.c_cflag |= (CLOCAL | CREAD);//Enable in default. 106 107 /* 108 *Set baud rate. e.g B115200 is 115200 bauds. 109 */ 110 cfsetispeed(&new_tc, valid_baud_rate);//input speed 111 cfsetospeed(&new_tc, valid_baud_rate);//output speed 112 113 /* 114 *Set parity. 115 */ 116 switch(parity) 117 { 118 case 'n': 119 case 'N': 120 new_tc.c_cflag &= ~PARENB; //Disable parity. 121 break; 122 case 'o': 123 case 'O': 124 new_tc.c_cflag |= PARENB; //Enable parity. 125 new_tc.c_cflag |= PARODD; //Odd parity. 126 break; 127 case 'e': 128 case 'E': 129 new_tc.c_cflag |= PARENB; //Enable parity. 130 new_tc.c_cflag &= ~PARODD; //even parity. 131 break; 132 } 133 134 /* 135 *Set data bits. 136 */ 137 new_tc.c_cflag &= ~CSIZE; 138 switch(data_bits) 139 { 140 case 5: 141 break; 142 case 6: 143 break; 144 case 7: 145 new_tc.c_cflag |= CS7; 146 break; 147 case 8: 148 new_tc.c_cflag |= CS8; 149 break; 150 } 151 152 /* 153 *Set stop bits. 154 */ 155 (stop_bits == 2)?(new_tc.c_cflag |= CSTOPB):(new_tc.c_cflag &= ~ CSTOPB); 156 157 tcflush(fd,TCIFLUSH); 158 //new_tc.c_cc[VTIME] = 0; 159 //new_tc.c_cc[VMIN] = 1; 160 161 if( tcsetattr(fd, TCSANOW, &new_tc) != 0) 162 { 163 rt_kprintf("Set port config fail!\n"); 164 } 165 } 166 167 int recv_comm(int fd, unsigned char *buffer, rt_size_t size, struct timeval *timeout) 168 { 169 struct timeval t; 170 int ret = 0; 171 rt_size_t drv_recved = 0; 172 int recved = 0, need = size; 173 int timeout_cnt = 0; 174 unsigned char *c = RT_NULL; 175 fd_set readSet; 176 177 RT_ASSERT(RT_NULL != buffer); 178 179 if(fd == -1) 180 { 181 return -1; 182 } 183 184 t.tv_sec = 0; 185 t.tv_usec = 100000; 186 187 if(RT_NULL == timeout) 188 { 189 /* Wait forever approximate, it's a large time. */ 190 timeout_cnt = 0xffffffff; 191 } 192 else 193 { 194 timeout_cnt = (timeout->tv_sec * 1000 * 1000 + timeout->tv_usec)/(t.tv_sec * 1000 * 1000 + t.tv_usec); 195 } 196 197 while(1) 198 { 199 FD_ZERO(&readSet); 200 FD_SET(fd, &readSet); 201 202 ret = select(fd+1,&readSet,RT_NULL,RT_NULL,&t); 203 if(ret < 0) 204 { 205 rt_kprintf("select error %d\n",ret); 206 break; 207 } 208 else if(ret == 0) 209 { 210 /* timeout */ 211 timeout_cnt--; 212 213 if(timeout_cnt == 0) 214 { 215 rt_kprintf("need %d data in timeout %d ms,but only %d recved.\n", 216 size, 217 timeout->tv_sec * 1000 + timeout->tv_usec / 1000, 218 recved); 219 220 recved = 0; 221 222 break; 223 } 224 } 225 else 226 { 227 if(FD_ISSET(fd, &readSet)) 228 { 229 c = &buffer[size - need]; 230 ioctl(fd, FIONREAD, &drv_recved); 231 232 /* check poll and ioctl */ 233 RT_ASSERT(drv_recved != 0); 234 235 drv_recved = (drv_recved > need ? need : drv_recved); 236 recved = read(fd, c, drv_recved); 237 if(recved != drv_recved) 238 { 239 rt_kprintf("fatal error %s(%d).\n",__FUNCTION__,__LINE__); 240 RT_ASSERT(0); 241 recved = 0; 242 break; 243 } 244 245 need -= recved; 246 247 if(need) 248 { 249 continue; 250 } 251 else if (need == 0) 252 { 253 recved = size; 254 break; 255 } 256 else 257 { 258 rt_kprintf("fatal error %s(%d).\n",__FUNCTION__,__LINE__); 259 RT_ASSERT(0); 260 } 261 262 } 263 } 264 } 265 266 return recved; 267 } 268 269 int send_comm(int fd, const unsigned char *buffer, rt_size_t size) 270 { 271 RT_ASSERT(RT_NULL != buffer); 272 273 if(fd == -1) 274 { 275 return -1; 276 } 277 278 //serial framework does not support poll out now 279 write(fd, buffer, size); 280 281 return 0; 282 } 283 284 int flush_comm(int fd) 285 { 286 if(fd == -1) 287 { 288 return -1; 289 } 290 tcflush(fd,TCIFLUSH); 291 return 0; 292 } 293 294 void termios_test_entry(void *p) 295 { 296 int len = 0; 297 int fd = -1; 298 unsigned char *pBuf = RT_NULL; 299 struct termios_test_s *pTerm = (struct termios_test_s *)p; 300 301 if((fd = open_comm(pTerm->dev)) == -1) 302 { 303 rt_kprintf("Check the device name...\n"); 304 return; 305 } 306 307 pBuf = (unsigned char *)rt_malloc(BUFFER_SIZE); 308 RT_ASSERT(pBuf != RT_NULL); 309 310 memset(pBuf, 0x00, BUFFER_SIZE); 311 312 config_comm(fd, pTerm->baud_rate, Default_parity, 8, 1); 313 314 flush_comm(fd); 315 316 rt_kprintf("Block recv 10 bytes.\n"); 317 /* Block recv 10 bytes */ 318 len = recv_comm(fd, pBuf, 10, RT_NULL); 319 320 rt_kprintf("Recv:%s\n", pBuf); 321 322 send_comm(fd, pBuf, len); 323 rt_kprintf("Termios test exit.\n"); 324 325 close_comm(fd); 326 327 rt_free(pBuf); 328 pBuf = RT_NULL; 329 } 330 331 int termios_test(int argc, char **argv) 332 { 333 rt_thread_t tid; 334 335 if(argc < 2) 336 { 337 rt_kprintf("Please input device name...\n"); 338 return -1; 339 } 340 341 term_param.dev = argv[1]; 342 term_param.baud_rate = ((argc >= 3) ? atoi(argv[2]) : Default_baud_rate); 343 344 tid = rt_thread_create("termtest", 345 termios_test_entry, (void *)&term_param, 346 512, RT_THREAD_PRIORITY_MAX/3, 20); 347 348 if (tid != RT_NULL) 349 rt_thread_startup(tid); 350 351 return 0; 352 } 353 354 #ifdef RT_USING_FINSH 355 #include <finsh.h> 356 #ifdef FINSH_USING_MSH 357 MSH_CMD_EXPORT_ALIAS(termios_test, termtest, e.g: termtest /dev/uart4 115200); 358 #endif /* FINSH_USING_MSH */ 359 #endif /* RT_USING_FINSH */ 360 361