Xmos_getting Started With Examples

download Xmos_getting Started With Examples

of 24

description

Getting started with a new micro-controller

Transcript of Xmos_getting Started With Examples

  • XMOS startKIT: Introduction, Terminology/Architecture,

    Getting Started and Example Programs Posted by shabaz in Internet of Things on May 5, 2014 12:56:00 AM This is part 1 in a series of XMOS startKIT posts. The following topics are covered here:

    Introduction/Terminology/Architecture

    Running Tasks in Parallel

    XMOS and IoT

    Installing the development environment xTIMEcomposer

    Building and running an Example Program

    Example: Controlling a Servo

    Example: Multi-tasking

    Troubleshooting/Debugging

    Part 2 is called XMOS startKIT: Building an XMOS and Raspberry Pi Robot XMP-1 and it covers these topics:

    Robot introduction. Hardware and Software overview and Circuit/Wiring diagram

    Serial Peripheral Interface (SPI) introduction

    Connecting the Raspberry Pi to the XMOS startKIT

    SPI implementation on the XMOS and Raspberry Pi boards

    Implementing multiple servo control

    Creating a Raspberry Pi web server and application using Javascript and Node.js

    Hardware assembly of a robot

    Part 3 is called XMOS startKIT: XMOS and Raspberry Pi Oscilloscope XAE 1000 and it covers these topics:

    Oscilloscope Introduction

    SPI transmit and receive between the Raspberry Pi and the XMOS startKIT

    Using the analog to digital converter (ADC) on the startKIT

    Real-time traces/graphics in a web browser

    Introduction This post documents how to get started with XMOS startKIT which is an interesting board recently released (well, 5 months ago). The board is only slightly larger than a credit card (less than a centimetre longer) and packs an XMOS chip with multiple

    processors (more on that later), built-in 4-channnel ADC, touch sensors, integrated programmer/debugger, LEDs, switch and

    places for connectors. It costs under 12 including VAT (also available from Newark).

    It was found that the XMOS startKIT is fantastic at handling timed events and multitasking. The development environment is

    fairly straightforward to use (it is based on Eclipse), and the programming language is C with a few extensions to handle

    multitasking requirements. Today, if you want to handle input/output at a relatively high speed with very high accuracy and ease-

    of-use, XMOS devices are very high up on the list of suitable devices.

    The startKIT has a connector placeholder which is ideal for communicating to the Raspberry Pi, however for these first steps the

    board was used standalone. (Note - to use with a Raspberry Pi, a DIL pin header strip is required and a ribbon cable assembly; the

    board is not intended to be plugged on top).

    For some initial experiments the XMOS board was used to connect to a hobby servo, and the on-board LEDs were used to test

    multitasking capabilities. A great debugging tool called XScope was also tried out briefly. Information on all that is further

    below.

  • First, some terminology needs to be addressed. It can be confusing, because the terminology used to describe XMOS technology

    has changed over time. So, the terminology and architecture is discussed below briefly. It can be skipped if you want to just get

    on with setting up the XMOS programming environment and running some demo code. You probably do want to read it at a later

    stage though.

    XMOS Terminology and Architecture We are used to hearing about multi-cored chips which have multiple processors per chip, or at least multiple instances of most

    parts of a complete processor. In XMOS terminology, the term core means multiple instances of some parts of a complete processor and the sharing of some things not present on non-XMOS processors. This may sound like a bad thing, but read on and

    you'll find it isn't. In fact the implementation is a good thing for certain tasks; the kind of tasks that embedded systems often

    require. (Ill call these cores XMOS cores from now on, to make it clear). Totally unique non-shared instances of groups of XMOS cores can be placed on the same silicon; these unique instances are called tiles in XMOS terminology. A diagram can say a thousand words; the diagram below (taken from the xCORE architecture PDF document) shows in red the

    XMOS cores (8) per tile (two tiles in this diagram).

  • The device on the startKIT also happens to contain two tiles, each with 8 XMOS cores. One tile is available for user programs

    (tile #1), the other one (tile #0) is dedicated as a debugger on the startKIT.

    XMOS have taken many of the essential bits of operating systems (i.e. traditionally software-based) and have implemented them

    in hardware. This means that you dont need to run (say) uC/OS or other lightweight real-time OSs, and you can still achieve multi-tasking.

  • In addition, you get ultra-low jitter, latency and the ability to prescribe timing (things still extremely difficult to achieve with

    traditional real-time OSs on conventional processors) for one of the main things youd want an embedded processor to handle - input/output.

    This is the kind of stuff that is possible with FPGAs, and with non-XMOS processors running at a very high speed, but XMOS

    devices allow you to do this automatically with no software overhead, and with a standard programming language C with a few extensions. The extensions are designed to be as simple as possible to use (almost FPGA test-bench like) for handling I/O

    timing, and the message-passing/process synchronisation concepts are expressed as close as possible to the way conventional

    OSs handle this.

    This all sounds impressive (and it is), but XMOS devices take this a step further and make the message-passing/process

    synchronisation transparent to the programmer, so that the actual execution can occur between XMOS cores residing on the same

    tile, or on separate tiles on the same physical chip, or on separate chips connected with wire links. The hardware responsible for

    all that is known as xCONNECT (shown in blue on the right side in the diagram above). Again, some terminology needs

    explaining; xCONNECT is a term that appears to encompass links and switches. The links and switches allow the connection

    between the cores, regardless of where they reside. The links and switches are used to create point-to-point virtual circuits or

    channels which can be opened up for as long as required, to pass information. The channels can traverse multiple physical chips to get to the correct destination. Each chip is connected to its closest neighbours using one or more sets of wire links (for a short

    distance of the order of several centimetres; for a longer distance additional circuitry would be required). At any one time

    multiple channels can exist; there is a quality of service scheme that exists too.

    Back to the XMOS cores in a tile; as mentioned earlier, each XMOS core has some dedicated hardware, and some shared

    hardware. The dedicated part is a separated set of registers per XMOS core. The shared part is memory and pipeline, but also a

    hardware scheduler used for implementing the process state and dispatching instructions into the pipeline in a round-robin

    fashion. Another major part of the secret sauce concerns the ability to timestamp events. XMOS instructions can be used to let an

    XMOS core sleep until one of a number of events occurs (such as a pin going high); when the event does occur, there is no delay

    waiting for a context-switch (which entails copying registers to memory and vice-versa) to occur as with a regular software-based

    OS. The scheduler merely needs to change the state so that that the sleeping XMOS core can execute. This is therefore fast and

    saves many clock cycles.

    You may be wondering how timing can be guaranteed if XMOS cores can sleep. It is true that when many XMOS cores are

    asleep, the remainder ones will run faster. However, you can guarantee that the amount of processing time that each running one

    will receive will be a minimum of 1/x processor cycles, where x is the total number of XMOS cores currently running within a

    tile. The guarantee allows you to know beforehand if your code can execute in time to handle input/output. Actual I/O will still be

    timed precisely because I/O is time stamped. You can schedule input to be captured at specific times, or to be sent out at specific

    times. If the XMOS core needs to wait until that time occurs, then it will do so, allowing more processing time for the remainder

    running XMOS cores.

    The timestamping is simply a breeze to use. The following line of code will instruct the device to set the pin led logical high after time 100, and then low after a further time 100. Put into a loop, the LED would flash with precise timing. + expand sourceview plain

    1. led @ 100

  • Running Tasks in Parallel Another common task is of course the handling of multiple tasks. As is clear from the earlier text, XMOS cores run in a

    preemptive manner with round robin scheduling. From the main() function it is possible to assign processes to run on separate

    XMOS cores using the following syntax: + expand sourceview plain

    1. par

    2. {

    3. task1();

    4. task2();

    5. }

    It is possible to select specific tiles with some modified syntax (the tiles can be off-board if a configuration file is modified to

    contain the node routing identifiers and routing table).

    Since you may want to achieve some process synchronisation/communication between the cores, there are a few different

    methods of doing this. One simple way is to create a channel (the concept of a channel was described earlier) and send data down

    it. The receiving task can sit and wait for the message using a select statement.

    The main() function can define a channel using the chan variable type, and the tasks can receive it as a parameter. + expand sourceview plain

    1. int

    2. main(void)

    3. {

    4. chan c;

    5.

    6. par

    7. {

    8. task1(c);

    9. task2(c);

    10. }

    11.

    12. // ...

    13. }

    To send a message from one task to another: + expand sourceview plain

    1. c inval:

    4. printf(message received: %d\n, inval);

    5. break;

    6. }

  • The select statement will cause execution to wait for that XMOS core, until a message is received on the channel. When a

    message is received, the hardware scheduler will make the XMOS core active again.

    XMOS and IoT Similar to any other device selection, a determination would need to be made if the XMOS device is suitable for the desired

    application. The device on the startKIT has 8 XMOS cores and 64kbyte of memory on-chip. This is fine for many applications

    (e.g. audio, motor control) but not ideal for some other applications (for example video capture may require a larger buffer).

    Where XMOS devices would absolutely excel in an Internet of Things (IoT) world would be for handling the hundreds of

    protocols in systems that exist today that are not connected to the Internet. XMOS devices make superb protocol engines since

    timing is easy to implement, and quick to code up without relying on interrupt service routines like with conventional CPUs.

    The rest of this post covers installing and getting started with the XMOS startKIT. A few example programs are explored, as well

    as some debugging capabilities.

    Installing xTIMEcomposer For this, youll need to register at xmos.com and download xTIMEcomposer Community version from their support pages. (The screenshots below are for Windows, but the Linux version looked identical. Windows, Mac and Linux are supported, but for

    Linux check to ensure your particular distribution is supported).

    Double-click to install the software, and accept the defaults where prompted. When installed, start it up.

    For documentation, there will be a link in the Windows start menu, which opens a browser with all the online (mostly PDF)

    documentation, and this will be used later. All the documentation there is useful and relevant.

    At the workspace prompt, put in something appropriate for your needs, and select it to be a default if you wish.

    Import an Example Program As a first step, import an example project. To do this, select Community tab as shown here, and then traverse to The spinning bar, right-click and import into the workspace.

  • The example is imported from github. This requires a folder for the import. I created and selected a folder as shown here.

  • Once the project has been imported, you can expand the project hierarchy to view the source code (main.xc file) as shown below.

    Building the project To build the project, first select the top level of the project hierarchy (app_spinning_bar) and then click on the hammer icon, or

    select Project->Build Project.

  • If all goes well with the build, success is reported at the console at the bottom, as shown below. Youll also see the built file (app_spinning_bar.xe) in the bin folder in the project hierarchy, and you can view it in Windows Explorer too if desired as shown

    in the screenshot here.

  • Plugging in the startKIT Now you can plug in the startKIT into your PC if youve not already done so. Note that there is currently a software bug that means that the USB port on the PC must be USB 2.0, not USB 3.0. Some modern laptops have mostly USB 3.0 ports but may

    have a USB 2.0 port perhaps on the back (e.g. Lenovo does this with some ThinkPads). So, plug the startKIT into a USB 2.0 port

    and avoid any USB 3.0 ports for now.

    When plugged into a port, youll see a message appear to indicate that the device is correctly installed.

    Windows device manager could also be checked to confirm all is ok:

  • Running a Program In order to run the code, first select Run->Run Configurations, and then double-click on xCORE Application as shown here.

  • Once youve double-clicked, you should see a display as shown below. You should not have to make any changes here, but just observe to make sure all the highlighted areas look similar. Notice the Target drop-down should say something like XMOS startKIT connected to . If it does not, then click Refresh List. If that doesnt work either, then perhaps the startKIT is plugged into a USB 3.0 port by mistake.

    When Run is clicked, the spinning bar program will get transferred to the startKIT and will begin executing.

    From now on, to run or stop the program directly from the main view, you can use the run and stop icons as shown here:

  • Programming the FLASH To permanently store the program in FLASH, select Run->Flash Configurations. In the window that appears, double-click on

    xCORE Application as shown here:

    The display should look as shown here, but confirm all the marked items, and then click Apply and then click Flash.

  • When you clicked Flash, the console displays some text in red. The warning can be ignored:

  • Once the console says xflash succeeded as shown above, the USB cable can be disconnected and reconnected to make the program run.

    To re-program the FLASH after making any code changes and recompiling, the lightning shaped icon can be used:

  • Controlling a Servo I wrote some quick code to experiment with timing with XMOS. XMOS handles timing quite uniquely, almost hardware test-

    bench language style. Typically with a microcontroller, a clock is set up to interrupt the microcontroller and execute an interrupt

    service routine that can then be used to control input/output. For easier control of the exact timing some microcontrollers have

    dedicated PWM units with quite a bit of flexibility, but nothing like XMOS have implemented.

    As an example with XMOS, for servo PWM, it is possible to use these lines in a loop, where width is a variable corresponding to

    microseconds in this case: + expand sourceview plain

    1. t+=width; servo @ t

  • 3.

    4. clock clk = XS1_CLKBLK_1;

    5. out buffered port:1 servo = XS1_PORT_1F;

    6.

    7. int main(void)

    8. {

    9. int i;

    10. unsigned int t=0;

    11. unsigned int width=1500;

    12.

    13. configure_out_port(servo, clk, 0);

    14. set_clock_ref(clk);

    15. set_clock_div(clk, 50); // 1MHz

    16. start_clock(clk);

    17.

    18. while(1)

    19. {

    20. printf("Enter servo position in microseconds (1500 is center):\n");

    21. scanf("%d", &width);

    22. for (i=0; i

  • In order to experiment with multiple tasks, the simple program here was written, which flashes an X symbol and a + symbol in a pattern. It will flash the X a few times, then flash the + a few times, and then repeat. The code could be written in a single process of course, but it is implemented in two tasks to see how multi-XMOS cores are handled.

    The first bit of the code just defines the LED patterns that will be used: + expand sourceview plain

    1. #include

    2.

    3. /*

    4. * LEDs: the patterns for each bit are:

    5. * 0x80000 0x40000 0x20000

    6. * 0x01000 0x00800 0x00400

    7. * 0x00200 0x00100 0x00080

    8. *

    9. * To get the desired value, OR the bits that

    10. * you want to remain OFF

    11. */

    12. port leds = XS1_PORT_32A;

    13. unsigned int leds_value[]={

    14. 0xE1F80, // Blank

    15. 0xA0280, // Plus symbol

    16. 0x41500}; // X symbol

    17.

    18. port pin = XS1_PORT_1F; // for debugging with a scope

    The next part of the code defines a task which just periodically sends a message to another task: + expand sourceview plain

    1. void task1(chanend c)

    2. {

    3. while(1)

    4. {

    5. delay_milliseconds(1000);

    6. c

  • 10. {

    11. select

    12. {

    13. case t when timerafter(time+(100*1E5)) :> time: // 100*1E5 is 100msec

    14. if (toggle & 0x01)

    15. {

    16. leds

  • To use XScope, the header file xscope.h needs to be included in the program. Also, double-clock on the Makefile in the Project

    Explorer, and you should see a XMOS Application Makefile Editor appear.

    Traverse to the Xcc Flags section and append -fxscope to the flags list as shown above, and then click File->Save.

    Then, go to Run->Configurations and change the Target I/O options setting from JTAG to xSCOPE.

  • Next, click on the XScope tab, and change the Mode from Disabled to Offline [XScope] Mode as shown below. The, click Apply and then Close.

  • Now the code can be modified to insert the instrumentation. In the main() function, the following line can be added: + expand sourceview plain

    1. xscope_register (1, XSCOPE_STATEMACHINE , " State Transitions ", XSCOPE_UINT, " State ");

    Now, whenever there is a state change, the following code can be added, where x is a number that will represent the state. + expand sourceview plain

    1. xscope_probe_data(0, x);

    I inserted such a line in the main() function, twice in task1 (after each delay_milliseconds function) and in task2 to record the

    LED toggled state.

    When the code is compiled and run, a file gets created called xscope.xmt. Click Terminate to stop the program, and you will see

    the file in the Project Explorer. Double-click the file, and the Offline Scope will appear where the console view was. Check the State checkbox. You will see a view similar to the one shown below (you can use the zoom keys to the right of the console view

    to expand in). This shows the states and the time spent in each state. The states are shown on the vertical axis (marked 0,1, 2,

    etc). Time is on the horizontal axis.

  • XScope is capable of a lot more. It can also plot analog values. For example, the xscope_register function can be called as + expand sourceview plain

    1. xscope_register(1, XSCOPE_CONTINUOUS , " Continuous Value 1", XSCOPE_UINT , " Value ");

    The same xscope_probe_data command as before will now plot analog values. Multiple sets of data can be captured

    simultaneously using this syntax: + expand sourceview plain

    1. xscope_register (3, XSCOPE_STATEMACHINE , " State Transitions ", XSCOPE_UINT, " State ",

    2. XSCOPE_CONTINUOUS , " Continuous Value 1", XSCOPE_UINT , " Value ",

    3. XSCOPE_CONTINUOUS , " Continuous Value 2", XSCOPE_UINT , " Value ");

    Here is an example of analog values output:

  • Summary It was fairly painless to begin to use the startKIT, and although some learning is needed to make full use of it, I think it will be

    worth it.

    At under 12 the startKIT is an extremely low cost board, and will excel at anything timing related.

    For IoT projects, the startKIT would be the ideal device for implementing the hundreds of protocols that exist with industrial

    equipment, some of which would be timing critical.

    For home use, the startKIT is perfect for connecting to the Raspberry Pi (this will be explored later).