<<

Simple UART

The intention of this module is to implement high speed uart, at the expense of threads and 1-bit ports. Other modules provide lower-speed uarts that are thread-efficient, or that may use fewer 1-bit ports. This module will support a 10 Mbaud rate with 100 MIPS threads, and correspondingly less with lower MIPS per thread.

Note: the compiler inserts a spurious ZEXT and SETC in two places which makes 10 Mbit fail with 83 MIPS threads.

Hardware Platforms

This UART is supported by all the hardware platforms from XMOS having suitable IO such as XC-1,XC-1A,XC-2,XK-1,etc and can be run on any XS1-L or XS1-G series devices.

The example is prepared to run on teh XK-1 but can be easily modified for other boards. However note that a 500 MHz core clock is expected so when running on G4 devices the baud rate should be reduced until it works, which can be done by altering the last “clocks” argument to the call to uart_tx_fast and uart_rx_fast in app_uart_fast/src/main.xc.

Programming Guide

API

void uart_rx_fast(in port p, streaming chanend c, int clocks)

This function implements a fast UART.

It needs an unbuffered 1-bit port, a streaming channel end, and a number of port-clocks to wait between bits. It receives a start bit, 8 bits, and a stop bit, and transmits the 8 bits over the streaming channel end as a single token. On a 62.5 MIPS thread this function should be able to keep up with a 10 MBit UART sustained (provided that the streaming channel can keep up with it too).

This function does not return.

Parameters:
  • p – input port, 1 bit port on which data comes in
  • c – output streaming channel - read bytes of this channel (or words if you want to read 4 bytes at a time)
  • clocks – number of clock ticks between bits. This number depends on the clock that you have attached to port p; assuming it is the standard 100 Mhz reference clock then clocks should be at least 10.
void uart_tx_fast(out port p, streaming chanend c, int clocks)

This function implements a fast UART.

It needs an unbuffered 1-bit port, a streaming channel end, and a number of port-clocks to wait between bits. It waits for a token on the streaming channel, and then sends a start bit, 8 bits, and a stop bit. On a 62.5 MIPS thread this function should be able to keep up with a 10 MBit UART sustained (provided that the streaming channel can keep up with it too).

This function does not return.

Parameters:
  • p – output port, 1 bit port on which data should be transmitted
  • c – input streaming channel - output bytes of this channel (or words if you want to output 4 bytes at a time)
  • clocks – number of clock ticks between bits. This number depends on the clock that you have attached to port p; assuming it is the standard 100 Mhz reference clock then clocks should be at least 10.

Example programs

Declare ports (and clock blocks if you do not want to run the ports of the reference clock):

clock refClk = XS1_CLKBLK_REF;

in port rx = XS1_PORT_1A;
out port tx = XS1_PORT_1B;

A function that produces data (just bytes 0..255 in this example)

void produce(streaming chanend c) {
    for(int i = 0; i < 256; i++) {
        c <: (unsigned char) i;
    }
}

A function that consumes data (and in this example throws it away)

void consume(streaming chanend c) {
    unsigned char buf[256];
    unsigned char foo;
    for(int i = 0; i < 200; i++) {
      c :> buf[i];
    }
    for(int i = 0; i < 200; i++) {
      printhexln(buf[i]);
    
    }
}

And a main par that starts the threads:

int main(void) {
    streaming chan c, d;
    configure_out_port_no_ready(tx, refClk, 1);
    configure_in_port_no_ready(rx, refClk);
    clearbuf(rx);
    par {
        produce(d);
        consume(c);
        uart_tx_fast(tx, d, 100);
        uart_rx_fast(rx, c, 100);
    }
}