Tag Archives: avr

ATmega168 documentation uses word addressing, avrdude uses byte addressing

I was programming USBaspBootloader into a metaboard with an Atmel AVR ATmega168 microcontroller. I always got this error:

usb 6-2: device descriptor read/64, error -71
usb 6-2: device not accepting address 21, error -71

1. USBaspBootloader’s Makefile specifies atmega168 and BOOTLOADER_ADDRESS=3800 by default. This is in hex addressing a byte, i.e. 0x3800. avrdude uses byte-addressing.

ATmega168 documentation refers to 0x1C00 as the bootloader address. This is in hex addressing a word. 0x3800 / 2 = 0x1C00.

So, when programming a bootloader using avrdude, USBaspLoader’s Makefile should have 3800 (the default), not 1C00.

2. bootloaderconfig.h has features enabled that make the bootloader too big (> 2K). I had to turm them off:


All of this was, of course, done under Linux.

Atmel AVR timer/counter examples

Here’s the catch: the timer/counter is capable of operating on a completely hardware level, no software interaction required. A nice explanation is given here (section 2). This page starts with an introduction using a software counter. Which shows how tedious that is, especially counting the clock durations yourself.

Another page at AVRfreaks here deals exclusively with the software implementation, although using the timer/counter registers for counting. This is useless and horribly wrong, that’s not how timers/counters with “output compare” capabilities should be used! The dangerous part is that this article doesn’t even mention the hardware-only implementation.

Atmel’s assembly: branch to address, not label

Say you had this code to wait for n iterations, where n is stored in register arg. You could write:

dec arg
brne wait ; step back to dec

Which would be OK. But if you didn’t have that much free registers, you would probably pass n using the stack. In which case your procedure would grow intensely fucked up, like this:

; (line/s to get argument from stack)
; ...
dec arg
brne wait_dec ; step back to dec

This ain’t good. Instead, branch to a relative adress:

; (line/s to get argument from stack)
; ...
dec arg
brne PC-0x01 ; step back to dec

Making my own USBasp programmer

I’ve been trying to make some for the last two weeks (yes, two weeks). I didn’t use the provided designs, that’s why it took so long: first, I wanted to get apprehended with the UNIX electronics CADs; then, as one should expect, I ran into design trouble of a layout that hasn’t been tested.

So here’s some valuable experience:

0) When developing with a crystal, make sure it’s the first thing you put near the IC! You need minimal distances, remember?

1) Design the PCB while looking at the schematic – you can actually see that C1 and C3 can be put very nicely near the USB connector (pins 1 and 4); R3 right next to it, too (pins 1 and 2); and some components “stick” naturally to the IC. This can be applied to other schematics.

2) check your schematic, not just the PCB. I’ve actually wasted the last week trying to pin-point the cause of a weird behaviour: the programmer can be programmed, the fuses can be set, it works as a stand-alone USB device (when no target is connected) and even when the target (a known-to-work USBasp) is connected, but not set to self-programming mode. As soon as it is (jumper 2 is set), the built USBasp starts to malfunction:

  • if the Brown-Out Detector is enabled (some other fuse combinations also apply), the power LED flickers, and the device is unrecognized;
  • under other configurations, the device simply does not power-on (the LED stays blank);

What I have found out is that I accidentally put JP2 in the wrong place: as you can see on the schematic, the wire that goes out of pin 5 of the ISP socket branches into one that joins the SS, and the other one that goes to ~RESET. Since I’ve redrawn my schematic, I accidentally put the jumper in the wire that goes with the SS.

Now, this has far-reaching complications. First off, this means that ~RESET is always connected to pin 5 of X2. Thus if the programmer is in slave mode (being programmed), the master controls ~RESET when it issues commands, and its +5V (through pin 2, VCCINT) influences the ~RESET through R6 (10K). Cumulatively, this provides the same conditions that would be seen in proper master-mode.

When such a USBasp is a master with no target, or the target is not set to self-programming (target’s JP2 disconnected), then master’s ~RESET is only influenced by the +5V, which comes from the USB. Also no problem here.

But when the target has JP2 set, you effectively have two programmers set to self-programming! This results in a race condition and also a loop, where master feeds the slave with VCCINT, which is then provided back to the master through pin 5 of X2 – and since master has its JP2 “shorted out”, it all effectively sets its ~RESET to +5V!

“Now, that’s pretty fucked up right here!” – you’re going to say; but, actually, this can be worked to an advantage. If you test your programmer on a known-to-work USBasp target, you will immediately notice such non-standart behaviour. If it was a normal target on the other end, you’d have an even bigger hell of a time finding what’s wrong than I did.

Not to mention you’d get a programmer that’s unable to reproduce itself.

3) If this is your first USBasp, build it of discreet components (and let teh ceiling cat be with you, ameh). This way you:

  • can change the IC easily if you misprogram the fuses (say, edit “hfuse” to “lfuse” in avrdude, move the cursor to change the fuse value, and accidentally press Enter instead of Backspace (doh!);
  • can use resistors to “jump” long distances over several lines you’ve already run;
  • know for sure what the values of the capacitors are (!).
  • don’t have to deal with SMT Zener diodes, which might only be available in MINIMELF packages.

4) Along the way, I also got to read some valuabl infoz on how AVR and USB get along.

First tryout of AVRs

I bought a few programmers some time ago. On eBay, for around 16 dollars american. They’re a copy of Thomas’ Fischl’s USBasp. Now I’m toying around with them – a part of my summer internship.

First off, I tried connecting one working programmer to the other and see how it goes. Well, FreeBSD couldn’t recognize it:

avrdude: error: could not find USB device "USBasp" with vid=0x16c0 pid=0x5dc

This is since I’m using a laptop. It has ppi (parallel port interface) in the kernel, but it doesn’t have a parallel port. And avrdude simulates writing to a parallel port for programming, or something like that. So, no /dev/ppi0 – no programming.

So I turned Windows back on and tried the avrdude that comes with WinAVR (version 20080610). It couldn’t locate USBasp also, but for a different reason: the libusb driver that comes with USBasp is outdated or something. The latter link leads to another one, where you can download the new driver. Also, this page with error explanations (linked in the same thread) was somewhat useful.

So, then Windows and avrdude saw the USBasp programmer I was using, but didn’t see the second identical USBasp programmer (known to work) that I used as a target (even if both of them had the green power light on):

avrdude: error: programm enable: target doesn't answer. 1

I set the “self-programming” jumper on the target, but that didn’t help right away. It did turn the target’s “power” LED off.

I additionally had to set the “slow SCK” fuse on both the programmer and the target. Otherwise there was some trouble reading the target chip signature:

avrdude: Device signature = 0x0000ff
avrdude: Expected signature for ATMEGA8 is 1E 93 07
avrdude: safemode read 1, lfuse value: ff
avrdude: safemode read 2, lfuse value: ff
avrdude: safemode read 3, lfuse value: 0
avrdude: safemode: Verify error - unable to read lfuse properly. Programmer may
not be reliable.
avrdude: safemode: To protect your AVR the programming will be aborted

Then I got this:

avrdude: Device signature = 0x1e9307
avrdude: safemode read 1, lfuse value: ff
avrdude: safemode read 2, lfuse value: ff
avrdude: safemode read 3, lfuse value: ff
avrdude: safemode: lfuse reads as FF
avrdude: safemode read 1, hfuse value: d9
avrdude: safemode read 2, hfuse value: d9
avrdude: safemode read 3, hfuse value: d9
avrdude: safemode: hfuse reads as D9

At this point, I could basically dump the target’s memory, program it, etc.. Note that the fuse values on these programmers that I’ve bought are somewhat different from those specified in the USBasp readme.

So to sum up, the jumper positions are:

power: programmer – Vusb, target – Vtarget;
self-programming: programmer – off, target – on;
slow SCK: programmer – on, target – on.

I’ll write up what happens next.