Help save net neutrality! Learn more.
Close

USB Boarduino

USB Boarduino Tutorial

Written by Warren W. Gay VE3WWG

This tutorial was written to save other Arduino folks a lot of trouble getting started with AVR-Ada. While the Arduino IDE is a great place to start, advanced projects may require a make file and the use of Ada. I started out using the Arduino IDE myself, but soon after I also returned to using Ada in other projects. Naturally I pined to use Ada on the USB Boarduino I that had invested in.

If you're like me, you might be short on time and in a hurry. Haste eventually made things take longer for me. So I'll pass on some lessons learned. Consider this the "fast track" if you are hoping to use your Arduino with AVR-Ada.

The hardware in the example used is the USB Boarduino, with the ATmega168 part in the socket.

AVR-Ada Installation

I'm going to assume you have Cygwin installed. Alternatively, you may be using a DOS or MSYS shell instead.

If you're using Linux, you'll need the AVR tool chain installed in place of WinAVR. Linux users may want to use the following documentation as a start:

www.avrfreaks.net/wiki - AVR-GCC

To install AVR-Ada currently (under Windows), you need to download and install:

WinAVR-20100110-install.exe

AVR-Ada-1.1.0.exe

When installing software newer than this, note that the limiting factor will be AVR-Ada. Look for it first and then determine what version of WinAVR it will cooperate with.

Beyond installing them both into the same directory (I used C:WinAVR-20100110), this part is painless.

Part Numbers

Looking at the literature and various software packages, you might conclude that the ATmega328p part designation covers all of it's family members including the ATmega168p, which I was using. While the code may be the same, the architecture resources are different. Most notably the available amount of RAM!

What I discovered later, is that function calls failed to return. This was due to the compiler generating code for the ATmega328p, which has more RAM (2048 bytes vs 1024 for the ATmega168p). So if you're not sure which part you are using then get the magnifying glass out now and specify it correctly. Details count in WinAVR!

AVR-Ada Support for ATmega168p

Once I configured my project to compile with -XMCU=atmega168p, it failed because there was no “built” library support for it. You can easily correct that problem, by doing the following:

C:> CD C:WinAVR-20100110libgnat
C:> MKDIR avr_libatmega168plib
C:> avr-gnatmake -XMCU=atmega168p -P avr.gpr

Once project avr.gpr has been "made" with the part number of your choosing, you should be able to compile your project, as per usual.

Arduino Blink Test

The “blink LED” project is the “Hello World” program in the embedded systems world. The Arduino project describes their flavor of this here:

www.arduino.cc/en/Tutorial/Blink

Assuming you are using an Arduino board, this project is the first thing you should test This will make sure your PC and hardware communicate and work ok together:

  1. Start up the Arduino IDE
  2. Start a new sketch
  3. Paste in the code from the web page cited above (alternatively you may be able to find a "blink" project in example sketches provided).
  4. Be sure to “Verify” it (this compiles it actually), and
  5. Upload it to the board (burn it into the chip).

If the LED blinks on and off, you have proven that:

  1. The communication to the Arduino is working,
  2. The programming facility works, and
  3. The ATmega chip is ok.

If this doesn't work, then try the various Arduino resources and troubleshoot that first. That will be the easiest path to AVR-Ada happiness. In this tutorial, I'm going to assume that the Arduino blink project worked.

Blinky in Ada

Up until this point, I had never needed to use GNAT's “project files”. But avoiding them in AVR-Ada is definitely a bad idea.

Using GNAT's project files will drastically reduce the complexity of your AVR-Ada build process. So it is important to get the essentials of this correct for your first AVR-Ada project. Further, you can use this simple example as a starting point for new projects.

The GNAT Project File

Within my Cygin environment, I created a subdirectory ~/avr for my own avr projects. Under that, I then created subdirectory “blinky”, and changed to that directory (~/avr/blinky). This is what we'll assume for this tutorial.

Within your project directory, you want to create your GNAT project file. Call it blinky.gpr. The following simple one can be used to get started:

with "avr.gpr";

project Blinky is

    package Compiler renames AVR.Compiler;
    package Builder  renames AVR.Builder;
    package Binder   renames AVR.Binder;
    package Linker   renames AVR.Linker;

    for Exec_Dir use ".";
    for Source_Files use ("blinky.adb");
    for Main use ("blinky.adb");

end Blinky;

If you don't follow this general formula and try to specify all the options in the make file (as I did), you will waste several hours. After you give up, you'll then come back to using the above. Save yourself the grief.

The AVR Script (For Cygwin Users)

If you don't use Cygwin, then skip to the next section. The avr script below is designed to allow the native windows avr tools to be temporarily searched first on the PATH. This avoids mixing with Cygwin tools.

Note that I mount /cygdrive/c as /c in my own cygwin environment. If you don't, then substitute /cygdrive/c where you see /c in the example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#!/bin/bash
# Put the C:WinAVR tools in the path and execute cmd:
#

AVR="/c/WinAVR-20100110/bin:/c/WinAVR-20100110/utils/bin"
PATH="$AVR:$PATH

cmd="$1"
shift 1

case "$1" in
    make )        cmd=/usr/bin/make;;
    * )           ;;
esac

exec $cmd $@

# End

You will need to edit the line AVR=... to match where you've installed your WinAVR. The case statement in this script makes certain that the Cywin version of the make command is used. Otherwise, we expect the avr tool chain to be used.

The Makefile

To build this project, we just need a bare bones make file. The first example is for Cygwin, which makes use of the avr script. Non-Cygwin users can review the second Makefile example.

Cygwin Makefile

MCU=atmega168p
AVRDUDE_CONF=C:/WinAVR-20100110/bin/avrdude.conf

all:
    exec avr make avr_all

clean:
    rm -f b~*.ad[sb] *.o *.ali *.hex *.elf

burn:
    exec avr make avr_burn

dump:
    avr avr-objdump -mavr:5 -d blinky.elf

avr_all:
    avr-gnatmake -g -XMCU=$(MCU) -Pblinky.gpr
    avr-objcopy -O ihex blinky.elf blinky.hex

avr_burn:
    avrdude -C $(AVRDUDE_CONF) -v -v -p m168 \
            -c arduino -P COM5 -b 19200      \
            -F -U flash:w:blinky.hex

# End

IMPORTANT: Change the MCU= line if you're using a different AVR chip (this is critical).

You may also need to change the AVRDUDE_CONF= line as well, if your WinAVR was installed differently (theoretically, avrdude should be able to find its own config file, but I don't like leaving things to chance here).

Normal Makefile

If you're using Linux instead, your make file can be simpler:

MCU=atmega168p
AVRDUDE_CONF=/usr/local/etc/avrdude.conf

all:
    avr-gnatmake -g -XMCU=$(MCU) -Pblinky.gpr
    avr-objcopy -O ihex blinky.elf blinky.hex

clean:
    rm -f b~*.ad[sb] *.o *.ali *.hex *.elf

burn:
    avrdude -C $(AVRDUDE_CONF) -v -v -p m168  \
            -c arduino -P COM5 -b 19200       \
            -F -U flash:w:blinky.hex

dump:
    avr avr-objdump -mavr:5 -d blinky.elf

# End

Make Targets

The make "targets" that we will use are:

  • clean - Deletes all avr executables, work files (object files) etc. and “cleans” up your project directory.
  • all - This is the default - “make all” causes a compile and link of your project to occur. In this case, a happy result is to produce the file “blinky.hex”.
  • burn - is designed to use avrdude to upload your program and burn it into the chip.
  • dump - is a programmer convenience, to dump out the assembly code for your executable

Target "all" is the default, if you just enter "make". The Cygwin Makefile translates a target "all" (for example), into "avr_all". This is how you can conveniently access the WinAVR tool chain from a Cygwin session.
This invokes the avr script to temporarily modify the environment PATH for the avr tool chain.

USB Boarduino LED

One of the challenges I faced, was figuring which ATmega port and bit to use in order to turn on and off the “standard” LED on the USB Boarduino. In the Arduino realm, all you care about is that the LED is controlled by “digital pin 13”. The real port and bit is mapped for you in the Arduino library code. Finding out how this mapped to the hardware seemed to be a well kept secret. Perhaps this had more to do with the USB Boarduino's schematic. There was no LED drawn on it (apart from power), even though it is present on the PCB.

The USB Boarduino's schematic labels only “digital pins" 2 through 10. By extension and I should have realized that the “digital pins 11, 12 and 13” must be the ones labeled MOSI, MISO and SCK respectively. Additionally, "digital pins" 0 and 1 are labeled RxD and TxD on the schematic.

After some investigation I was able to conclude that the "standard" LED is controlled by ATmega168 port B, bit 5. This is the one labeled “SCK” on the schematic.

LED Activation Sense

Often an LED is “lit up” when you output a “low” signal. In this case a resistor tied to +5V, with the LED's anode connected to the resistor (+) and the cathode tied to the "output pin". In this circuit, bringing the pin low completes the circuit and lights the LED.

However, for the "standard" LED on the Arduino, it is lit when the output goes “high” instead. This means you must set the bit “true” (1 or high) to light it, and otherwise set it "false" (0 or low) to turn it off.

When things are not working in the beginning, this kind of trivial information is important to know about.

The Blinky Ada Program

There is no mapping of "digital pins" in AVR-Ada like there is in the Arduino. So knowing the port and bit that controls the LED is important to the Ada version of the Blink program (we'll call it “Blinky”).

Create the Ada source file named blinky.adb:

with AVR.MCU;
with AVR.Wait;
use AVR;

procedure Blinky is

    procedure Delay_MS(MS : Natural) is
    begin
        for X in 1..MS loop
            AVR.Wait.Wait_4_Cycles(8000);
        end loop;
    end;

    LED : Boolean renames MCU.PortB_Bits(5);
begin

    MCU.DDRB_Bits := (others => DD_Output);

    loop
        LED := True;
        Delay_MS(600);
        LED := False;
        Delay_MS(200);
    end loop;

end Blinky;

The inner procedure “Delay_MS” is a very crude approximation to milliseconds. It serves our purposes here, however. The argument MS indicates how many milliseconds to waste time for.

The variable named “LED” is a renamed bit from a boolean array:

MCU.PortB_Bits(0..7)

Setting the correct bit True turns on the LED and setting it False darkens it. In the loop coded, the LED stays on longer than it stays off. This helps to prove which sense of the LED activates it.

Build Blinky

From the shell, you should be able to “make” (or “make all”) to build blinky. If you had failed compiles beforehand, it is best to do a “make clean” first. The removal of old files forces a complete rebuild of everything.

$ make
exec avr make avr_all
make[1]: Entering directory `/home/Warren/avr/blinky'
avr-gnatmake -g -XMCU=atmega168p -Pblinky.gpr
avr-gcc -c --RTS=rts/avr5 -gnatec=C:WinAVR-20100110libgnatgnat.adc -gdwarf-2 -gnatwp   -gnatwu -gnatn -gnatp -gnatVn -Os -gnatef -fverbose-asm -frename-registers   -mmcu=atmega168p -gnateDMCU=atmega168p -fdata-sections -ffunction-sections   -g -I- -gnatA F:cygwinhomeWarrenavrblinkyblinky.adb
avr-gnatbind --RTS=rts/avr5 -freestanding -I- -x F:cygwinhomeWarrenavrblinkyblinky.ali
avr-gnatlink F:cygwinhomeWarrenavrblinkyblinky.ali -Wl,--gc-sections -gdwarf-2   -Wl,--relax "--GCC=avr-gcc -Os -mmcu=atmega168p --RTS=rts/avr5 -fdata-sections   -ffunction-sections" -g -LC:WinAVR-20100110libgnatavr_libatmega168plib   -lavrada -o F:cygwinhomeWarrenavrblinkyblinky.elf
avr-objcopy -O ihex blinky.elf blinky.hex
make[1]: Leaving directory `/home/Warren/avr/blinky'
$

When all is successful, you should see a new hex file:

$ ls -ltr
...
-rwxr-xr-x 1 Warren   None   635 2010-07-31 23:41 blinky.hex

It should look something like this:

$ cat blinky.hex
:1000000033C000004CC000004AC0000048C00000DF
:1000100046C0000044C0000042C0000040C00000D4
:100020003EC000003CC000003AC0000038C00000E4
:1000300036C0000034C0000032C0000030C00000F4
:100040002EC000002CC000002AC0000028C0000004
:1000500026C0000024C0000022C0000020C0000014
:100060001EC000001CC0000011241FBECFEFD8E04E
:10007000DEBFCDBF11E0A0E0B1E0ECEDF0E002C0EA
:1000800005900D92A030B107D9F711E0A0E0B1E0E2
:1000900001C01D92A030B107E1F702D01DC0B0CF62
:1000A00000D08FEF84B920E43FE12D9A81E090E009
:1000B000F9013197F1F742E08835940711F0019684
:1000C000F7CF2D9881E090E0D9011197F1F7883CA6
:0C00D000910559F30196F8CFF894FFCF8A
:00000001FF
$

Program Upload (Burn)

This is the moment you've been waiting for. To upload the hex file
to your ATmega chip (the USB Boarduino in my case), you do:

$ make burn
exec avr make avr_burn

make[1]: Entering directory `/home/Warren/avr/blinky'

avrdude -C C:/WinAVR-20100110/bin/avrdude.conf -v -v -p m168 -c arduino -P COM5 -b 19200    -F -U flash:w:blinky.hex

avrdude.exe: Version 5.10, compiled on Jan 19 2010 at 10:45:23
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com
Copyright (c) 2007-2009 Joerg Wunsch

System wide configuration file is
"C:/WinAVR-20100110/bin/avrdude.conf"

Using Port                    : COM5
...
avrdude.exe: verifying ...

avrdude.exe: 220 bytes of flash verified

avrdude.exe done.  Thank you.

make[1]: Leaving directory `/home/Warren/avr/blinky'
$

My USB Boarduino executes the program immediately after the "upload".
However, some Arduinos require a reset and a ten second delay. Hopefully
yours blinked!

Troubleshooting

I spent a lot of time sorting out the parameters used by Arduino for avrdude. The Arduino IDE tends to hide all of this good info from the end user. Here are some things to watch out for and to know about:

  • The config file should be specified to avrdude (especially if you have the Arduino IDE installed). In my case, it was AVRDUDE_CONF=C:/WinAVR-20100110/bin/avrdude.conf. In the make file, this is passed to the avrdude -C option.
  • -v -v helps you see what is happening (very verbose). If you like, reduce or eliminate these from the avrdude command in the Makefile.
  • The part is specified as -p m168 for my Arduino setup. If you're using different parts, you may need to change this.
  • -c arduino indicates that this is an “Arduino” programmer. I suspect that this is key due to the way the chip is reset using one of the serial control signals (RTS?).
  • -P COM5 specifies the Boarduino's serial port on my system. This is the USB virtual com port. Check your device control panel if you need to verify this.
  • IMPORTANT: The “Arduino bootloader” seems to insist on a baud rate of -b 19200.

The above information is about the USB Boarduino, using a chip with an Arduino bootloader in it. If you have a stock chip, or using a different bootloader, then you may need to revisit the avrdude settings.

Summary

Once you have all of the answers (for Arduino), using AVR-Ada is rather straight forward to use. Here are some key points to keep in mind:

  • Make sure the version of WinAVR installed is the one supported by your release of AVR-Ada.
  • For the Arduino, be sure to test out the Arduino C language Blink application first.
  • Use a GNAT project file for your AVR-Ada project, even if you're a stout Makefile only user.
  • When using Cygwin, use the “avr” script to temporarily change your PATH for your AVR tools.

USB Boarduino Notes

  • Specify MCU=atmega168p in the Makefile if you are using the ATmega168p.
  • The avrdude part number for the ATmega168 is -p m168
  • The avrdude programmer is -c arduino
  • The avrdude baud rate is -b 19200

USB Boarduino Pinouts

The following chart is a mapping between the USB Boarduino's outer pins
and the AVR port and pin numbers.

For example, the d5 pin (Arduino's digital 5)
is mapped to AVR port PD5 (port D pin 5).

Left pin AVR Port Notes Right Pin AVR Port Notes
d8 PB0 Digital 8 d7 PD7 Digital 7
d9 PB1 PWM d6 PD6 PWM
d10 PB2 PWM d5 PD5 PWM
d11 PB3 MOSI/PWM d4 PD4 Digital 4
d12 PB4 MISO d3 PD3 PWM
d13 PB5 SCK (Boarduino LED) d2 PDs Digital 2
gnd gnd d1 PD1 TXD
aref Chip pin 21 AREF d0 PD0 RXD
empty
a0 PC0 analog in 0
a1 PC1 analog in 1
a2 PC2 analog in 2 5V VCC 5 volts
a3 PC3 analog in 3 gnd gnd Ground
a4 PC4 analog in 4 3V 3 volts
a5 PC5 analog in 5 reset PC6 Reset

[img src="attachment/Boarduino_Pinout.png"]

avrdude Notes

  • I used programmer type '''-c avrisp'''
  • Baud rate is 19200 ('''-b 19200''')
  • Your port may vary ('''-P COM5''' possibly)

Using your "Device Manager" (Windows) you should be able to narrow it
down. Since you're not likely to have other USB serial ports, there might
only be one showing:

[img src="attachment/USB_Port.png"]

In my case, the port is configured for COM3. But I believe the default
install puts it at COM5. If it shows up in the list, I would try the
COM5 first.

Testing the Programming

I would do a read test first. This will tell you if the programmer is
able to see your Boarduino or not. If not, it may be because the port
was specified incorrectly.

avrdude -C C:\...\avrdude.conf -c avrisp -P COM3 -b 19200 -v -p m168 -U flash:r:"read.bin":r

If it is successful, you should see something like:

avrdude.exe: Version 5.10, compiled on Jan 19 2010 at 10:45:23
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2009 Joerg Wunsch

System wide configuration file is "C:CYGWINusrlocaletcavrdude.conf"

Using Port                    : COM3
Using Programmer              : avrisp
Overriding Baud Rate          : 19200
AVR Part                      : ATMEGA168
Chip Erase delay              : 9000 us
PAGEL                         : PD7
BS2                           : PC2
RESET disposition             : dedicated
RETRY pulse                   : SCK
serial program mode           : yes
parallel program mode         : yes
Timeout                       : 200
StabDelay                     : 100
CmdexeDelay                   : 25
SyncLoops                     : 32
ByteDelay                     : 0
PollIndex                     : 3
PollValue                     : 0x53
Memory Detail                 :

Block Poll               Page                       Polled
Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom        65     5     4    0 no        512    4      0  3600  3600 0xff 0xff
flash         65     6   128    0 yes     16384  128    128  4500  4500 0xff 0xff
lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

Programmer Type : STK500
Description     : Atmel AVR ISP
Hardware Version: 2
Firmware Version: 1.16
Vtarget         : 0.0 V
Varef           : 0.0 V
Oscillator      : Off
SCK period      : 0.1 us

avrdude.exe: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.05s

avrdude.exe: Device signature = 0x000000
avrdude.exe: Yikes!  Invalid device signature.
Double check connections and try again, or use -F to override
this check.

avrdude.exe done.  Thank you.

There is a device signature mismatch shown in the results
but the -F option overrides this and I just ignore it.