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