I spent the whole yesterday battling with an ATMega16U4 microcontroller. I was trying to set the fuses to use the internal RC-oscillator instead of the external crystal oscillator. In the end I had to modify my avrdude.conf but the problem with the fuses ended up being pretty simple…

Adding support for ATMega16U4 to avrdude

Well the first problem was that even the SVN version of avrdude does not seem to support the ATMega16U4 AVR. I had to resort to modifying the /etc/avrdude.conf. What I did was I copied the ATMega32U4 block and modified it (changed the memory sizes, pages, id, desc, signature) to suit the ATMega16U4:

#------------------------------------------------------------
# ATmega16u4
#------------------------------------------------------------

part
id = "m16u4";
desc = "ATmega16U4";
signature = 0x1e 0x94 0x88;
has_jtag = yes;
# stk500_devcode = 0xB2;
# avr910_devcode = 0x43;
chip_erase_delay = 9000;
pagel = 0xD7;
bs2 = 0xA0;
reset = dedicated;
pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1",
"x x x x x x x x x x x x x x x x";

chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0",
"x x x x x x x x x x x x x x x x";

timeout = 200;
stabdelay = 100;
cmdexedelay = 25;
synchloops = 32;
bytedelay = 0;
pollindex = 3;
pollvalue = 0x53;
predelay = 1;
postdelay = 1;
pollmethod = 1;

pp_controlstack =
0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
hventerstabdelay = 100;
progmodedelay = 0;
latchcycles = 5;
togglevtg = 1;
poweroffdelay = 15;
resetdelayms = 1;
resetdelayus = 0;
hvleavestabdelay = 15;
chiperasepulsewidth = 0;
chiperasepolltimeout = 10;
programfusepulsewidth = 0;
programfusepolltimeout = 5;
programlockpulsewidth = 0;
programlockpolltimeout = 5;

idr = 0x31;
spmcr = 0x57;
rampz = 0x3b;
allowfullpagebitstream = no;

memory "eeprom"
paged = no; /* leave this "no" */
page_size = 8; /* for parallel programming */
size = 512;
min_write_delay = 9000;
max_write_delay = 9000;
readback_p1 = 0x00;
readback_p2 = 0x00;
read = " 1 0 1 0 0 0 0 0",
" x x x x x a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";

write = " 1 1 0 0 0 0 0 0",
" x x x x x a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" i i i i i i i i";

loadpage_lo = " 1 1 0 0 0 0 0 1",
" 0 0 0 0 0 0 0 0",
" 0 0 0 0 0 a2 a1 a0",
" i i i i i i i i";

writepage = " 1 1 0 0 0 0 1 0",
" 0 0 x x x a10 a9 a8",
" a7 a6 a5 a4 a3 0 0 0",
" x x x x x x x x";

mode = 0x41;
delay = 10;
blocksize = 8;
readsize = 256;
;

memory "flash"
paged = yes;
size = 16384;
page_size = 128;
num_pages = 128;
min_write_delay = 4500;
max_write_delay = 4500;
readback_p1 = 0x00;
readback_p2 = 0x00;
read_lo = " 0 0 1 0 0 0 0 0",
" 0 a14 a13 a12 a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";

read_hi = " 0 0 1 0 1 0 0 0",
" 0 a14 a13 a12 a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";

loadpage_lo = " 0 1 0 0 0 0 0 0",
" x x x x x x x x",
" x x a5 a4 a3 a2 a1 a0",
" i i i i i i i i";

loadpage_hi = " 0 1 0 0 1 0 0 0",
" x x x x x x x x",
" x x a5 a4 a3 a2 a1 a0",
" i i i i i i i i";

writepage = " 0 1 0 0 1 1 0 0",
" a15 a14 a13 a12 a11 a10 a9 a8",
" a7 a6 x x x x x x",
" x x x x x x x x";

mode = 0x41;
delay = 6;
blocksize = 128;
readsize = 256;
;

memory "lfuse"
size = 1;
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0",
"x x x x x x x x i i i i i i i i";

read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0",
"x x x x x x x x o o o o o o o o";
min_write_delay = 9000;
max_write_delay = 9000;
;

memory "hfuse"
size = 1;
write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0",
"x x x x x x x x i i i i i i i i";

read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0",
"x x x x x x x x o o o o o o o o";
min_write_delay = 9000;
max_write_delay = 9000;
;

memory "efuse"
size = 1;
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0",
"x x x x x x x x x x x x i i i i";

read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0",
"x x x x x x x x o o o o o o o o";
min_write_delay = 9000;
max_write_delay = 9000;
;

memory "lock"
size = 1;
read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0",
"x x x x x x x x x x o o o o o o";

write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x",
"x x x x x x x x 1 1 i i i i i i";
min_write_delay = 9000;
max_write_delay = 9000;
;

memory "calibration"
size = 1;
read = "0 0 1 1 1 0 0 0 x x x x x x x x",
"0 0 0 0 0 0 0 0 o o o o o o o o";
;

memory "signature"
size = 3;
read = "0 0 1 1 0 0 0 0 x x x x x x x x",
"x x x x x x a1 a0 o o o o o o o o";
;
;

This seemed to work because now avrdude would read and deal with the ATMega16U4.

Problem with setting the fuses

After I got avrdude working I was still unable to set the fuses, they would read out just fine but writing them had no effect (the value stayed the same). I even started debugging the programming bus with my logic analyzer because I just couldn’t figure out why it was not working. Just before I was going to bed I noticed this:

ATMega16U4 lock bits

ATMega16U4 lock bits

The external oscillator version ships with the lock bits PROGRAMMED and the internal oscillator version (ATMega16U4RC) has the lock bits UNPROGRAMMED?

So I did a chip erase (this changes the lock bits to 1) and after that the fuse bits programmed just fine.

Remember to read your datasheets carefully!


One Response so far.


  1. Volodymyr says:

    Thank you very much for the information!

Leave a Reply