Robust UART code

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
ahenshaw
Experienced Member
Posts: 96
Joined: Mon Mar 22, 2010 8:55 pm

Robust UART code

Post by ahenshaw »

Before writing it myself, I thought that I'd ask if anyone was working to create a fully-featured, robust UART library.

I've seen the various demo UART implementations, but those are not exactly best-of-breed -- I'd like something that sampled multiple times per bit period, for example.

In addition, I'd like it structured such that, once it is initialized, all interaction is done over channels. So, when transmitting, I'd like my higher-level processes to be able to send a string of characters over the output channel and I want to be able to receive a complete line of characters (buffering until newline is received) over my input channel.


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

Post by Woody »

ahenshaw wrote:I thought that I'd ask if anyone was working to create a fully-featured, robust UART library.
...
I'd like something that sampled multiple times per bit period, for example.
...
all interaction is done over channels
...
I'm afraid that there are no internal plans to do this at the moment. The problem with UARTs is that if you write one with all the bells and whistles, it has a slow top bit rate and/or takes up a lot of threads. Many applications will not require some or all of these features, so it's a bit of a waste of resources, it's also pretty straightforward to write a UART.

I have written a UART in the past with *8 Rx triple sampling with voting, flexible config (8N1/7E1.5 etc.), RTS/CTS flow control, 16C550 style FIFOs and robust error checking. I was a bit ambitious though and I put it into a single thread. This meant that the maximum speed I got it to operate at was only 38400. It's rather messy because of all the compromises I had to make, but you're welcome to the code for reference if you like. I'll contact you directly so I can email you the code.

Anyway, be careful how you split the threads. This depends very much on the features you want to use and the highest bit rate you need for the UART. It will be much easier to write and achieve timing if you split the Rx and Tx onto separate threads. You also want to think carefully about where you perform the buffering (on the Rx/Tx thread or on a thread driving those threads).

I've just rewritten the UART code for the xmos.com site which should be up shortly. I've implemented two very basic UARTs, so it's not of direct interest to you, but may be useful reference.
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

The new UART code has now been published on xmos.com http://www.xmos.com/applications/comms/uart

It has two UART implementations: a simple two thread implementation, and a single thread implementation. Neither of them feature multiple Rx sample or I/O buffers, but they are an interesting start point for development.
User avatar
leon_heller
XCore Expert
Posts: 546
Joined: Thu Dec 10, 2009 10:41 pm
Location: St. Leonards-on-Sea, E. Sussex, UK.

Post by leon_heller »

uart.h seemed to be missing when I tried to build the examples.
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

leon_heller wrote:uart.h seemed to be missing when I tried to build the examples.
It's there in module_uart.1v0/src/uart.h

Did you follow the instructions for importing it into XDE? This is in the README file. You need to make sure you tick all the checkboxes when you import the project.
User avatar
leon_heller
XCore Expert
Posts: 546
Joined: Thu Dec 10, 2009 10:41 pm
Location: St. Leonards-on-Sea, E. Sussex, UK.

Post by leon_heller »

Thanks. I imported it incorrectly, it's OK now.
User avatar
ahenshaw
Experienced Member
Posts: 96
Joined: Mon Mar 22, 2010 8:55 pm

Post by ahenshaw »

Something weird is happening. I've taken the one-thread uart code, written some convenience functions, and put it with the following code

Code: Select all

#include <platform.h>
#include "uartlib.h"

on stdcore[0]: port term_port_rx = PORT_UART_RX;
on stdcore[0]: port term_port_tx = PORT_UART_TX;


void Status(chanend fromTerminal, chanend toTerminal)
{
	// example application
	chputs(toTerminal, "\n\rHello World!\n\r");
	for(int i=0; i < 1000000; i++){
		if (!(i%10000)) {
			chputi(toTerminal, i);
			chputs(toTerminal, "\n\r");
		}
	}
}

int main(void) {
  chan toTerm;
  chan fromTerm;
  par {
    on stdcore[0]: uartHandler(toTerm, fromTerm, term_port_tx,  term_port_rx, 38400);
    on stdcore[0]: Status(fromTerm, toTerm);
  }
  return 0;
}
it works perfectly. The above code runs in a fraction of a second, as you might expect. However, if I replace

Code: Select all

on stdcore[0]: Status(fromTerm, toTerm);
with

Code: Select all

on stdcore[1]: Status(fromTerm, toTerm);
then the program slows to a crawl (taking 27 seconds). What am I missing?
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

? Nothing springs out.

I assume you're on a G4 device. Do you get part of the Tx message then a pause of 27s then the rest in a burst?

There is a slightly longer latency with channel communications across cores, but at 38400 that should pale into insignificance.

Any chance you could post your chputi/s functions?
User avatar
davelacey
Experienced Member
Posts: 104
Joined: Fri Dec 11, 2009 8:29 pm

Post by davelacey »

If you are using an XC-1, have you put it in program mode?

http://www.xmos.com/published/xc-1-quick-start-guide
User avatar
ahenshaw
Experienced Member
Posts: 96
Joined: Mon Mar 22, 2010 8:55 pm

Post by ahenshaw »

Program mode was the problem. I found a post referring to that in another thread. Like the author of that post, I had gotten so used to not needing to do that when I was doing single-core programs, that I completely forgot about it. Everything is smooth, now. Thanks!