いとうです。相変わらず思わしくありませんが、試したことのレポートです。
From: Kouichi Hirabayashi <k...@mogami.com> Subject: [FreeBSD-users-jp 94055] Re: umodem で PICC18F2550 にアクセスすると不安定 Date: Thu, 15 Nov 2012 22:37:46 +0900 > 相手のデバイスがコマンド(BARH\r\n)を読めていないか、 > コマンド/レスポンスがちぐはぐになっているような気が > します。相手側のデータを読み出す方法があるとよいの > ですが、それが非現実的でないとしたら、select() を使 > わすに、 > > open(); // LF 終端の canonincal 入力 > sleep(); // 1, 2 秒とか長めにして > write(); // コマンド > read(); やってみましたが、状況は変わりませんでした。 > を試して、それでもためなら、open() でデリミタ(LF)で > なく 1 バイト単位の入力を指定して、バイト単位で読ん > で見ると何かわかるかもしれません。 いただいたアドバイスを反映したつもりで、末尾のようなコードを試してみま した。 - raw モードにして、1Byte ずつ sleep()しながら write()し、read()も 1Byte ずつ読むようにした。 - read()の前の select()を復活させて、気圧計側が待ちに入っているようなら 再送するようにした…つもりだが、うまくいっていない模様。 というのが気をつけたところです。 結果は ----- # ./test11 i = 0 j = 0 BARH : (略) : i = 9 j = 0 BARH calling select() back from select(), n = 1 calling read() c = '1'(0x31) calling read() c = '0'(0x30) calling read() c = '0'(0x30) calling read() c = '4'(0x34) calling read() c = '.'(0x2e) calling read() c = '5'(0x35) calling read() c = 'h'(0x68) calling read() c = 'P'(0x50) calling read() c = 'a'(0x61) calling read() c = '.'(0x0d) calling read() c = '.'(0x0a) calling read() c = '>'(0x3e) rmesg: 1004.5hPa > i = 10 j = 0 BARH calling select() back from select(), n = 0 j = 1 BARH calling select() back from select(), n = 0 j = 2 BARH calling select() back from select(), n = 0 j = 3 BARH calling select() back from select(), n = 0 retry limit of write() exceeded. ----- と、read()の手前の select()がタイムアウトして、さらに close()が帰って来 ません。 $ ps alxwwp 98979 UID PID PPID CPU PRI NI VSZ RSS MWCHAN STAT TT TIME COMMAND 0 98979 91357 0 44 0 5832 1052 ttyout I+ 1 0:00.00 ./test11 と、今度は ttyout でブロックされています。 なお、0x0a の次の'>'は、気圧計のコマンドラインのプロンプトです。 ----- #include <err.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <termios.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/select.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/uio.h> #define PAUSE 2 #define MAX_RETRY 3 main() { int i, j, k, fd; size_t tlen; ssize_t n; char *tmesg, c, *p, rmesg[16]; fd_set fds; struct termios tios; struct timeval timeout; for (i = 0; ; i++) { printf("i = %d\n", i); if ( (fd = open("/dev/cuaU0", O_RDWR) ) < 0) { err(1, "open()"); } sleep(PAUSE); if (ioctl(fd, TIOCEXCL) < 0) { err(1, "ioctl(TIOCEXCL)"); } if (tcflush(fd, TCOFLUSH) < 0) { err(1, "tcflush(TCOFLUSH)"); } if (tcflush(fd, TCIFLUSH) < 0) { err(1, "tcflush(TCIFLUSH)"); } if (tcgetattr(fd, &tios) < 0) { err(1, "tcgetattr()"); } tios.c_cc[VMIN] = 0; tios.c_cc[VTIME] = 100; tios.c_cflag |= (CREAD | CLOCAL); tios.c_iflag &= ~(IXON | IXOFF | IMAXBEL); tios.c_lflag &= ~(ECHO | ECHONL); cfmakeraw(&tios); if (tcsetattr(fd, TCSADRAIN, &tios) < 0) { err(1, "tcsetattr()"); } timeout.tv_sec = 1; timeout.tv_usec = 0; tmesg = "BARH\r\n"; tlen = strlen(tmesg); p = rmesg; j = 0; do { printf(" j = %d\n ", j); for (k = 0; k < tlen; k++) { sleep(PAUSE); if (write(fd, &tmesg[k], 1) < 0) { err(1, "write()"); } putchar(tmesg[k] ); fflush(stdout); } FD_ZERO(&fds); FD_SET(fd, &fds); printf(" calling select()"); fflush(stdout); if ( (n = select(fd + 1, &fds, NULL, NULL, &timeout) ) < 0) { err(1, "select() for read()"); } printf(" back from select(), n = %d\n", n); } while ( (n == 0) && j++ < MAX_RETRY); if (!n) { printf(" retry limit of write() exceeded.\n"); close(fd); printf(" back from close()\n"); sleep(PAUSE); exit(1); } j = 0; while ( (j < MAX_RETRY) && (p - rmesg < sizeof(rmesg) ) ) { printf("calling read() "); fflush(stdout); if ( (n = read(fd, &c, 1) ) < 0) { err(1, "read()"); close(fd); sleep(PAUSE); exit(1); } if (n) { printf(" c = '%c'(0x%02x) ", isprint(c)? c:'.', c); } else { printf(" n = 0 "); } fflush(stdout); if (c) { *p++ = c; } else { j++; } if (c == '>') { goto DONE; } } printf("retry limit of read() exceeded\n"); close(fd); sleep(PAUSE); exit(1); DONE: *p = '\0'; printf("\nrmesg: %s\n", rmesg); close(fd); sleep(PAUSE); } } ----- kkdlabs.jp, featuring Koh-ichi Ito as just another DNS freak in town.