Lesson 2: Setting up the toolchain

In this lesson we will be setting up the MSC430-GCC toolchain. The version of the toolchain available at the time of this writing is MSP430-GCC 5_00_00_00 which includes the first stable release of GCC 6.x. This new version is maintained by SOMNIUM Technologies, who has actually provided a Linux installer. However, I will show you how to compile it from source instead. I want to go through this exercise because the compiler for your target may not always be available in a pre-packaged binary or the version available may be older than required.

In the last lesson, we already installed gcc in our virtual machine. However the version of gcc that is available in the repositories is built for your host architecture, in our case x86. Compiling code for a target that is a different architecture than your host machine is called cross-compiling. We will build a gcc (using gcc) which runs on an x86 machine, but compiles machine code for the MSP430. So to start, fire up your virtual machine, open a browser and go to TI’s download site. At the bottom in the “Products Downloads” table, you should download these two files:

  • msp430-gcc-6.2.1.16_source-full.tar.bz2
  • msp430-gcc-support-files-1.198.zip

The first archive contains the toolchain source code. The second contains device specific support files. Navigate to the location where these files were downloaded.

Building the toolchain

Building the toolchain takes long so you can download this build script which basically executes all the following commands without you having to sit around and wait for each one to complete. Make sure to first change the permissions so the script is executable and then run the script as root.

chmod u+x msp430_gcc_build.sh
sudo ./msp430_gcc_build.sh

While that runs, lets take a look at how we get the toolchain up and running. First, the following environment variables need to be set.

export PREFIX=/opt/msp430-toolchain
export TARGET=msp430-none-elf
export PATH=$PREFIX/bin:$PATH

We don’t want them to be system wide or persistent so they are set only in the context of our shell. To do so use the export command. The environment variables defined are:

  • PREFIX – the directory where your cross-compiler will be installed – I typically install my toolchains under the “/opt” directory
  • TARGET – the target architecture in the format <arch>-<target-os>-<abi/output> or something of that nature (its not really well defined). In our case the arch is msp430, target-os is none because it will be bare metal development, and output is elf format
  • PATH – the system path, already defined but we must add location of the binaries we will build to it

We also have to install some packages that are required to compile the toolchain.

sudo apt-get install texinfo expect libx11-dev g++ flex bison libncurses5-dev

Briefly this is what each of them is for:

  • texinfo: utility to help create documentation in various formats
  • expect: program which talks to other programs interactively, used in scripts
  • libx11-dev: X11 windowing system development package
  • g++: gnu C++ compiler (we only installed the C compiler last lesson)
  • flex: fast lexical analyser generator
  • bison: parser generator
  • libncurses5-dev:  screen handling and optimization package, basically a terminal upgrade

Now extract the first package containing the source code.

tar xvf msp430-gcc-6.2.1.16_source-full.tar.bz2

This might take a while… If you are not familiar with the tar command, it is a very widely used archiving utility which supports multiple compression algorithms. The command line parameters we passed are as follows:

  • x – extract
  • v – verbose
  • f – for file, always followed by the filename of the file you want to compress/extract

If you want to learn more about the tar command you should read the man page (i.e. “man tar” in the command line).

Navigate to the newly created directory msp430-gcc-6.2.1.16_source-full. There are several directories which are the individual components required to build the entire toolchain. Technically, gcc itself is only the compiler. The toolchain consists of many other packages which perform various tasks such as assembling, linking, built-in functions, debugging, etc… A standard C library (libc) is also typically included unless you are developing an operating system. In this case, newlib is the C library included but there are plenty others available such as glibc and uClibc. In each of these directories the following steps need be performed:

  1. configure: the build system generates the makefiles based on the host and target configuration (more on this later)
  2. compile: compile the component into the toolchain binaries using the generated makefiles
  3. install: install the binaries in their final location

Gcc itself requires some additional prerequisites and symbolic links to the standard C library.

pushd gcc
source ./contrib/download_prerequisites
ln -fns ../newlib/libgloss libgloss 
ln -fns ../newlib/newlib newlib
popd

The first command pushd  is another way to change directories, similar to cd but it pushes the current directory into a stack. You can later pop that directory off the stack using the popd command and return to the last directory.

The source command  runs the script and downloads those libraries alongside the compiler source. These libraries are mostly software implementations of arithmetic operations that the hardware does not support (i.e. division, floating point).

The ln command is for creating links, in this case passing the arguments –fns creates symbolic links. The symbolic links created are to the standard C library source in newlib. Using symbolic links makes them appear as if they are actually in the gcc directory, when they are in fact located up a level in the newlib directory. The standard C library is required because it is built with gcc and provides the standard C header files.

Next the build directories are created.

mkdir build
cd build
mkdir binutils
mkdir gcc
mkdir gdb

One very important note about compiling the GNU toolchain is you don’t compile it in the source directory. If you try, you are very likely to get build errors. Instead, for each component, we create it own build directory: one for binutils, one for gcc (and newlib) and one for gdb.

The build environment is based on automake/autoconf, so the configure script must be run first.

pushd binutils
../../binutils/configure --target=$TARGET --prefix=$PREFIX --program-prefix=msp430- --enable-languages=c --disable-nls
make
sudo make install
popd

Configuring the build can be fairly complicated to understand because there can be many required or optional parameters that that change the way the application is built. The parameters are application specific, so just because you know how to configure one application, doesn’t mean you know all the options for the next. Basically what happens when you run configure is the script analyses your system for various dependencies and from the information it collects, it is able to generate makefiles, configuration files and sometimes header files that will be compatible with your system. If you are not familiar with makefiles, don’t worry about it for now, there is a lesson dedicated to them. Sometimes dependencies cannot be resolved in which case the configuration (or build) will fail.

In the case of GNU toolchain the configure script accepts many arguments but only a few are required in most cases. The target and prefix argument are as described above in the environment variables section. The program-prefix simply adds a prefix to all the binary files, so for example gcc will become msp430-gcc. This is useful when you want to have one makefile that can build the same code for many architectures. For example, if I wanted compile main.c for both msp430 and arm, I could define my compiler as $(target)-gcc and then configure with target=msp430 to use msp430-gcc or configure with target=arm to use arm-gcc. The disable-nls flag tells the build to disable Native Language Support (NLS) which basically means GCC only outputs diagnostics in English. Finally, enable-languages tells the build system to compile only the specified programming languages – in this case C and C++. If you are interested in the many other options for gcc compilation you can read all about them here.

The next command, make, compiles the source code and the output is stored in the current build directory. If you need to completely clean your build directory or rebuild from scratch,  the make distclean target is supposed to do this for you but in my experience it is often not effective. Its easier and safer to just delete the whole build directory and start again.

Did the compilation finish? If not take a coffee break…

Once it is done, the output files from the compilation need to be installed. The command sudo make install copies all the required files from the build directory to the directory specified by the environment variable PREFIX. It must be run as root because the /opt directory is read-only by default.

The same procedure has to be repeated for each of the other source directories. First for the gcc itself:

pushd gcc
../../gcc/configure --target=$TARGET --prefix=$PREFIX --program-prefix=msp430- --enable-languages=c --disable-nls
make
sudo make install
popd

And finally for gdb – the GNU debugger:

pushd gdb
../../gdb/configure --target=$TARGET --prefix=$PREFIX --program-prefix=msp430- --enable-languages=c --disable-nls
make
sudo make install
popd

Note that the same parameters are passed to the configuration script for each of these builds. This seems to work fine, however the README file provided suggests disabling certain features but does not indicate why.

Adding the support files

The final step is to install the device support header and linker files. These are provided separately from the toolchain source in the second archive downloaded. The files need to be extracted but since it is a zip, it is a slightly different than before. Go back to the download directory run the unzip command.

unzip msp430-gcc-support-files-1.198.zip

Unzip will be extract the files to the a directory named msp430-gcc-support-files. It contains an include directory in which you will see all header files and linker scripts for each MSP430 device. The header files include all the device specific definitions and memory locations for registers and peripherals. The linker scripts tell the linker how to map various sections of code to physical memory locations on the device. Although they are all packaged together, the header and linker files belong in different locations in your installation. Use the following commands to copy the files to the appropriate location.

cd msp430-gcc-support-files/include
chmod -R 644 *
sudo cp *.ld $PREFIX/msp430-none-elf/lib/430/
sudo cp *.h $PREFIX/msp430-none-elf/include

The second command is used to change the permissions of the files so they can be read by any user. This way the user compiling does not need to have root privileges. The location where the files are copied to is defined by the toolchain. If you put them somewhere else, you will have to explicitly point to them when compiling your code.

And there you have it. Next lesson I will give you your first piece of code to compile, introduce you to the various utilities that come with the compiler and show you how to program and run the application on the MSP430 Launchpad.