# serial port rs-232 full duplex connectme NET+OS6.3 example

**URL:** <https://forums.digi.com/t/serial-port-rs-232-full-duplex-connectme-net-os6-3-example/5314>\
**Category:** NET+OS\
**Created:** [April 27, 2007, 7:48am UTC](https://forums.digi.com/t/serial-port-rs-232-full-duplex-connectme-net-os6-3-example/5314 "2007-04-27T07:48:34Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![gfanini](https://avatars.discourse-cdn.com/v4/letter/g/6bbea6/32.png) [@gfanini](https://forums.digi.com/u/gfanini)\
**Post date:** [April 27, 2007, 7:48am UTC](https://forums.digi.com/t/serial-port-rs-232-full-duplex-connectme-net-os6-3-example/5314/1 "2007-04-27T07:48:34Z")

</div>

my application being a ethernet to serial bridge I would need to use the serial port in full duplex if possible.

I found examples in NET+OS6.3 to connect the 2 com ports on the board but they are half-duplex (one example on [ftp1.digi.com](http://ftp1.digi.com) is DMA but it’s still only half-duplex): i.e. either read OR write simultaneously, since RS-232 is full-duplex, i.e. there are 2 separate FIFO for rx/tx on each port, is it possible to both read AND write to a serial port and where to find an example ?  
should I set flow control to enable full duplex ?  
I tried to set up simultaneous read/write threads but the act of writing appears to empty the read buffer.

---

<div class="post-metadata">

**Author:** ![gfanini](https://avatars.discourse-cdn.com/v4/letter/g/6bbea6/32.png) [@gfanini](https://forums.digi.com/u/gfanini)\
**Post date:** [April 28, 2007, 3:17pm UTC](https://forums.digi.com/t/serial-port-rs-232-full-duplex-connectme-net-os6-3-example/5314/2 "2007-04-28T15:17:43Z")

</div>

I would like to port (for example) this miniterm.c with full duplex serial rs232 to NET+OS 6.3, is it possible with DIGI serial UART driver of connectme board :

/\*

- AUTHOR: Sven Goldt ([goldt@math.tu-berlin.de](mailto:goldt@math.tu-berlin.de))
- 
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- 
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- 

_/  
/_  
This is like all programs in the Linux Programmer’s Guide meant  
as a simple practical demonstration.  
It can be used as a base for a real terminal program.  
\*/

#include  
#include  
#include  
#include  
#include

#define BAUDRATE B38400  
#define MODEMDEVICE “/dev/modem”  
#define ENDMINITERM 2 /\* ctrl-b to quit miniterm \*/

#define \_POSIX\_SOURCE 1 /\* POSIX compliant source \*/

#define FALSE 0  
#define TRUE 1

volatile int STOP=FALSE;

void child\_handler(int s)  
{  
STOP=TRUE;  
}

main()  
{  
int fd,c;  
struct termios oldtio,newtio,oldstdtio,newstdtio;  
struct sigaction sa;

/\*  
Open modem device for reading and writing and not as controlling tty  
because we don’t want to get killed if linenoise sends CTRL-C.  
\*/  
fd = open(MODEMDEVICE, O\_RDWR | O\_NOCTTY);  
if (fd \<0) {perror(MODEMDEVICE); exit(-1); }

tcgetattr(fd,&oldtio); /\* save current modem settings \*/

/\*  
Set bps rate and hardware flow control and 8n1 (8bit,no parity,1 stopbit).  
Also don’t hangup automatically and ignore modem status.  
Finally enable receiving characters.  
\*/  
newtio.c\_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

/\*  
Ignore bytes with parity errors and make terminal raw and dumb.  
\*/  
newtio.c\_iflag = IGNPAR;

/\*  
Raw output.  
\*/  
newtio.c\_oflag = 0;

/\*  
Don’t echo characters because if you connect to a host it or your  
modem will echo characters for you. Don’t generate signals.  
\*/  
newtio.c\_lflag = 0;

/\* blocking read until 1 char arrives \*/  
newtio.c\_cc[VMIN]=1;  
newtio.c\_cc[VTIME]=0;

/\* now clean the modem line and activate the settings for modem \*/  
tcflush(fd, TCIFLUSH);  
tcsetattr(fd,TCSANOW,&newtio);

/\*  
Strange, but if you uncomment this command miniterm will not work  
even if you stop canonical mode for stdout. This is a linux bug.  
_/  
tcsetattr(1,TCSANOW,&newtio); /_ stdout settings like modem settings \*/

/\* next stop echo and buffering for stdin _/  
tcgetattr(0,&oldstdtio);  
tcgetattr(0,&newstdtio); /_ get working stdtio \*/  
newstdtio.c\_lflag &= ~(ICANON | ECHO);  
tcsetattr(0,TCSANOW,&newstdtio);

/\* terminal settings done, now handle in/ouput _/  
switch (fork())  
{  
case 0: /_ child _/  
/_ user input _/  
close(1); /_ stdout not needed _/  
for (c=getchar(); c!= ENDMINITERM ; c=getchar()) write(fd,&c,1);  
tcsetattr(fd,TCSANOW,&oldtio); /_ restore old modem setings _/  
tcsetattr(0,TCSANOW,&oldstdtio); /_ restore old tty setings _/  
close(fd);  
exit(0); /_ will send a SIGCHLD to the parent _/  
break;  
case -1:  
perror(“fork”);  
tcsetattr(fd,TCSANOW,&oldtio);  
close(fd);  
exit(-1);  
default: /_ parent _/  
close(0); /_ stdin not needed _/  
sa.sa\_handler = child\_handler;  
sa.sa\_flags = 0;  
sigaction(SIGCHLD,&sa,NULL); /_ handle dying child _/  
while (STOP==FALSE) /_ modem input handler _/  
{  
read(fd,&c,1); /_ modem _/  
write(1,&c,1); /_ stdout _/  
}  
wait(NULL); /_ wait for child to die or it will become a zombie \*/  
break;  
}  
}

---

<div class="post-metadata">

**Author:** ![egawtry](https://avatars.discourse-cdn.com/v4/letter/e/8e8cbc/32.png) [@egawtry](https://forums.digi.com/u/egawtry)\
**Post date:** [April 28, 2007, 3:56pm UTC](https://forums.digi.com/t/serial-port-rs-232-full-duplex-connectme-net-os6-3-example/5314/3 "2007-04-28T15:56:59Z")

</div>

Use the tc functions. Do NOT use getchar(). I will post an example when I get back to my computer.

-Erik

---

<div class="post-metadata">

**Author:** ![gfanini](https://avatars.discourse-cdn.com/v4/letter/g/6bbea6/32.png) [@gfanini](https://forums.digi.com/u/gfanini)\
**Post date:** [April 30, 2007, 11:06am UTC](https://forums.digi.com/t/serial-port-rs-232-full-duplex-connectme-net-os6-3-example/5314/4 "2007-04-30T11:06:55Z")

</div>

I will also post my code that OS6.3 I think does not have fork() so it’s with threads, but I suspect I have serial receiver buffering off because writes clear the receive buffer.

---

<div class="post-metadata">

**Author:** ![gfanini](https://avatars.discourse-cdn.com/v4/letter/g/6bbea6/32.png) [@gfanini](https://forums.digi.com/u/gfanini)\
**Post date:** [May 2, 2007, 7:52am UTC](https://forums.digi.com/t/serial-port-rs-232-full-duplex-connectme-net-os6-3-example/5314/5 "2007-05-02T07:52:19Z")

</div>

the read thread :

/\* SerialRead  
\*

- Description: This function does the setup of the Serial port 0 and then uses it to
- receive data which were sent into the serial port 0.
- 
- Called by: root
- 

\*/  
void SerialRead(ULONG thread\_input)  
{  
int zeroFd, result, status, baudrate;  
int bytetorecv = 0;  
int numBytesRcvd= 0;  
int numBytesSent= 0;

#ifdef LOOP\_FOREVER\_IN\_THIS\_TEST  
unsigned int iteration = 0;  
#endif

#ifdef OLD\_SERIAL\_API  
int iOptions;  
#else  
static int first\_open = 1;  
struct ioflags\_t iOptions;  
struct termios tios;  
struct serial\_cntr\_t prev\_counters;  
struct serial\_cntr\_t curr\_counters;  
memset( &prev\_counters, 0, sizeof(prev\_counters));  
#endif

```
printf ("serial recv thread created.

```

");

// char _sendBuffer=setSendBuffer(BufferSizeForSendAndReceive);  
while (1/SWserlTests[currentop].szData/)  
{  
/_ Check status. _/  
// status = tx\_semaphore\_get(&semaphore\_0, TX\_WAIT\_FOREVER);  
if (status != TX\_SUCCESS)  
{  
printf("Unable to get semaphore for com 0.  
");  
goto err;  
}  
else  
{  
zeroready = 0; /_ com zero not ready \*/

```
        zeroFd = open (TEST_COM0, SWserlTests[currentop].mode); /* because hardware handshake is needed */
        if (zeroFd &lt;0)
        {
            printf ("Can't open %s [%d].

```

", TEST\_COM0, getErrno());  
goto err;  
}  
else  
{  
#if IS\_DTR\_DSR\_PRESENT == TRUE  
#ifdef OLD\_SERIAL\_API  
do  
{  
/\* get the DCD state \*/  
result = ioctl(zeroFd, SIO\_GET\_STATUS\_DCD, &iOptions);  
if (result \< 0)  
{  
printf ("ioctl(SIO\_GET\_STATUS\_DCD) errno[%d]  
", getErrno());  
goto err;  
}

```
                /* get the DSR state */
                result = ioctl(zeroFd, SIO_GET_STATUS_DSR, &amp;status);
                if (result &lt; 0)
                {
                    printf ("ioctl(SIO_GET_STATUS_DSR) errno[%d]

```

", getErrno());  
goto err;  
}

```
                if ((status == 0) &amp;&amp; (iOptions == 0))
                {
                    printf ("Connect Serial cable!

```

" );  
// tx\_thread\_sleep(100);  
}  
}  
while((status == 0) && (iOptions == 0));  
#else  
do  
{  
tcgetstats( zeroFd, &ser\_status );  
if ( (ser\_status.mstat & (MS\_DCD | MS\_DSR)) == 0 )  
{  
printf ("Connect Serial cable!  
");  
// tx\_thread\_sleep(100);  
}  
}  
while( (ser\_status.mstat & (MS\_DCD | MS\_DSR)) == 0 );  
#endif /\* OLD\_SERIAL\_API _/  
 #endif /_ IS\_DTR\_DSR\_PRESENT \*/

```
            /* set the baud rate */
            baudrate = SWserlTests[currentop].baudrate;

```

#ifdef OLD\_SERIAL\_API  
result = ioctl(zeroFd, SIO\_BAUD\_SET, &baudrate);  
if (result \< 0)  
{  
printf ("ioctl(Baud set) errno[%d]  
", getErrno());  
goto err;  
}  
#else  
tcgetattr(zeroFd, &tios);  
cfsetospeed(&tios, baudrate);  
#endif

```
            /* set other parameters */
            iOptions = SWserlTests[currentop].ioflags;

```

#ifdef OLD\_SERIAL\_API  
result = ioctl(zeroFd, SIO\_HW\_OPTS\_SET, &iOptions);  
if (result \< 0)  
{  
printf ("ioctl(Line options) failure: errno[%d]  
", getErrno());  
goto err;  
}  
#else  
tios.c\_cflag = iOptions.cflags;  
tios.c\_iflag = iOptions.iflags;

```
	result = tcsetattr( zeroFd, TCSANOW, &amp;tios );
	if (result &lt; 0) {
                printf ("ioctl(Set attributes) failure: errno[%d]

```

", getErrno());  
goto err;  
}  
if ( cfgetospeed(&tios) != baudrate ) {  
printf ("ioctl(Baud set) errno[%d]  
", getErrno());  
return;  
}  
if ( (tios.c\_cflag != iOptions.cflags) ||  
(tios.c\_iflag != iOptions.iflags) )  
{  
printf ("ioctl(Flag settings) failure errno[%d]  
", getErrno());  
goto err;  
}  
#endif

```
    bytetorecv = BufferSizeForSendAndReceive;

```

// bytetorecv = SWserlTests[currentop].szData;

#ifdef OLD\_SERIAL\_API  
result = ioctl(zeroFd, SIO\_GET\_STATUS\_ERROR, &iOptions);  
if (iOptions != 0)  
{  
printf ("Error condition [0x%x].  
", iOptions);  
ioctl(zeroFd, SIO\_CLEAR\_STATUS\_ERROR, &iOptions);  
}  
#else  
tcgetcounters(zeroFd, &curr\_counters);

```
	if (first_open) {
	    prev_counters = curr_counters;
	    first_open = 0;
	} 
	if (prev_counters.norun != curr_counters.norun)
	{
            printf ("Error condition [Overrun].

```

");  
}  
if (prev\_counters.noflow != curr\_counters.noflow)  
{  
printf ("Error condition [Overflow].  
");  
}  
if (prev\_counters.nframe != curr\_counters.nframe)  
{  
printf ("Error condition [Framing Error].  
");  
}  
if (prev\_counters.nparity != curr\_counters.nparity)  
{  
printf ("Error condition [Parity Error].  
");  
}  
if (prev\_counters.nbreak != curr\_counters.nbreak)  
{  
printf ("Error condition [Break].  
");  
}  
prev\_counters = curr\_counters;  
#endif

```
            zeroready = 1;

```

// status = tx\_semaphore\_put(&semaphore\_0);  
numBytesRcvd = 0;  
// com0NotFinish = 1;  
do  
{  
if (numBytesRcvd \< bytetorecv)  
{  
bufstat("R1 ",zeroFd);  
result = read(zeroFd, (rcvBuffer0 + numBytesRcvd), (bytetorecv - numBytesRcvd));  
bufstat("R2 ",zeroFd);

```
					if (result &lt; 0)
                    {
                        printf ("read failed [%d].

```

", getErrno() );  
}  
else  
{  
numBytesRcvd += result;  
printf ("serial num bytes recvd [%d]=%c.  
", numBytesRcvd, (char _)_(rcvBuffer0 + numBytesRcvd - result) );  
}

```
					INT32 var_yellow,var_green;
					char cmd[100];
					char rc=(char *)*(rcvBuffer0 + numBytesRcvd - result);
					manGetINT32(EXAMPLE_greenLedOn, &amp;var_green, NULL, MAN_TIMEOUT_FOREVER);
					manGetINT32(EXAMPLE_yellowLedOn, &amp;var_yellow, NULL, MAN_TIMEOUT_FOREVER);

					switch (rc)
					{
					case 'D':// tasto down
						if(var_green==2)
							sendTrap();
						manSetINT32(EXAMPLE_greenLedOn, 1, NULL, MAN_TIMEOUT_FOREVER);
						break;
					case 'U':// tasto up
						if(var_green==1)
							sendTrap();
						manSetINT32(EXAMPLE_greenLedOn, 2, NULL, MAN_TIMEOUT_FOREVER);
						break;
					case 'O':// led on
					    manSetINT32(EXAMPLE_yellowLedOn, 1, NULL, MAN_TIMEOUT_FOREVER);
						break;
					case 'o':// led off
					    manSetINT32(EXAMPLE_yellowLedOn, 2, NULL, MAN_TIMEOUT_FOREVER);
						break;
					case 'Q':// richiesta comandi
					if(g_delta)
					{

```

// while (bytetosend) // attendo invio ;  
sendBuffer[0]=g\_delta;// ultimo set da snmp manager  
bytetosend=1;  
// tx\_thread\_sleep(1); /\* wait for send to finish completely \*/  
SerialWrite1(zeroFd,sendBuffer,1);  
// while (bytetosend) // attendo invio ;

```
						g_delta=0;
						break;
					}

					default:

```

/\*  
if (result \> 0)  
{  
while (bytetosend) // attendo invio  
;  
sendBuffer[0]=rc;// ultimo set da snmp manager   
bytetosend=1;  
}  
\*/  
break;  
}  
// SerialWrite(zeroFd,&rc,1);  
}  
}  
while (numBytesRcvd \< bytetorecv);  
numBytesRcvd = 0;  
numBytesSent = 0;  
result = close (zeroFd);  
if (result\<0)  
{  
printf ("Close failed [%d].  
", getErrno() );  
}

```
            currentop++;

```

#ifdef LOOP\_FOREVER\_IN\_THIS\_TEST  
if (SWserlTests[currentop].szData == 0)  
{  
currentop = 0;  
printf("  
Iteration %d  
", ++iteration);  
}  
#endif  
}  
} /\* end if _/  
} /_ end while _/  
// tx\_thread\_sleep(1000); /_ wait for send to finish completely \*/  
printf ("Thread Serial One complete.  
");  
return;

err:  
return;  
}

the write thread will write in this way but it seems to me it is flushing the input buffer, and also getting serial port stats seems to flush it

void SerialWrite1(int oneFd, char \*psendBuffer, int pbytetosend)  
{  
int result;

```
bufstat("W1 ",oneFd);
result = write (oneFd, psendBuffer, pbytetosend);
bufstat("W2 ",oneFd);
if (result &lt; 0)
{
    printf ("write failed [%d].

```

", getErrno());  
}  
else  
{  
if (result)  
printf("serial char sent ‘%c’  
",psendBuffer[0]);  
}  
}

---

<div class="post-metadata">

**Author:** ![gfanini](https://avatars.discourse-cdn.com/v4/letter/g/6bbea6/32.png) [@gfanini](https://forums.digi.com/u/gfanini)\
**Post date:** [May 11, 2007, 12:37pm UTC](https://forums.digi.com/t/serial-port-rs-232-full-duplex-connectme-net-os6-3-example/5314/6 "2007-05-11T12:37:44Z")

</div>

I sent some files from pc hypeterminal of known content with a alphabet like pattern and checked the contents received by the digi while the digi was also sending a known pattern which was wrapping periodically well on the terminal on the pc, also with another little test program on the pc I did not need any 10 ms delay on the pc to wait for the “turn around” of the digi from write to read (which I checked with my colleague it is not obviously full duplex, since only one end is transmitting at any one time, but the problem is half duplex with some sort of problem in quickly transitioning to read from the digi’s end) so I suspect it’s a problem of the microchip pic’s uart I observed this initially and I have yet to find out what is lacking on the pic. I did set to 0 this #define NEED\_ECHO 0 from netos\_serl.c which might have been a problem but I am unsure.Thanks for any information.
