2007년 8월 13일 월요일

Serial COM 포트 사용하기

우선 기본적으로 내장되어 있는 Serial Port는 COM1, COM2가 존재하는데 COM1은 일반적으로 콘솔용으로 사용하고 COM2를 serial interface용으로 사용할 수 있습니다. 하드웨어 설명서에 나온대로 본다면,

+---+---+---+---+---+
TX-RX-NC NC TX-
+---+---+---+---+---+
TX+RXDTXDRX+GND
+-------------------+

그런데 기본적으로 COM2는 RXD, TXD, GND만 사용하도록 되어있습니다. RS-485지원할려면 조금 번거로운 작업을 거쳐야 됩니다. 세개의 선만을 연결해서 크로스 케이블을 만듭니다.

이제 테스트만 남았는데 그전에 시리얼 포트에 대한 디바이스 이름을 살펴보면,

in Linux, /dev/ttyAM0(/dev/console), /dev/ttyAM1
in NetBSD, /dev/epcom0(/dev/console), /dev/epcom1

NetBSD에서 디바이스 이름을 몰라서 조금해멨는데 http://www.netbsd.org/ports/evbarm/ 에 이렇게 되어있네요.

Support for the TS-7200 was written by Jesse Off

* On-CPU RS232 UARTs (2) (epcom)

ts-7200# dmesggrep epcom
epcom0 at epsoc0 addr 0x808c0000-0x808c0fff intr 52
epcom0: console
epcom1 at epsoc0 addr 0x808d0000-0x808d0fff intr 54

NetBSD를 설치했을때 epcom* 디바이스가 /dev 에 없어서 다음처럼 디바이스를 생성시켜줍니다.

ts-7200# sh /dev/MAKEDEV epcom0
ts-7200# sh /dev/MAKEDEV epcom1
ts-7200# ls -al /dev/epcom*
crw------- 1 uucp wheel 107, 0 Aug 13 16:05 /dev/epcom0
crw------- 1 uucp wheel 107, 1 Aug 13 16:05 /dev/epcom1
ts-7200# chmod g+rw /dev/epcom*
ts-7200# ls -al /dev/epcom*
crw-rw---- 1 uucp wheel 107, 0 Aug 13 16:05 /dev/epcom0
crw-rw---- 1 uucp wheel 107, 1 Aug 13 16:05 /dev/epcom1

사실상 필요한 것은 /dev/epcom1이고 적절히 권한을 부여합니다. 이 경우에는 user, group에 대해서 read,
write를 할수 있게 했습니다.

이제 테스트 수행만 남았는데 간단하게 tx, rx할수 있는 프로그램을 만들어서 테스트를 해보았습니다.

결과)
ESP-NS(linux) -> TS-7200(NetBSD) : 수신측 TS-7200 보드에서는 8byte, 5byte씩 나누어져서 read된다.
TS-7200(NetBSD) -> ESP-NS(linux) : 수신측 ESP-NS 보드에서 가끔 8byte, 5byte씩 나누어져서 read된다.

Q) 수신 버퍼가 8byte씩 읽어지는 것으로 보입니다. How to increase read buffer? 궁금합니다.

아래 소스

/*
* $Id: txrx.c,v 1.1 2007/08/13 08:04:40 pjy Exp $
*/
#include
#include
#include
#include

typedef struct
{
char speed[20]; /* 1200, 2400, 9600, 19200, 38400 */
char data_bit[20]; /* 5, 6, 7, 8 */
char parity[20]; /* NO, EVEN, ODD */
char stop_bit[20]; /* 1, 2 */
char control[20]; /* NO, Xon/Xoff */
} COMMSET_DS;

struct termios INIT_SETTING;

int setTTY(char*, char*);
int restoreTTY(int, const struct termios*);
int getCommSet(char*, COMMSET_DS*);
void prnCommSet(char*, char*, COMMSET_DS);
void getString(char*, const char*, int, char*);

int main(int argc, char *argv[])
{
int fd, len;
char buf[1024];

if(argc != 4) {
fprintf(stderr, "Usage: %s flag(1:tx, other:rx) device set\n", argv[0]);
fprintf(stderr, " flag: 1(tx), other(rx)\n");
fprintf(stderr, " device: /dev/ttyS03 ~ /dev/ttyS06(ESP-NS linux)\n");
fprintf(stderr, " device: /dev/ttyAM0 ~ /dev/ttyAM1(TS-7200 linux)\n");
fprintf(stderr, " device: /dev/epcom0 ~ /dev/epcom1(TS-7200 NetBSD)\n");
fprintf(stderr, " set: speed:data bit:parity:stop bit:control\n");
fprintf(stderr, " ex) in ESP-NS board(linux)--->\n");
fprintf(stderr, " tx-> %s 1 /dev/ttyS05 115200:8:NO:1:NO\n", argv[0]);
fprintf(stderr, " rx<- %s 2 /dev/ttyS05 115200:8:NO:1:NO\n", argv[0]); fprintf(stderr, " ex) in TS-7200 board(linux)--->\n");
fprintf(stderr, " tx-> %s 1 /dev/ttyAM1 115200:8:NO:1:NO\n", argv[0]);
fprintf(stderr, " rx<- %s 2 /dev/ttyAM1 115200:8:NO:1:NO\n", argv[0]); fprintf(stderr, " ex) in TS-7200 board(NetBSD)--->\n");
fprintf(stderr, " tx-> %s 1 /dev/epcom1 115200:8:NO:1:NO\n", argv[0]);
fprintf(stderr, " rx<- %s 2 /dev/epcom1 115200:8:NO:1:NO\n\n", argv[0]); return 1; } fd = setTTY(argv[2], argv[3]); if(fd < 0) { fprintf(stderr, "Can't set tty.\n"); return 1; } printf("%s Terminal attribute set OK!\n", argv[2]); if(atoi(argv[1]) == 1) { snprintf(buf, sizeof(buf), "Hello, NetBSD"); while(1) { len = write(fd, buf, strlen(buf)); if(len > 0)
printf("send %d bytes: %.*s\n", len, len, buf);
sleep(3);
}
}
else {
while(1) {
len = read(fd, buf, sizeof(buf));
if(len > 0)
printf("read %d bytes: %.*s\n", len, len, buf);
}
}

(void)restoreTTY(fd, &INIT_SETTING);
return 0;
}

int setTTY(char *device, char *comm)
{
struct termios new_settings;
COMMSET_DS commset;
int fd;

printf("---------- %s device set start ----------\n", device);
/********************************************************************
open device and get comm set value
*********************************************************************/
if((fd = open(device, O_RDWR | O_NOCTTY)) < 0) { fprintf(stderr, "Unable to open %s\n", device); return -1; } if(getCommSet(comm, &commset) != 1) { fprintf(stderr, "getCommSet(%s) error\n", comm); return -1; } prnCommSet(device, comm, commset); /******************************************************************** set terminal flag *********************************************************************/ tcgetattr(fd, &INIT_SETTING); new_settings = INIT_SETTING; new_settings.c_iflag &= ~ISTRIP; /* No Character strip */ new_settings.c_iflag |= IGNBRK; /* ignore Break */ #ifdef _TMP_ new_settings.c_iflag |= IGNCR; /* ignore CR */ #endif new_settings.c_iflag &= ~ICRNL; /* no map CR to NL on input */ new_settings.c_iflag &= ~IGNCR; /* enable CR */ new_settings.c_iflag &= ~INLCR; /* no map NL to CR on input */ new_settings.c_iflag |= IGNPAR; /* ignore chars with parity err */ if(!strcmp(commset.control, "NO")) { new_settings.c_iflag &= ~IXON; /* disable input flow control */ new_settings.c_iflag &= ~IXOFF; /* disable output flow control */ printf("NOTE. set flow control flag: disable\n"); } else if(!strcmp(commset.control, "Xon/Xoff")) { new_settings.c_iflag |= IXON; /* enable input flow control */ new_settings.c_iflag |= IXOFF; /* enable output flow control */ printf("NOTE. set flow control flag: Xon/Xoff\n"); } else { new_settings.c_iflag &= ~IXON; /* disable input flow control(default) */ new_settings.c_iflag &= ~IXOFF; /* disable output flow control(default) */ printf("NOTE. set flow control flag: disable(default)\n"); } if(!strcmp(commset.parity, "NO")) { new_settings.c_cflag &= ~PARENB;/* no parity */ printf("NOTE. set parity flag: no parity\n"); } else if(!strcmp(commset.parity, "EVEN")) { new_settings.c_cflag |= PARENB; /* enable parity */ new_settings.c_cflag &= ~PARODD;/* even parity */ printf("NOTE. set parity flag: even parity\n"); } else if(!strcmp(commset.parity, "ODD")) { new_settings.c_cflag |= PARENB; /* enable parity */ new_settings.c_cflag |= PARODD; /* odd parity */ printf("NOTE. set parity flag: odd parity\n"); } else { new_settings.c_cflag &= ~PARENB; /* no parity(default) */ printf("NOTE. set parity flag: no parity(default)\n"); } new_settings.c_cflag &= ~CSIZE; if(!strcmp(commset.data_bit, "5")) { new_settings.c_cflag |= CS5; /* set 5bits/char */ printf("NOTE. set data bit flag: 5bits/char\n"); } else if(!strcmp(commset.data_bit, "6")) { new_settings.c_cflag |= CS6; /* set 6bits/char */ printf("NOTE. set data bit flag: 6bits/char\n"); } else if(!strcmp(commset.data_bit, "7")) { new_settings.c_cflag |= CS7; /* set 7bits/char */ printf("NOTE. set data bit flag: 7bits/char\n"); } else if(!strcmp(commset.data_bit, "8")) { new_settings.c_cflag |= CS8; /* set 8bits/char */ printf("NOTE. set data bit flag: 8bits/char\n"); } else { new_settings.c_cflag |= CS8; /* set 8bits/char(default) */ printf("NOTE. set data bit flag: 8bits/char(default)\n"); } new_settings.c_cflag |= CLOCAL; /* ignore modem status lines */ new_settings.c_cflag |= CREAD; /* enable receiver */ if(!strcmp(commset.stop_bit, "1")) { new_settings.c_cflag &= ~CSTOPB; /* 1 stop bit */ printf("NOTE. set stop bit flag: 1 stop bit\n"); } else if(!strcmp(commset.stop_bit, "2")) { new_settings.c_cflag |= CSTOPB; /* 2 stop bit */ printf("NOTE. set stop bit flag: 2 stop bit\n"); } else { new_settings.c_cflag &= ~CSTOPB; /* 1 stop bit(default) */ printf("NOTE. set stop bit flag: 1 stop bit(default)\n"); } #ifdef _TMP_ new_settings.c_oflag &= ~OPOST; /* ouput processing off */ new_settings.c_oflag |= TAB3; /* expand tabs to space */ #endif new_settings.c_lflag &= ~ICANON; /* non-canonical mode */ new_settings.c_lflag &= ~ECHO; /* echo off */ new_settings.c_lflag &= ~ISIG; /* ignore signal from tty */ /*new_settings.c_lflag &= ~IEXTEN;*//* extended input processing off*/ /*new_settings.c_cc[VMIN] = 1; new_settings.c_cc[VTIME] = 0;*/ if(!strcmp(commset.speed, "1200")) { /* 1200 bps */ cfsetispeed(&new_settings, B1200); cfsetospeed(&new_settings, B1200); printf("NOTE. set speed flag: 1200 bps\n"); } else if(!strcmp(commset.speed, "2400")) { /* 2400 bps */ cfsetispeed(&new_settings, B2400); cfsetospeed(&new_settings, B2400); printf("NOTE. set speed flag: 2400 bps\n"); } else if(!strcmp(commset.speed, "4800")) { /* 4800 bps */ cfsetispeed(&new_settings, B4800); cfsetospeed(&new_settings, B4800); printf("NOTE. set speed flag: 4800 bps\n"); } else if(!strcmp(commset.speed, "9600")) { /* 9600 bps */ cfsetispeed(&new_settings, B9600); cfsetospeed(&new_settings, B9600); printf("NOTE. set speed flag: 9600 bps\n"); } else if(!strcmp(commset.speed, "19200")) { /* 19200 bps */ cfsetispeed(&new_settings, B19200); cfsetospeed(&new_settings, B19200); printf("NOTE. set speed flag: 19200 bps\n"); } else if(!strcmp(commset.speed, "38400")) { /* 38400 bps */ cfsetispeed(&new_settings, B38400); cfsetospeed(&new_settings, B38400); printf("NOTE. set speed flag: 38400 bps\n"); } else if(!strcmp(commset.speed, "57600")) { /* 57600 bps */ cfsetispeed(&new_settings, B57600); cfsetospeed(&new_settings, B57600); printf("NOTE. set speed flag: 57600 bps\n"); } else if(!strcmp(commset.speed, "115200")) { /* 115200 bps */ cfsetispeed(&new_settings, B115200); cfsetospeed(&new_settings, B115200); printf("NOTE. set speed flag: 115200 bps\n"); } else if(!strcmp(commset.speed, "230400")) { /* 230400 bps */ cfsetispeed(&new_settings, B230400); cfsetospeed(&new_settings, B230400); printf("NOTE. set speed flag: B230400 bps\n"); } else { /* 9600 bps(default) */ cfsetispeed(&new_settings, B9600); cfsetospeed(&new_settings, B9600); printf("NOTE. set speed flag: 9600(default) bps\n"); } /******************************************************************** set terminal type *********************************************************************/ if(tcsetattr(fd, TCSANOW, &new_settings) != 0) { fprintf(stderr, "Could not set attributes\n"); return -1; } printf("%s device has been initialized successfully.\n", device); return fd; } int restoreTTY(int fd, const struct termios *init_setting) { if(tcsetattr(fd, TCSANOW, init_setting) != 0) { fprintf(stderr, "Could not restore terminal attribute\n"); return -1; } return 1; } int getCommSet(char *str, COMMSET_DS *pCommSet) { char tmp[100]; getString(str, ":", 0, tmp); memcpy(pCommSet->speed, tmp, sizeof(pCommSet->speed));
/*printf("0(speed) -> %s, %s\n", tmp, pCommSet->speed);
printf("strlen() = %d\n", strlen(pCommSet->speed));*/
if(strlen(pCommSet->speed) < 1) return 0; getString(str, ":", 1, tmp); memcpy(pCommSet->data_bit, tmp, sizeof(pCommSet->data_bit));
/*printf("1(data_bit) -> %s, %s\n", tmp, pCommSet->data_bit);
printf("strlen() = %d\n", strlen(pCommSet->data_bit));*/
if(strlen(pCommSet->data_bit) < 1) return -1; getString(str, ":", 2, tmp); memcpy(pCommSet->parity, tmp, sizeof(pCommSet->parity));
/*printf("2(parity) -> %s, %s\n", tmp, pCommSet->parity);
printf("strlen() = %d\n", strlen(pCommSet->parity));*/
if(strlen(pCommSet->parity) < 1) return -2; getString(str, ":", 3, tmp); memcpy(pCommSet->stop_bit, tmp, sizeof(pCommSet->stop_bit));
/*printf("3(stop_bit) -> %s, %s\n", tmp, pCommSet->stop_bit);
printf("strlen() = %d\n", strlen(pCommSet->stop_bit));*/
if(strlen(pCommSet->stop_bit) < 1) return -3; getString(str, ":", 4, tmp); memcpy(pCommSet->control, tmp, sizeof(pCommSet->control));
/*printf("4(control) -> %s, %s\n", tmp, pCommSet->control);
printf("strlen() = %d\n", strlen(pCommSet->control));*/
if(strlen(pCommSet->control) < 1) return -4; return 1; } void prnCommSet(char *device, char *comm, COMMSET_DS CommSet) { printf("device : %s\n", device); printf("comm set: %s\n", comm); printf(" -> speed : %s\n", CommSet.speed);
printf(" -> data bit : %s\n", CommSet.data_bit);
printf(" -> parity : %s\n", CommSet.parity);
printf(" -> stop bit : %s\n", CommSet.stop_bit);
printf(" -> control : %s\n", CommSet.control);

return;
}

void getString(char *data, const char *delim, int order, char *str)
{
int k = 0;
char *token, ddd[1024];

strncpy(ddd, data, sizeof(ddd));
*str = 0x00;
token = strtok(ddd, delim);
while(token != NULL) {
if(k++ == order) { /* target string */
strcpy(str, token);
break;
}
token = strtok(NULL, delim); /* get next token */
}
}

/************************************************************************
End of Code
*************************************************************************/

댓글 없음: