Sample project with Uart on startkit Topic is solved

New to XMOS and XCore? Get started here.
hessa59
Active Member
Posts: 37
Joined: Sat Mar 18, 2017 7:19 pm

Sample project with Uart on startkit

Post by hessa59 »

I have imported the uart library into my startkit project and am getting all kinds of errors.
Does anyone know where I can find some simple sample code for using a simple transmit only uart on the startkit?

I have tried the sample code from the programming guide but the compiler doesn't seem to like the tile[0] stuff from the sample code.

I get errors about multi tile applications.
I know that the startkit has one tile reserved for debugging.

Any help would be greatly appreciated!


View Solution
User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am
Contact:

Post by mon2 »

Here is what works for me with the UART library importing w/StartKit:

1) use the latest toolkit Version: Community_14.2.4 (build 15898, Dec-20-2016)

2) Create an empty project -> apply your name of choice to this project -> select the StartKit as the target. Leave the rest as default on this page.

3) Locate the library lower left of the screen -> Serial Peripherals -> UART library -> double click and allow for the importing of this library into your project

4) double click the makefile -> check the box under USED MODULES which should read as lib_uart.

5) Enter your empty source file in your project -> create a main routine (mine was just empty) - to only remove this as a possible error for the compiler.

6) Clean and rebuild your project and lots of required files for this lib_uart should also be imported and built in the process.

In the end, the target .xe binary file should be built and without errors using the above steps.

From memory, what baud rates do you wish to communicate ? If you are fine with non-standard baud rates then this IP is fine to use as-is. If you are interested in framing to perhaps PC compatible baud rates (ie. 19200, 115200, etc.) then you will need to apply an external clock oscillator (3v3 swing) onto any free single bit port. Valid choices are 14.7456 Mhz if you wish to communicate @ 921k for example or slower and be PC compatible. Some of the UART IP can support speeds like 10Mbps but then you cannot of course use RS232 transceivers at such speed. Rather, will need RS422 or RS485 or LVDS. Also, such transceivers cannot be slew rate limited at such high speeds. A wiser choice is to source the $8 USD PLL (Si5351A) from Adafruit. Using the StartKit as an I2C bus master, you can generate any clock value you wish and then feed this custom clock into a free single bit port to allow for your XMOS UART IP to frame at any baud rate you wish (but within limits of the IP of course).

Source code using the StartKit and the Adafruit Si5351A PLL is posted here:

http://www.xcore.com/viewtopic.php?f=44&t=4647&start=10
hessa59
Active Member
Posts: 37
Joined: Sat Mar 18, 2017 7:19 pm

Post by hessa59 »

Hello mon2

Thanks for your very detailed reply!

It may take me a little while to try it out as I will need to set up the clock source etc.

On my previous attempt the compiler also tried to download files. It successfully down loaded the GPIO library but was not able to down load the assert library which I added manually.

Is the following sufficient for the main in order to start the build? (Step 5)

int main(){

return 0;
}
Or do I also need some includes?

My actual intent is connect an FTDI virtual serial port cable for the purposes of debugging and testing control from a PC. Using printf to the console is creating timing issues. I was hoping that the uart would be on its own logical core and therefore not interfere with the timing of other tasks.

Eventually the device will be controlled from c# using the virtual serial port on the PC. I think it may be possible to use non standard baud rates because it is a virtual port.
User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am
Contact:

Post by mon2 »

If you are only wanting this to remove the blocking issues with printf, then review this solution:

https://www.xmos.com/support/tools/docu ... ion=X1093A

https://www.xmos.com/download/private/D ... 93A%29.pdf

You will want:

Run a program with xTAG output enabled
hessa59
Active Member
Posts: 37
Joined: Sat Mar 18, 2017 7:19 pm

Post by hessa59 »

Hi mon2

I also want to be able to control the startkit from the serial link so I will need to get the serial library working. Using your instructions I was able to at least get the uart library to compile with my project :)

However, I seem to have inconsistent behaviour on my system in regards to the Uart library loading other files. When I first tried on my own, the uart library pulled in the Gpio library but failed when trying to pull in the assert library.
Following your instructions it failed to pull in the GPIO library but when I manually added it I got the project to build.

I am currently trying to write some code so I can test it with my FTDI cable (with the hope that it works with non standard baud rates)

I have not been able to find any code in the link that you sent me that actually uses the port. It is mainly about setting up the clock.

It could be that the code is in the following link.

https://www.xmos.com/download/private/lib_i2c-

Unfortunately this link seems to be broken :(

Anyway thanks for all your help! I am certainly much closer.
User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am
Contact:

Post by mon2 »

Hi. You have many options but agree there may not be a complete public project using the StartKit & UART components.

From past reviews, we did manage to create a bit banged UART without an external crystal / clock source that could frame fine with PC baud rates. Keep in mind that the XMOS cores are ultra fast GPIO ports. Only thing faster is to skip to FPGA devices. So keeping this in mind one idea to explore is:

1) configure your FTDI controller so that you are working only with the CMOS (3v3) levels. NO RS232 unless you have a RS232 transceiver on the XMOS port pins as well. You will kill the XMOS CPU if are not careful !!

2) Connect any free single bit port (tons on J7 of your kit) -> wire that to the FTDI UART RX (again direct = 3v3 levels and NOT RS232). If you have RS232 then you must find a way to disable or source another FTDI board or apply a RS232 transceiver onto the XMOS. Recommend you stick with CMOS to CMOS interfacing at this time. Connect a common ground between XMOS board and your FTDI cable.

3) Now, write a simple single thread piece of code to output to the selected port pin -> UART basics = STAR BIT + delay + 8 data bits (delay between each bit) + stop bit. Send out the single character "A" using this logic. Keep tweaking your delays till you can see "A" on the FTDI tool with a terminal program. XMOS has precision delays which can be dialed up to frame @ 115200 bps, etc. We recall doing this for even faster rates.

The XMOS UART libraries are doing the same thing but often you do not need the extra fat of such software IP. It is a great learning method to test the code as posted above. Search around for "BIT BANG UART" to understand what needs to be done in the s/w. Time permitting, can post some code over the next few days but will not have access to lab instruments till Monday.

The XMOS tools allow to create a s/w oscilloscope to monitor the details of the selected single port pin, etc. or you can even connect a simple LED with a current limit resistor to 3v3 OR use a meter to check on your work. Start with:

Code: Select all

your_port_pin <: 1; // force the port pin to be a "1"
while(1);
run the above and confirm your port pin is a "1" and then

Code: Select all

your_port_pin <: 0; // force the port pin to be a "0"
while(1);
run the above and confirm your port pin is a "0" and then

Code: Select all

#include <timer.h>

#define delay 1000

while(1)
{
your_port_pin <: 1; // force the port pin to be a "1"
delay_milliseconds(delay);
your_port_pin <: 0; // force the port pin to be a "0"
delay_milliseconds(delay);
}
and your port pin should now pulse @ 1 Hz. Expand your code using this idea and once the delay is matching say 9600 bps, you will indeed see the character you send from XMOS being framed on the FTDI tool.

Now all this pain goes away if you do source a compatible clock source and apply this external clock onto yet another free single bit port pin. Using this external clock, you can inform the XMOS code to spit out or read in bits based on the external clock edges. Compatible clock values are 1.8432 Mhz, 14.7456 Mhz, or multiples of.


well, well, have a look at this complete code posted here:

http://www.xcore.com/viewtopic.php?f=21&t=5263

Courtesy of Leon Heller but modded for your StartKit:

Code: Select all

#include <platform.h>

#define BIT_RATE 115200
#define BIT_TIME XS1_TIMER_HZ / BIT_RATE

void txByte(unsigned char);
unsigned char rxByte(void);

out port TXD = XS1_PORT_1F;  // J7 connector Pin 1 on StartKit
in port   RXD = XS1_PORT_1H;  // J7 connector Pin 2 on StartKit

unsigned char array[10];

int main()
{	
	//unsigned char c;
	int i;
	
	while (1)
	{
		for (i = 0; i < 10; i++)
			array[i] = rxByte();
		for (i = 0; i < 10; i++)
			txByte(array[i]);			
	}
	
	return 0;
}

unsigned char rxByte(void)
{
   unsigned data = 0, time;
   int i;
   unsigned char c;
   
   // Wait for stop bit 
   RXD when pinseq (1) :> int _; 

   // wait for start bit
   RXD when pinseq (0) :> int _ @ time;  
   time += BIT_TIME + (BIT_TIME >> 1);
   
   // sample each bit in the middle.
   for (i = 0; i < 8; i += 1)
   {
      RXD @ time :> >> data;
      time += BIT_TIME;
   }

   // reshuffle the data.
   c = (unsigned char) (data >> 24);

   return {c};
}

void txByte(unsigned char c)
{
   unsigned time, data;
   
   data = c;
   
   // get current time from port with force out.
   TXD <: 1 @ time;
   
   // Start bit.
   TXD <: 0;
   
   // Data bits.
   for (int i = 0; i < 8; i += 1)
   {
      time += BIT_TIME;
      TXD @ time <: >> data;         
   }
   
   // two stop bits
   time += BIT_TIME;
   TXD @ time <: 1;
   time += BIT_TIME;
   TXD @ time <: 1; 
}

You will need to customize the port pins using for example J7 row on the StartKit to map the TX & RX pins.

Study and do try this out @ 115200 bps and chime back if you have issues. Best to create an empty project with the StartKit as the target and then cut & paste the above source code into the empty project and compile. Connect your TX on XMOS to the CMOS FTDI RX; your RX on XMOS to the CMOS FTDI TX; common ground. Run a terminal program on your PC @ 115200 N81 framing. Then send out some character or text using this UART to test.
hessa59
Active Member
Posts: 37
Joined: Sat Mar 18, 2017 7:19 pm

Post by hessa59 »

Hi mon2

Wow that's great! The 115200 baud seems to be magical. I was actually able to get the library to work at 115200 using the FTDI cable.

I have created a demo program that talks to the tera term vt terminal program using the FTDI cable. It sends one of three strings to the terminal continuously depending on a command received from the terminal.

a) command 'l' lowercase letters a to z

b) command 'u' upper case letters A to Z

c) command 'n' numerals from 0 to 9

Note: It only works at 115200

Code: Select all

/*
 * uart5.xc


 *
 *  Created on: Apr 15, 2017
 *      Author: hessa59
 *      Program used to demonstrate the use of the uart library with
 *      the start kit
 *      Note this program works at 115200 baud. Other baud rates
 *      may not work or result in strange behaviour
 *      It was tested with a 5 volt FTDI cable with FTDI rx coming straight from the start kit
 *      FTDI tx goes through 5 volt to 3.3 volt translation. The terminal program is Tera Term Vt
 *
 *      sendTask -> continuously prints one of three sequences of characters
 *      1) Capital letters A to Z
 *      2) Lowercase letters a to z
 *      3) Numbers 0 to 9
 *
 *      It receives commands from receiveTask
 *      'l' -> lowercase
 *      'u' - > uppercase
 *      'n' -> numbers
 *
 *      It issues a Bel tone to the terminal program when each command is processed.
 *      It sends three BELS in rapid succesion if a non valid command is issued.
 *
 *      receiveTask -> listens for commands and sends them to sendTask. It also buffers
 *      the commands ie if you type u l u l , you will get upper and lowercase print outs in succession
 *
 *
 */

#include <xs1.h>
#include <platform.h>
//#include<print.h>
#include <stdio.h>
#include <uart.h>
#include <gpio.h>


#define RX_BUFFER_SIZE 20
#define CARRIAGERETURN 0x0D
#define LINEFEED 0x0A
#define BELL 0x07

//both of these ports are available on the GPIO header
port p_uart_rx =  XS1_PORT_1E;
port p_uart_tx =  XS1_PORT_1H;

//receive buffer
#define RX_BUFFER_SIZE 20

//interface to send commands from receive to send
typedef interface iReceiveToSend{
    void commandFromConsole(char command);
}iReceiveToSend;


void sendTask(client uart_tx_if i_tx,server iReceiveToSend iS){
 static char firstLetter='A';
 static char lastLetter='Z';
 static char letterIndex;

    while(1){
        select {
            case iS.commandFromConsole(char command):

                i_tx.write(BELL);
                if (command=='l')
                {
                    firstLetter='a';
                    lastLetter='z';
                }
                else if (command=='u')
                {
                     firstLetter='A';
                     lastLetter='Z';
                 }
                else if (command=='n')
                 {
                       firstLetter='0';
                       lastLetter='9';
                 }
                else{
                    i_tx.write(BELL);
                    delay_milliseconds(150);
                    i_tx.write(BELL);
                    delay_milliseconds(150);
                    i_tx.write(BELL);
                }

                break;
        default:
            letterIndex=firstLetter;
            while (letterIndex<=lastLetter){
                i_tx.write(letterIndex);
                letterIndex++;
                delay_milliseconds(100);
            }

            i_tx.write(CARRIAGERETURN);
            i_tx.write(LINEFEED);
            break;
        }
    }
}

void receiveTask(client uart_rx_if i_rx,client iReceiveToSend iR ){
    static char inChar=0;


    while(1){
    select {
        //notification raised by receive library
        case i_rx.data_ready():
            inChar = i_rx.read(); // get char and clear notification
            iR.commandFromConsole(inChar); // send command to send task
    break;

    }
    }

}

int main(){

    // interface to uart library
    interface uart_rx_if i_rx;
    interface uart_tx_if i_tx;

    //interface between receive and send tasks
    //sender is server to recive client
    interface iReceiveToSend iRTS;

   // interface to g[io library
    input_gpio_if i_gpio_rx[1];
    output_gpio_if i_gpio_tx[1];


    par{
        //output gpio/uart tasks
        output_gpio(i_gpio_tx, 1, p_uart_tx, null);

        uart_tx(i_tx, null,
        115200, UART_PARITY_NONE, 8, 1,
        i_gpio_tx[0]);

        //input gpio/uart tasks

        input_gpio_with_events(i_gpio_rx, 1, p_uart_rx, null);
        uart_rx(i_rx, null, RX_BUFFER_SIZE,
        115200, UART_PARITY_NONE, 8, 1,
        i_gpio_rx[0]);

        // scans serial input port for commands
        receiveTask(i_rx,iRTS);

        //outputs either uppercase/lowercase alphabet or numerals
        sendTask(i_tx,iRTS);
    }
    return 0;
}
I may have to switch to the hard coded bit bang method you have suggested at a later date as my program uses 4 cores for this simple task
Creating uart5.xe
Constraint check for tile[0]:
Cores available: 8, used: 4 . OKAY
Timers available: 10, used: 4 . OKAY
Chanends available: 32, used: 7 . OKAY
Memory available: 65536, used: 13636 . OKAY
(Stack: 2504, Code: 10266, Data: 866)
Constraints checks PASSED.
Build Complete

I am not sure how to place resources on a particular core on the startkit because every time I try to use the tile[x].core[y] syntax I get errors.

Once again a hearty thanks for all your help. I not sure of the proper forum etiquette here. Should I be clicking on a check mark to give you the credit for solving this? :)
Last edited by hessa59 on Mon Apr 17, 2017 2:07 pm, edited 1 time in total.
User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am
Contact:

Post by mon2 »

Hi. Sounds like you had a productive weekend :) Excellent on the progress.

The following syntax should work inside the par construct:

Code: Select all

on tile[x].core[y]:
here is an example of the same in use:

lines 49 & 50:

https://github.com/xmos/lib_uart/blob/m ... rc/main.xc

reference:
https://www.xmos.com/published/xmos-pro ... =B&page=23
Once again a hearty thanks for all your help. I not sure of the proper forum etiquette here. Should I be clicking on a check mark to give you the credit for solving this? :)
You are quite welcome. I think so. Then I believe the thread is marked as solved. Perhaps the accumulated points will lead to a new washer & dryer someday :)
Attachments
xmos_syntax.png
(41.44 KiB) Not downloaded yet
xmos_syntax.png
(41.44 KiB) Not downloaded yet
hessa59
Active Member
Posts: 37
Joined: Sat Mar 18, 2017 7:19 pm

Post by hessa59 »

Hi mon2

Great I will mark it as solved. However I think I should note for other readers that there may be an issue with using the examples you have cited above with the startkit because it reserves one tile for the debugger. I will save this issue for another thread. Thanks again!
ColtonEd
Newbie
Posts: 1
Joined: Sat Jul 29, 2017 2:16 pm

Post by ColtonEd »

hessa59 wrote:Hi mon2

Great I will mark it as solved. However I think I should note for other readers that there may be an issue with using the examples you have cited above with the startkit because it reserves one tile for the debugger. I will save this issue for another thread. Thanks again!
Oh so it reserves a tile for the debugger. That makes sense now, thanks Hessa.
Post Reply