oreilly.comSafari Books Online.Conferences.


Black Box with a View
Pages: 1, 2, 3

Hello (Embedded) World

When you start programming using an unfamiliar language or operating system, it is very helpful to write a Hello World program. Such simple programs are the first step in understanding the new environment.

For embedded systems, however, a Hello World program has a critical additional role. This role is to verify that the entire development tool chain--especially the target hardware--works. The process of running a program on an embedded platform is quite complex. You write the code on a host machine (typically a PC), compile it with a cross-compiler, and then upload the result onto the target through an interface (such as the JTAG adapter). Numerous problems can arise at each step.

For example, microcontrollers, even in the same family, often differ dramatically from each other. If you give the wrong options to the cross-compiler, or assume the existence of certain hardware features when writing your program, it is quite possible that the target device will be unable to execute the resulting object code.

The target hardware itself is often an early prototype; in the embedded world, it is rare for the electronics design to be completed before software development starts. Hardware errors and component failures--very common in such experimental devices--have a drastic impact on the operation of embedded software.

Finally, uploading the compiled program to the target is not fully reliable; it is not unusual for the transfer to introduce errors into the object code.

As mentioned previously, typical microcontroller applications do not use an operating system. There is no console, no log file, nor any other standard error-reporting mechanism. In consequence, embedded software often fails silently, with no feedback regarding the cause of the fault. In this situation, a simple Hello World program is the key to creating a minimally functional development environment. Example 1 is such a program.

/* This program flashes the LED connected to pin 1 of port 2 on
the MSP430F149.  The easyWeb2 development board has an LED
connected in this way. */

#include <io.h>

int main(void) {

  P2DIR=0xFF;  /* Configure all pins on port 2 as outputs. */
  P2OUT=0x02;  /* Set pin 1 to the high state; all others to
               the low state. The mask "0x01" would set pin 0
               to the high state, "0x04" would set pin 2
               to the high state, etc. */

  for(;;) {
    /* The following two lines implement a very crude delay loop.
       The actual length of the delay can vary significantly.
       This approach may not work with all compilers. */
    volatile int i;        /* Declare "i" as volatile ... */
    for(i=0;i<20000;i++);  /* ... so that this loop will not be optimized. */

    P2OUT=~P2OUT;          /* Toggle the state of all pins on port 2.  Every
                           pin that is high will be set low, and every
                           pin that is low will be set high.  */


Example 1. An embedded Hello World

Note the volatile keyword--a very common occurrence in embedded C development. This keyword most often designates a variable that may be read or written to in the background (usually by an interrupt service routine, or ISR).

The compiler disables many optimizations for a volatile variable (such as caching it in a register). In the example, the delay loop would run much faster if i were not volatile; the compiler could even remove the loop altogether. Some compilers may still render the delay loop ineffective despite the use of volatile, but mspgcc does not do so.

Save the code from Example 1 in a file (such as hello-world.c) and compile it with:

$ msp430-gcc -std=gnu89 -pedantic -W -Wall -Os -mmcu=msp430x149 \
	-o hello-world.elf hello-world.c

This produces the binary file hello-world.elf. Now, load the file onto the target using the pyJTAG tool.

$ msp430-jtag -epv hello-world.elf

You should see a flashing LED on your development board. You may have to type (note the .py extension) instead of just msp430-jtag, depending on how you installed pyJTAG.

If you are not using an easyWeb2 development board, your LED may be connected to a different port and pin of the microcontroller; in that case, you will need to make a minor change to the code. For example, for the TI MSP430 Development Tool model MSP-FET430X140, use port 1 (P1DIR and P1OUT) pin 0 (P1OUT=0x01 instead of P2OUT=0x02).

Choosing the right compiler options is especially important for embedded systems. In particular, note the -mmcu=msp430x149 option, which selects the correct MSP430 family member for the easyWeb2 development board. You will need to change this (see the "Compiler options" section of the mspgcc manual) if you are using a different variant of the MSP430. The -std=gnu89 option selects the ISO C 1989 standard, with GCC extensions. Some mspgcc header files require the extensions in order to compile. gnu89 is currently the default if you do not specify any -std option.

The -Os option tells the compiler to optimize the code for space rather than speed. While space optimization is not necessary in this small example, it is a common requirement when compiling more complex embedded software. In order to improve standards compliance and catch some unsafe constructs in the code, use the -pedantic, -W (capital W), and -Wall options. The GCC manual describes these options in detail. Finally, the -o option specifies the output filename.

It is also important to understand the options to the target programming tool (pyJTAG in this case). The example given uses three single-letter options (-epv). The first option erases all the flash memory of the target device, the second programs the device, and the third verifies the programming operation. The file used to program and verify the device is the last item on the command line in the example. For more information on pyJTAG, use the -h option (msp430-jtag -h or -h), or see the pyJTAG documentation in the mspgcc manual.

The highly primitive nature of the embedded Hello World is deliberate and very important. You want the lowest possible chance of something going wrong. This kind of program is something that you will write many times if you work with embedded systems. If the program runs, you immediately have the answers to several key questions about your development environment:

  • You have figured out how to write a functioning program for your device.
  • The cross-compiler generates the right code for your microcontroller.
  • The process of loading the executable onto the target system works.
  • The hardware is at least minimally functional; there may still be many mistakes, but the microcontroller can run a program, which is the critical first step.

The next article will cover several important embedded development techniques. These design patterns form the foundation for the subsequent discussion of connected embedded systems.

Pages: 1, 2, 3

Next Pagearrow

Sponsored by: