Embedded Development with XCode

Jim Schimpf

Introduction

I am always amazed and envious of those who can write complicated GUI applications but being an embedded developer in real life, what really gets me excited is to turn on an LED or flip a relay.  Until OS X there never was much interest or support for embedded development on the Apple Mac, now with the UNIX underpinnings of OS we can can benefit from the huge open source effort supporting small microprocessors.

    What I also want is to be able to use XCode to do the development.  I've been doing my professional embedded systems with an IDE and would very much like this luxury in my amateur efforts.  Putting all the code into a project and having the IDE treat your code as a database so you can find structures, functions and definitions with just a click is almost a necessity once the project grows beyond a few files.

    Using the Mac to do this work requires three things, first the tool chain.  This is the compiler/assembler/linker/loader generator for your particular microprocessor.  Second some hardware + software to load the generated program into the microprocessor.  And third, we are going to show how to manage your project with XCode.

Tool Chain

Tool chains are specific for a microprocessor or family of processors.  In my case I am working with the ATMEL AVR line and specifically the 90s8515.

       ATMEL AVR Processor page

This is part of a whole family of RISC 8 bit micros that can be programmed in-circuit and are relatively cheap.  My choice was made when I acquired a device with one of these in it already and wanted to program it myself.

    Enter the GNU organization, they have developed a very portable C compiler (gcc) that is already used by Apple.  The compiler source is available and is designed to be re-targeted for almost any hardware.  You do need more than just the compiler, you also need a collection of tools to manipulate the output files to create the actual file to load the the micro.  And most important you need a runtime library specifically built for this processor. 

I found this page from Stanford which details how to get the tool chain and install it on your machine. (These instructions would work on most any UNIX box).

    AVR Tool Chain

    You go to this page and download the following 4 parts:

  • binutils    - These are utilities for manipulating the elf and binary files generated.
  • gcc        - This is the C compiler, targeted for the AVR
  • libc        - This is the C runtime library targeted for the AVR
  • usip        - This is a chip programmer designed for x86 machines (optional)

    Since this is a Mac, things are a little simpler.  You can use Stuffit Expander and a double click to expand all the archives, instead of the command line operations.  The configure/make/install operation for each of the four though is exactly the same and while lengthy works just fine on the Mac.

    When all of this is done you have the AVR tools in /usr/local/bin and the other parts in /usr/local/avr.  The tools include avr-gcc, the c compiler, avr-objcopy code extractor and avr-objdump a disassembler/dumper for the output files.  The other parts in /usr/local/avr include the special include files for the AVR processors and the C run time library. You then set /usr/local/bin in the PATH environment variable and you are off to the races.

    At this point you can compile code and build rom images to be downloaded into the processor.  I've included a simple example here that flashes an LED attached to the processor.  It uses a Makefile to build the parts and extract the ROM code. This is example code from MIT Solar Electric Vehicle Team, written by Michael Seeman slightly changed to support the latest tools.  If  your tool chain is correctly installed you should be able to cd to the sample code directory and type make then have the sample.rom loadable binary built.

    The makefile in the above example is very valuable in showing exactly what command line values are needed to compile an application and the link flags needed to build a loadable image.  Also it shows the commands needed after the ELF file is built to extract the binary image. 

Programming the chip

    And here is where the Mac always has a problem.  We have to move the ROM file generated by the tool chain into the chip and need some kind of hardware connection from our computer to the micro.  On x86 type PC's they have the parallel part which on most of those machines is as useful as an appendix but can be used as uncommitted digital I/O to program a chip.  Mac's never had a parallel port or any other kind of port that can be used to do the kind of digital I/O we need.

    To back up a bit the ATMEL chips can be programmed in circuit by wiggling the reset line and then sending in programming commands over the Serial Peripheral Interface (SPI).  On the x86 machines they program the parallel port to do this (see the code of UISP in your tool chain (Universal In System Programmer)).

    On the Mac we can plug digital I/O devices into the USB bus and use those devices like the x86 machines use the parallel port.  I have a Delcom Engineering  USB Development board which gives me 8 digital bits in and 8 bits out and supporting software for OS X.  While not really fast it does do the job and wiring it up to the AVR chip as follows:

PORT 0 (Bit 0 Input) <--- MISO on AVR
PORT 1 (Bit 0 Output) ---> MOSI on AVR
PORT 1 (Bit 1 Output) ---> SCK on AVR
PORT 1 (Bit 7 Output) ---> ~RESET on AVR

Allows programming of the AVR chips. The AVR manual (Serial Programming) gives the steps necessary to program both the program ROM and the chip EEPROM. I've written a program to support this, it reads the ROM file generated by the tool chain and will then program the AVR chip via the Delcom board. The source and Xcode project is here.

The code for USIP was very valuable in showing me exactly how to send out the data via SPI. The manual for the chip shows the SPI waveforms as:
See SPI program waveform from AVR manual

Reading the code in USIP (see TDAPA::SendRecv(int b) in DAPA.C) showed that the clock was inverted compared to the above figure.  As my original code did not work, I then inverted the clock as in USIP and it has worked since. 

Xcode Use

At this point I have a system that will compile C code into ROM images and a tool that will put that binary file into a chip.  Next I wanted to have the code managed by XCode so that it would jump to error lines in code and allow easy point and click access to program functions.

I found this article by Dr. Rolf Jansen on using FreePascal with Xcode.  It showed me how to define scripts that are executed when Xcode compiles and links the code.  Also I found this Apple document that listed the script variables available.

All the code and Xcode project for the following example is here.

Setting Up Xcode for build

  •  Create a new Standard Tool Project in your microprocessor code area
  • Delete the main.c and bring in your microprocessor files
  • Pick the project and Get Info, Pick Styles and scroll down and turn off ZeroLink
Zerolink dialog box
  • Pick the Target and Get Info, Pick the Rules Tab and change the C source files to use a script.  We use the command line from the makefile in the sample code with the variables mentioned in the Apple document.  This will put the .o files into the build directory.  This isn't quite right but will work for now. The output file is specified to be the .o file and ROM file, this is like a make line in that if the thing isn't built yet do what you can to get to the next stage.
Cfile command line data
  • Add a new rule for the *.o files to do the link.  This will use the command lines from the make file to link all the objects into the ELF file and then build the ROM file.  This is not exactly the right way, but I could not find any script variable that had the names of all the .o files or the build phase where to place this.  So we sort of cheat and do the whole operation in a single script.  Suggestions here would be welcome.  Note we specify the ROM file as the output so the script will terminate when the ROM is created.
Object file commands

Using Xcode

    At this point the project will be almost like any regular Mac project.  You can build the code, if you get errors clicking on the error line will take you to the offending line of code.  Double clicking with CMD a highlighted function or constant will jump to where that code is defined.  You can then use this project as the basis for other projects.  Note you must change the .o script for each project, it has to have the names of all the .o's to be linked.  (This is where someone out there is going to tell me the RIGHT way to do this.)

    Clean doesn't seem to work but that is because I put the .o files in the wrong place.  In a standard project they are in build/<name>.build/<name>.build/Objects-Normal/ppc.  Wasn't quite sure how to build that !

Future Work

It would be nice if the debug worked but that would need a micro that would support remote debugging and download.  Someday I hope the Mac will support USB JTAG/BDM pods so we could develop/download/debug on 32 bit processors like embedded PPC's, ColdFires or various DSP's.  The good news is with the UNIX and open source support OS X already has, the tool chains for most processors already exist.  The only things missing from making Mac's tools work for embedded systems are download hardware/software and Xcode support.

Appreciation

    There is a wealth of material out there on programming and using the AVR micros and I thank the various keepers of these sites for making this stuff available.  The folks who build and maintain the tools for this and other processors deserve our thanks for their huge effort making it so easy for us.  Finally I thank the writers of papers mentioned above for taking the time to explain how to get from point A to point B giving me a clue on how to get this stuff working.