UART problem - help needed

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
otitov
XCore Addict
Posts: 207
Joined: Thu Dec 10, 2009 11:00 pm
Location: Mexico

UART problem - help needed

Post by otitov »

I am experiencing strange behavior in my UART implementation which I would like to describe below.

Setup: XC-2 Ethernet board connected by 2 cables to Arduino UART's pins RX and TX, XC-2 connected via XTAG to computer.

On Arduino I run simple sketch which sends about 80 bytes, wait 1 sec, sends about 160 bytes, waits 1 sec, then sends about 240 bytes, waits 3 sec, repeat, via TX pin:

Code: Select all

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.write("-- about 80 bytes\r\n");
  for(int i=33; i<127; i++) {
    Serial.write(i);
  }
  Serial.write("\r\n");
  delay(1000);
  
  Serial.write("-- about 160 bytes\r\n");
  for(int j=0; j<2; j++) {
    for(int i=33; i<127; i++) {
      Serial.write(i);
    }
  }
  Serial.write("\r\n");
  delay(1000);
  
  Serial.write("-- about 240 bytes\r\n");
  for(int j=0; j<3; j++) {
    for(int i=33; i<127; i++) {
      Serial.write(i);
    }
  }
  Serial.write("\r\n");
  delay(3000);
}
On XC-2 I run simple "UART bypass" - I wait for input byte from Arduino, read it, send it other channel to other thread which sends this byte via XTAG to computer:

Code: Select all

/*
 ============================================================================
 Name        : xc2-uart.xc
 Description : UART code for the XC-2 board 
 ============================================================================
 */

#include <platform.h>

#define BIT_RATE 9600
#define BIT_TIME XS1_TIMER_HZ / BIT_RATE


on stdcore[0]: out port PORTUART_TX = PORT_UART_TX;
on stdcore[3]: in port PORT_GPS_UART_RX = XS1_PORT_1B;

void txByte(out port TXD, unsigned char byte);
unsigned char rxByte(in port RXD);

void doUART(chanend c) {
	unsigned char byte;
	
	do {
		c :> byte;
		txByte(PORTUART_TX, byte);		
	} while(1);
}

void doGPS(chanend c) {
	unsigned char byte;

	do {
		byte = rxByte(PORT_GPS_UART_RX);
		c <: byte;
	} while(1);
}


int main() {
	chan c1, c2;
	
	par {
		on stdcore[0]: doUART(c1);
		on stdcore[3]: doGPS(c1);
	}
	
  return 0;
}

void txByte(out port TXD, unsigned char byte) {
  unsigned time, data;
  timer t;

  data = byte;
  
  TXD <: 1;
  
  /* get initial time */
  t :> time;
   
  /* output start bit */
  TXD <: 0;
  time += BIT_TIME;
  t when timerafter(time) :> void;
		
  /* output data bits */
  for (int i=0; i<8; i++) {
    TXD <: >> data;
    time += BIT_TIME;
    t when timerafter(time) :> void;
  }

  /* output stop bit */
  TXD <: 1;
  time += BIT_TIME;
  t when timerafter(time) :> void;
}

unsigned char rxByte(in port RXD) {
  unsigned data = 0;
  timer t;
  unsigned time;

  RXD when pinseq(1) :> void;
  
  RXD when pinseq(0) :> void;
  
  t :> time;
  
  time += BIT_TIME + ((BIT_TIME) >> 1);
  
  
  // sample each bit in the middle.
     for (int i = 0; i < 8; i++)
     {
    	t when timerafter(time) :> void;
        RXD :> >> data;
        time += BIT_TIME;
     }
     
     /* input stop bit */
     //time += (BIT_TIME >> 1) ;
     //t when timerafter ( time ) :> void ;
     
  return (unsigned char)(data >> 24);   
}
Arduino outputs:

Code: Select all

-- about 80 bytes
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop
qrstuvwxyz{|}~
-- about 160 bytes
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop
qrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab
cdefghijklmnopqrstuvwxyz{|}~
-- about 240 bytes
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop
qrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab
cdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST
UVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
The reading in HyperTerminal from XC-2 output is:

Code: Select all

-- about 80 bytes
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW•¥µÅÕåõ…‰‘•™¡¥©­±µ¹½ÁÅÉ
ÍÑÕÙÝáåéíñõù5
             -- about 160 bytes
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV•¥µÅÕåõ…‰‘•™¡¥©­±µ¹½ÁÅÉ
ÍÑÕÙÝáåéíñõù…"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd
efghijk«Ëë
          ÅÉÍÑÕÙÝáåéíñõù5
                         -- about 240 bytes
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV•¥µÅÕåõ…‰‘•™¡¥©­±µ¹½ÁÅÉ
ÍÑÕÙÝáåéíñõù…"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd
efghijk«Ëë
          ÅÉÍÑÕÙÝáåéíñõù…"*2:BJRZ,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX
YZ[\]^_`abcdefghijklmnopqrstu×åéíñõù5
Please note, that from first "X" in first section the output is broken till next appearance of ' " ' symbol.

Sorry, I have no idea what is going wrong.

Please, help!


User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

Nothing immediately springs out I must say.

Firstly check that flow control turned off on Arduino and Hyperterminal.

There are a couple of improvements you could add to the RX side. Looks like you've already considered them but anyway:
1. Sample in the centre of the start bit and junk if not 0
2. Sample in the centre of the stop bit and junk if not 1

The Tx code looks OK to me, but can you test the TX side on it's own?

Can you check the Rx and Tx signals on a 'scope? Check the bit duration is as expected on both sides, and that you see stop bits etc.

Also, you could try another terminal emulator. I've always had problems with Hyperterminal.
User avatar
otitov
XCore Addict
Posts: 207
Joined: Thu Dec 10, 2009 11:00 pm
Location: Mexico

Post by otitov »

First of all thanks for your input!

I will follow posting here right after I complete a stage.

I wrote following TX testing code for XC-2, it should emulate Arduino's code as close as possible:

Code: Select all

/*
 ============================================================================
 Name        : xc2-uart.xc
 Description : UART code for the XC-2 board 
 ============================================================================
 */

#include <platform.h>

#define BIT_RATE 9600
#define BIT_TIME XS1_TIMER_HZ / BIT_RATE
#define oneSecond XS1_TIMER_HZ

on stdcore[0]: out port PORTUART_TX = PORT_UART_TX;
//on stdcore[3]: in port PORT_GPS_UART_RX = XS1_PORT_1B;

void txByte(out port TXD, unsigned char byte);
void doUART_TX_Test(void);


int main() {
	par {
		on stdcore[0]: doUART_TX_Test();
		//on stdcore[3]: doGPS(c1);
	}
	
  return 0;
}

void doUART_TX_Test(void) {
	timer t;
	unsigned time;
	
	t :> time;
	
	do {
		
		for(int i=33; i<127; i++) {
			txByte(PORTUART_TX, i);
		}
		txByte(PORTUART_TX, '\r');
		txByte(PORTUART_TX, '\n');
		
		// wait 1 second
		time += oneSecond;
		t when timerafter(time) :> void;
		
		for(int j=0; j<2; j++) {
			for(int i=33; i<127; i++) {
				txByte(PORTUART_TX, i);
			}
		}
		txByte(PORTUART_TX, '\r');
		txByte(PORTUART_TX, '\n');
		// wait 1 second
		time += oneSecond;
		t when timerafter(time) :> void;
		
		for(int j=0; j<3; j++) {
			for(int i=33; i<127; i++) {
				txByte(PORTUART_TX, i);
			}
		}
		txByte(PORTUART_TX, '\r');
		txByte(PORTUART_TX, '\n');
		// wait 3 seconds
		time += 3*oneSecond;
		t when timerafter(time) :> void;

	} while(1);
}

void txByte(out port TXD, unsigned char byte) {
  unsigned time, data;
  timer t;

  data = byte;
  
  TXD <: 1;
  
  /* get initial time */
  t :> time;
   
  /* output start bit */
  TXD <: 0;
  time += BIT_TIME;
  t when timerafter(time) :> void;
		
  /* output data bits */
  for (int i=0; i<8; i++) {
    TXD <: >> data;
    time += BIT_TIME;
    t when timerafter(time) :> void;
  }

  /* output stop bit */
  TXD <: 1;
  time += BIT_TIME;
  t when timerafter(time) :> void;
}
The output in HyperTerminal was:

Code: Select all

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop
qrstuvwxyz{|}~
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop
qrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab
cdefghijklmnopqrstuvwxyz{|}~
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop
qrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab
cdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST
UVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
Looks ok for me. Can I assume now that TX routine on XC-2 works fine?
User avatar
otitov
XCore Addict
Posts: 207
Joined: Thu Dec 10, 2009 11:00 pm
Location: Mexico

Post by otitov »

Flow control is turned off (set to "hardware").

Sorry, no oscilloscope here, neither logic analyzer (will be next big investment for my lab).

UPDATE: flow control set to NONE
Last edited by otitov on Mon Mar 15, 2010 10:18 pm, edited 1 time in total.
User avatar
otitov
XCore Addict
Posts: 207
Joined: Thu Dec 10, 2009 11:00 pm
Location: Mexico

Post by otitov »

I have SecureCRT terminal. Run same tests and the output looks identical to what I see in HyperTerminal.
User avatar
otitov
XCore Addict
Posts: 207
Joined: Thu Dec 10, 2009 11:00 pm
Location: Mexico

Post by otitov »

Some discoveries:

Code: Select all

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW•¥µÅÕåõ…‰‘•™¡¥©­±µ¹½ÁÅÉÍÑÕÙÝáåéíñõù5
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
Fist line represents the bypass output and the second line - how it should be looking.

First line missed 4 bytes! Or more, or less...
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

otitov wrote:Flow control is turned off (set to "hardware").
Hardware flow control is not off! It means that the RTS (Request To Send) and CTS (Clear To Send) signals are used to control the flow. Software flow control emulates RTS/CTS by injecting XON and XOFF characters into the data stream. See if you can deselect all flow control.

That said, it doesn't look like flow control is your issue. Try to keep using a terminal emulator that doesn't automatically detect the bit rate. I'd stick with SecureCRT. Never used it but anything's got to be better than Hyper terminal ;)
Last edited by Woody on Mon Mar 15, 2010 10:31 am, edited 1 time in total.
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

No scope? Oh.

I agree that the Tx side looks good.

Can you link the Arduino's Tx to the PC directly and check that works OK. If that's working fine then the problem must be in the XCore Rx.
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

To check the Rx in isolation of the Arduino, you could write some code to echo Rx chars to the Tx. Make sure you've got separate threads for the Rx and Tx sides though (you don't want to miss any Rx characters whilst you're Txing.
User avatar
Berni
Respected Member
Posts: 363
Joined: Thu Dec 10, 2009 10:17 pm

Post by Berni »

Make sure your baudrate is correct. The USART example on the xmos website has its baud rate slightly off in the high speeds. A slightly off baudrate typically results in large chunks of data not sending properly as the clock loses sync til the end.

Try to tweak your baudrade up or down slightly and see if it makes any diference.