oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

Embedded Development with Xcode

by Jim Schimpf

I'm constantly 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 Mac OS X, there never was much interest or support for embedded development on the Mac. Now, with the UNIX underpinnings of Mac OS X, we can benefit from the huge open source effort supporting small microprocessors.

What I also want is to be able to use Xcode to for this 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 of 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, which I'm going to explore in this article. First, the tool chain. This is the compiler/assembler/linker/loader generator for your particular microprocessor. Second, some hardware plus software to load the generated program into the microprocessor. And third, a look at how to possibly manage the project in Xcode.

Tool Chain

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

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 source code for it is available and is designed to be re-targeted for almost any hardware. Beyond the compiler, you also need a collection of tools to manipulate the output files to create the actual file to load the micro. And most importantly, you need a runtime library specifically built for this processor.

I found a page from Stanford, AVR Tool Chain, that details how to get the tool chain and install it on your machine. (These instructions would work on most any UNIX box.)

Go to this page and download the following four 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 we're working on a Mac, things are a little simpler. You can use Stuffit Expander and a double-click to expand all the archives--no need for 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; the 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 runtime library. You then set /usr/local/bin in the PATH environment variable, and you're 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 the 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, and 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

Here is where the Mac always seems to have 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 PCs, there is the parallel port, 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. Macs never had a parallel port or any other kind of port that could be used to do the kind of digital I/O we need.

Hmmm, looks like I'm getting a little ahead of myself. 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 x86 machines, they program the parallel port to do this. (See the code of UISP (Universal In System Programmer) in your tool chain.)

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 eight digital bits in and eight bits out and supporting software for OS X. While it's not really fast, it does do the job and wiring it up to the AVR chip is 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

Programming 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 are 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 lists the script variables available.

Setting Up Xcode for Build

  1. Create a new Standard Tool Project in your microprocessor code area.
  2. Delete the main.c file and bring in your microprocessor files.
  3. Pick the project and Get Info, Pick Styles and scroll down and turn off ZeroLink.

    Zerolink dialog box

  4. 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

  5. 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 of 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 of 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. Command-double-clicking with 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 files 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 PPCs, ColdFires, or various DSPs.

The good news is, with its UNIX and open source support, Mac OS X already has the tool chains for most processors. The only things missing from making the Mac's tools work for embedded systems are download hardware/software and Xcode support.


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 the 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.

Jim Schimpf does embedded software development for telecommunications test equipment and develops Mac freeware in his free time, while not doing his other job of tractor repair/general grunt work for his 200-acre farm.

Return to the Mac DevCenter