Thursday, 2 December 2010

XSVF Player on MicroBlaze (JTAG Interface)

This post describes how to implement a JTAG configuration device using C and general purpose input/output (GPIO) on a MicroBlaze based embedded sytem. A Digilent NEXYS-2 board and Xilinx ISE/EDK 10.1.03 are used for this example.

The code is based on Xilinx Application Note XAPP058 and the code provided with it.

An example EDK project can be downloaded here.

The idea is to:
  • run the system provided on a NEXYS-2 board.
  • connect the JTAG port of a another FPGA/ FPGA board to GPIO of the first one.
  • download the configuration file for the devices on the second board in XSVF format to the RAM of the NEXYS-2 board.
  • run the XSVF player on the NEXYS-2 board in order to configure the devices on the second board.
Here are the steps to be taken in a bit more detail:

A. Prepare the configuration file for the device(s) you want to configure:

  1. Create BIT file(s) for the devices you want to configure.
  2. Use Xilinx IMPACT tool to create an XSVF file for the device(s) you want to configure. This works simply by running impact in GUI mode, setting up a project with all devices of the target board in the configuration chain and assigning BIT files.
    The final step is then to go to Output -> XSVF File -> Create XSVF File in order to generate the XSVF configuration file that can be used by the XSVF player.

B. Create the hardware and software for the NEXYS-2 board:
  1. download the example EDK project, unzip it and open it in EDK.
  2. use Device Configuration -> Update Bitstream to create the BIT file for the NEXYS-2 board, which contains the MicroBlaze based hardware system.
  3. go to a console and change into the "code" subfolder within the EDK project folder.
  4. open the "Makefile" in a text editor and adjust the two variables EDK_PROJECT_PATH and EDK_LIB_PATH to point to the EDK project paths where you have unzipped it to on your harddisk.
  5. go back to the console and type Make to build the XSVF Player software application. Note that you now should have an ELF file "xsvf_player.elf" in the "code" folder.

C. Download and run the hardware and software system / configuration files:
  1. connect a Xilinx programming cable to the NEXYS-2 board.
  2. connect a serial cable to the NEXYS-2 and your PC for MicroBlaze OS printfs.
  3. connect the GPIO used for the XSVF Player to the JTAG port of the second board you want to configure.
  4. go to the top-level folder of your EDK project and configure the Spartan FPGA on the NEXYS-2 board:
    impact -batch ./etc/download.cmd
  5. go to the "code" folder containing the compiled ELF file of the XSVF Player.
  6. run the Xilinx Embedded Debugger XMD: xmd and download/ run the ELF file:
  7. connect mb mdm -cable type xilinx_platformusb port usb21
  8. stop
  9. dow -data 0xcbf00000
  10. dow JTAG_SVF_Player_MBlaze/xsvf_player.elf
  11. run
  12. exit
  13. after exiting XMD:
  14. change the serial port specified in the Python script "comm_mblaze.py" to the one where your NEXYS-2 board is attached, save and
  15. run the Python skript, which communicates with the FPGA:
  16. ./comm_mblaze.py
  17. when you are asked for input, type "R" and "Enter". This will then run the XSVF Player that reads the configuration file for the target device(s) from RAM and configure them.

Notes:

  • The JTAG signals are written to a log-file on your computer if you specify the flag -DDEBUG_MODE in the Makefile (see Makefile).
  • In case you do not have a target device attached, which can deliver appropriate TDO signals, you can do a DUMMY run by specifying -DDEBUG_TDO_DONTCARE in the Makefile (see Makefile).
  • In the example above, you can store the XSVF configuration file wherever you want in the RAM, by specifying other addresses within the RAM (see item 9). Make sure to change the address in "defines.h" as well.

Friday, 15 October 2010

Install Player-Stage Robot Simulator under Linux

Make sure to install the necessary packages (particularly for graphics output)

sudo aptitude install libfltk-dev libfltk
sudo aptitude install autoconf automake

If someting fails during ''autoreconf -i'' later, fire up Synaptic and check whether the **latest** version is installed!


It's worth installing Player/Stage locally in your home!

This example will assume the PATH from below

cd
mkdir player-stage
cd player-stage

NOTE after installation, you'll end up with folders 'bin', 'include' and 'lib' here, which represents the local installation tree.


Check out the sources for player-stage from their SVN

I recommend version 2.1, as it is the most stable so far.

svn co https://playerstage.svn.sourceforge.net/svnroot/playerstage/code/player/branches/release-2-1-patches/ player-2.1
svn co https://playerstage.svn.sourceforge.net/svnroot/playerstage/code/stage/branches/release-2-1-patches/ stage-2.1


Install Player

INSTALL PLAYER FIRST! Stage is a module to Player and is compiled afterwards.

cd player-2.1
autoreconf -i
./configure --prefix=$HOME/player-stage/ps-2.1
make install

NOTE after running "autoreconf", insert the following line into "Makefile.am":
ACLOCAL_AMFLAGS = -I m4,

and the following one into "configure.ac":
AC_CONFIG_MACRO_DIR([m4])


Install Stage

Set the player/stage environment variables:

export PKG_CONFIG_PATH=$HOME/player-stage/ps-2.1/lib/pkgconfig
export PATH=$PATH:$HOME/player-stage/ps-2.1/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/player-stage/ps-2.1/lib

Configure and install stage:

cd stage-2.1
./bootstrap
./configure --prefix=$HOME/player-stage/ps-2.1
make install

NOTE after running "autoreconf", insert the following line into "Makefile.am":
ACLOCAL_AMFLAGS = -I m4,

and the following one into "configure.ac":
AC_CONFIG_MACRO_DIR([m4])

Now you should be good to go using Player/Stage



Tweaks & Error Messages During Install and how to Resolve Them


* glibc detected * ./stage_prob_controller: double free or corruption (!prev): 0x093e46d0 *

This is an old glibc++ error, which can be solved by setting the environment variable:

export MALLOC_CHECK_=0


Compile your own STAGE module: stage_test.cpp:21: error: ‘VERSION’ was not declared in this scope

You need to copy a config header file from the stage directory:

cp $HOME/player-stage/stage-2.1/config.h $HOME/player-stage/include/stage-2.1/
cp $HOME/player-stage/player-2.1/config.h $HOME/player-stage/include/player-2.1/


Stage is running and you want to know which TCP port it is listening on?

netstat --inet --tcp -lp

will tell you on a Linux box


In case of an error "unable to open color database"

sudo mkdir /usr/X11R6/lib/X11
sudo cp /etc/X11/rgb.txt /usr/X11R6/lib/X11/rgb.txt



Running a simple example from the include examples


Start the world simulator

player $HOME/player-stage/stage-2.1/worlds/simple.cfg


Start an example player (robot) from the included C++ examples

$HOME/player-stage/player-2.1/examples/libplayerc++/randomwalk



How to compile and run your own examples


Set the player/stage environment variables:

export PKG_CONFIG_PATH=$HOME/player-stage/lib/pkgconfig
export PATH=$PATH:$HOME/player-stage/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/player-stage/lib


Compile the demos

make OR
make files


Run Stage (check the Makefile for commands)

make start


Run your player (controller), for example

./prob_controller

Cross-compile Player/Stage for the ARM architecture (E-Puck)

Although the example given refers to an ARM based embedded system running Linux on an E-Puck robot, the procedure should be similar for any robot platform. As long as the target architecture is an ARM processor running Linux of course.

Important things to consider when compiling player for the E-Puck:

  • install the Embedian Armel cross-compiler + libraries (see above)
  • download the library "libtool" (works at least up to libtool 2.4 incl. libltdl 7.3 on the E-Puck) and install using "configure" as described above. NOTE it is important to put the libraries into the tool-chains "lib" folder!
  • download and install the "boost" library (recommended version: boost 1.34.1) (http://goodliffe.blogspot.com/2008/05/cross-compiling-boost.html)

FIRST: convince the "boost" build system to use your cross-compiler:

cd ./boost_1_34_1/tools/jam/src
./build.sh
cp bin.linux/bjam .
export PATH=/boost_1_34_1/tools/jam/src:$PATH
cd ../../../
add the following line to "./tools/v2/user-config.jam"
using gcc : 4.3 : /usr/bin/arm-linux-gnueabi-g++ ;


NOTE this does NOT work using "configure", instead use:

bjam -d2 --toolset=gcc '-sBUILD=release static multi/single' link=static --prefix=/usr/arm-linux-gnueabi --layout=system --with-thread --with-signals --with-filesystem install
bjam -d2 --toolset=gcc '-sBUILD=release static multi/single' --prefix=/usr/arm-linux-gnueabi --layout=system --with-thread --with-signals --with-filesystem install

to create both, static and dynamically linked libraries.

Finally, you can compile "player" as described above, although tell "configure" to use the cross-compiler!

Cross-Compiler for ARM Based Embedded System

Installing a cross-compiler for ARM

For an embeded Debian3 operating system, Emdebian4, on an Armel5 (ARM/ATMEL) processor. The cross-compiler toolchain will be installed on a Linux box running Ubuntu 10.04 (Lucid Lynx).

Adding Embedian repositories to the aptitude install system

sudo gedit /etc/apt/sources.list

Add the following lines to that file:

#
# -- Emdebian cross toolchains
#
deb http://buildd.emdebian.org/debian/ lenny main
deb-src http://buildd.emdebian.org/debian/ lenny main

NOTE: Since late 2010, the repository location has been changed to:

# deb http://www.emdebian.org/debian/ unstable main
# deb http://www.emdebian.org/debian/ testing main
deb http://www.emdebian.org/debian/ lenny main
deb-src http://www.emdebian.org/debian/ lenny main

In order to verify and be able to use the repositories they have to be authenticated via GPG.

The simple way to do this is:

sudo apt-get install emdebian-archive-keyring

If you want to do it manually, please check http://www.emdebian.org/packages/keys.html.


Installing the tool-chain via aptitude

sudo apt-cache search armel
sudo apt-get install linux-libc-dev-armel-cross
sudo apt-get install libc6-armel-cross libc6-dev-armel-cross
sudo apt-get install binutils-arm-linux-gnueabi
sudo apt-get install gcc-4.3-arm-linux-gnueabi
sudo apt-get install g++-4.3-arm-linux-gnueabi

In the case of library version conflicts the following might help:

sudo apt-get autoremove


Installing the cross-tools own aptitude and dpkg

The embedian tool-chain comes along with it's own package management, that will allow you to install pre-compiled versions of essential basic libraries that will make it easier to get going.

sudo apt-get install apt-cross dpkg-cross

Update the list of available software and list/install packages using:

sudo apt-cross -a armel -u
sudo apt-cross -a armel -l
sudo apt-cross -a armel -i


Using the Embedian cross-compiler

In order to compile code using the cross-compiler, you need to tell your PC explicitly to use it.

NOTE that the binaries created do NOT run on your PC as they are compiled to run on an ARM architecture! You can check for which platform etc. a file is by displaying it's ELF header:

readelf -h


Custom Makefile

Make sure that the following variables are set in your Makefile/environment:

CC = arm-linux-gnueabi-gcc (or arm-linux-gnueabi-g++)
CXX = arm-linux-gnueabi-g++

If you want to link static libraries, which can be helpful in the case of embedded systems where not necessarily all libraries are available as dynamically linked versions on the target system, use:

CFLAGS += -static


Software that uses the "configure" workflow (usually the case!)

./configure --prefix=/usr/arm-linux-gnueabi --host=arm-linux-gnueabi

E-Puck Link to Demos that run on the PIC Processor

You can find some demos that get the lights flashing on the E-Puck robots here:

http://www.gctronic.com/doc/index.php/E-Puck/

WLAN network setup for E-Puck and Linux Box

Setting up network for AD-HOC (point-to-point between PC and E-Puck)

We are working with a private local network using static IP addresses!

Add entries to file "/etc/network/interfaces" (on the PC):

auto wlan0
#iface wlan0 inet dhcp
iface wlan0 inet static
address 192.168.0.100
network 192.168.0.0
netmask 255.255.255.0
broadcast 192.168.0.255
#pointopoint 192.168.0.1
wireless-mode ad-hoc

and ''"/etc/network/interfaces"'' (on the E-Puck)

auto wlan1
#iface wlan1 inet dhcp
iface wlan1 inet static
address 192.168.0.1
network 192.168.0.0
netmask 255.255.255.0
broadcast 192.168.0.255
#pointopoint 192.168.0.100
wireless-mode ad-hoc


Invoke on both systems either

sudo /etc/init.d/networking restart

or

sudo ifdown wlan0 (or wlan1)
sudo ifup wlan0 (or wlan1)



Setting up network for ACCESS POINT (the PC needs a wireless router attached)

We are working with a private local network using static IP addresses!

Add entries to file "/etc/network/interfaces" (on the PC)

auto wlan0
#iface wlan0 inet dhcp
iface wlan0 inet static
address 192.168.0.100
network 192.168.0.0
netmask 255.255.255.0
gateway 192.168.0.200 (address of router!)
broadcast 192.168.0.255
wireless-essid 'name'
#wireless-key 1234567890
wireless-mode managed

and "/etc/network/interfaces" (on the E-Puck)

auto wlan1
#iface wlan1 inet dhcp
iface wlan1 inet static
address 192.168.0.1
network 192.168.0.0
netmask 255.255.255.0
gateway 192.168.0.200 (address of router!)
broadcast 192.168.0.255
wireless-essid 'name'
wireless-mode managed
#there is a line missing adjusting the power, look up on E-Puck


Invoke on both systems either

sudo /etc/init.d/networking restart

or

sudo ifdown wlan0 (or wlan1)
sudo ifup wlan0 (or wlan1)

Tuesday, 6 July 2010

Python Matplotlib: Using Scientific Number Format on Axes

This post will help you with formatting the numbers on axes of your graphs, if you are using Python Matplotlib. When the data you are plotting exceeds a pre-defined value range, Matplotlib will automatically switch to using scientific number formatting.

However, sometimes this can happen a bit erratic or you might want to always use scientific notation (which might be good practice in most cases anyways). This can be done via the following set of commands:

yfm = axScatter.yaxis.get_major_formatter()
yfm.set_powerlimits([ -3, 3])

In order to use these command, matplotlib needs to be included, of course. For plotting examples in Python please refer to the Matplotlib Example Gallery.