ATtiny1634 avrdude flash write bug and fix

Many avrdude configurations (avrdude.conf), including the latest (6.3) source from www.nongnu.org/avrdude, Debian Stretch, and Raspbian 7 have a bug in the avrdude.conf file that makes it impossible to correctly write to the ATtiny1634.

Reading from the device works fine. Writing to the device flash fails. The problem occurs in some configurations only, including linuxgpio, but not including usbasp.

Using an external programmer can result in a successful write, but has its own issues.

If you dig into it, the problem manifests as images being incompletely written as defective 32-byte stripes every fourth page, with 3/4 of the pages remaining cleared to all-ones.

The bug itself is here:

#------------------------------------------------------------
# ATtiny1634.
#------------------------------------------------------------

part
    id              = "t1634";
    desc            = "ATtiny1634";

...

    memory "flash"
        paged           = yes;
        size            = 16384;
        page_size       = 32;
        num_pages       = 512;

...

        loadpage_lo     = " 0 1 0 0 0 0 0 0",
                          " 0 0 0 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",
                          " 0 0 0 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",
                          " 0 0 0 a12 a11 a10 a9 a8",
                          " a7 a6 x x x x x x",
                          " x x x x x x x x";

To correct it, make these changes:

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

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

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

Explanation:

The 1634 uses 32-byte pages, addressed by 16-bit words (ie. actual address divided by two). "loadpage_lo" and "loadpage_hi" need to be supplied with a word address within a page (0-15), which requires four bits to encode. The original configuration uses six bits ("x x a5 a4 a3 a2 a1 a0"), which is incorrect. When an incorrect address is used with "loadpage_lo/hi", at least on my device, the high bits are ignored, but this may be undefined behaviour. The fix is to use four bits ("x x x x a3 a2 a1 a0"). Remember to change this in two places.

The "writepage" command similarly expects a 32-byte-aligned 16-bit addressed value to be supplied. The original configuration uses all but six bits ("a7 a6 x x x x x x") which is incorrect. The correct value is all but four bits ("a7 a6 a5 a4 x x x x").

The striping is caused by short address in "writepage", which means that only the first page in a four page set is ever written to. The corruption is caused by the long address in "loadpage_lo/hi", which assuming the wraparound behaviour I observed is consistent, means that the same page is being written to with the data from the current and the following three pages.

I am speculating slightly on the cause of the nature of the corruption, but I believe it is consistent and has to do with the properties of flash memory. Generally flash memory is erased per-page to all-ones, and is programmed by flipping bits to zero. In this case, a chip-wide erase clears the whole of flash memory to ones, and the pages are then programmed. Overwriting the same page four times with different data would result in a logical AND of the repeated data over the corresponding bits in each source page. I believe this produces the odd corruption patterns I observed when writing test data to the device, although I haven't confirmed this.

In closing, I include some test data that I had originally posted elsewhere.

Here is the first set of test data:

0000000 0100 0302 0504 0706 0908 0b0a 0d0c 0f0e
0000020 1110 1312 1514 1716 1918 1b1a 1d1c 1f1e
0000040 2120 2322 2524 2726 2928 2b2a 2d2c 2f2e
0000060 3130 3332 3534 3736 3938 3b3a 3d3c 3f3e
0000100 4140 4342 4544 4746 4948 4b4a 4d4c 4f4e
0000120 5150 5352 5554 5756 5958 5b5a 5d5c 5f5e
0000140 6160 6362 6564 6766 6968 6b6a 6d6c 6f6e
0000160 7170 7372 7574 7776 7978 7b7a 7d7c 7f7e
0000200 8180 8382 8584 8786 8988 8b8a 8d8c 8f8e
0000220 9190 9392 9594 9796 9998 9b9a 9d9c 9f9e
0000240 a1a0 a3a2 a5a4 a7a6 a9a8 abaa adac afae
0000260 b1b0 b3b2 b5b4 b7b6 b9b8 bbba bdbc bfbe
0000300 c1c0 c3c2 c5c4 c7c6 c9c8 cbca cdcc cfce
0000320 d1d0 d3d2 d5d4 d7d6 d9d8 dbda dddc dfde
0000340 e1e0 e3e2 e5e4 e7e6 e9e8 ebea edec efee
0000360 f1f0 f3f2 f5f4 f7f6 f9f8 fbfa fdfc fffe

Here's 256 bytes of what I get back:

0000000 0100 0302 0504 0706 0908 0b0a 0d0c 0f0e
0000020 1110 1312 1514 1716 1918 1b1a 1d1c 1f1e
0000040 ffff ffff ffff ffff ffff ffff ffff ffff
0000060 ffff ffff ffff ffff ffff ffff ffff ffff
0000100 ffff ffff ffff ffff ffff ffff ffff ffff
0000120 ffff ffff ffff ffff ffff ffff ffff ffff
0000140 ffff ffff ffff ffff ffff ffff ffff ffff
0000160 ffff ffff ffff ffff ffff ffff ffff ffff
0000200 8180 8382 8584 8786 8988 8b8a 8d8c 8f8e
0000220 9190 9392 9594 9796 9998 9b9a 9d9c 9f9e
0000240 ffff ffff ffff ffff ffff ffff ffff ffff
0000260 ffff ffff ffff ffff ffff ffff ffff ffff
0000300 ffff ffff ffff ffff ffff ffff ffff ffff
0000320 ffff ffff ffff ffff ffff ffff ffff ffff
0000340 ffff ffff ffff ffff ffff ffff ffff ffff
0000360 ffff ffff ffff ffff ffff ffff ffff ffff

The sequence repeats.

Here is the second set of test data:

0000000 feff fcfd fafb f8f9 f6f7 f4f5 f2f3 f0f1
0000020 eeef eced eaeb e8e9 e6e7 e4e5 e2e3 e0e1
0000040 dedf dcdd dadb d8d9 d6d7 d4d5 d2d3 d0d1
0000060 cecf cccd cacb c8c9 c6c7 c4c5 c2c3 c0c1
0000100 bebf bcbd babb b8b9 b6b7 b4b5 b2b3 b0b1
0000120 aeaf acad aaab a8a9 a6a7 a4a5 a2a3 a0a1
0000140 9e9f 9c9d 9a9b 9899 9697 9495 9293 9091
0000160 8e8f 8c8d 8a8b 8889 8687 8485 8283 8081
0000200 7e7f 7c7d 7a7b 7879 7677 7475 7273 7071
0000220 6e6f 6c6d 6a6b 6869 6667 6465 6263 6061
0000240 5e5f 5c5d 5a5b 5859 5657 5455 5253 5051
0000260 4e4f 4c4d 4a4b 4849 4647 4445 4243 4041
0000300 3e3f 3c3d 3a3b 3839 3637 3435 3233 3031
0000320 2e2f 2c2d 2a2b 2829 2627 2425 2223 2021
0000340 1e1f 1c1d 1a1b 1819 1617 1415 1213 1011
0000360 0e0f 0c0d 0a0b 0809 0607 0405 0203 0001

Read back:

0000000 9e9f 9c9d 9a9b 9899 9697 9495 9293 9091
0000020 8e8f 8c8d 8a8b 8889 8687 8485 8283 8081
0000040 ffff ffff ffff ffff ffff ffff ffff ffff
0000060 ffff ffff ffff ffff ffff ffff ffff ffff
0000100 ffff ffff ffff ffff ffff ffff ffff ffff
0000120 ffff ffff ffff ffff ffff ffff ffff ffff
0000140 ffff ffff ffff ffff ffff ffff ffff ffff
0000160 ffff ffff ffff ffff ffff ffff ffff ffff
0000200 1e1f 1c1d 1a1b 1819 1617 1415 1213 1011
0000220 0e0f 0c0d 0a0b 0809 0607 0405 0203 0001
0000240 ffff ffff ffff ffff ffff ffff ffff ffff
0000260 ffff ffff ffff ffff ffff ffff ffff ffff
0000300 ffff ffff ffff ffff ffff ffff ffff ffff
0000320 ffff ffff ffff ffff ffff ffff ffff ffff
0000340 ffff ffff ffff ffff ffff ffff ffff ffff
0000360 ffff ffff ffff ffff ffff ffff ffff ffff

The sequence repeats.

To produce the first set of test data:

#!/usr/bin/ruby -w
fh = File.open ARGV[0], "wb"
for j in 0 .. 15
  for i in 0 .. 255
    fh.write i.chr
  end
end
fh.close

To produce the second set of test data:

#!/usr/bin/ruby -w
fh = File.open ARGV[0], "wb"
for j in 0 .. 15
  for i in 0 .. 255
    fh.write (255-i).chr
  end
end
fh.close

Writing binary data:

avrdude -P gpio -c confignamehere -p attiny1634 -U flash:w:data.raw:r

Reading binary data:

avrdude -P gpio -c confignamehere -p attiny1634 -U flash:r:datao.raw:r

Sample configuration entry:

programmer
  id    = "confignamehere";
  desc  = "Testing";
  type  = "linuxgpio";
  reset = ;
  sck   = ;
  mosi = ;
  miso  = ;
  baudrate = 8192;
;

This took a fair bit of time and effort to diagnose, so I hope it proves useful.

Garth is generally available for part-time, casual, and full-time appointments, ad-hoc, short-term or long-term. Click here for further information, or here for Garth's contact details.

Navigation