{"id":740,"date":"2012-09-19T01:00:00","date_gmt":"2012-09-18T23:00:00","guid":{"rendered":"https:\/\/www.fussylogic.co.uk\/blog\/?p=740"},"modified":"2012-10-26T10:37:45","modified_gmt":"2012-10-26T09:37:45","slug":"blowing-a-fuse","status":"publish","type":"post","link":"https:\/\/www.fussylogic.co.uk\/blog\/?p=740","title":{"rendered":"Blowing a Fuse"},"content":{"rendered":"<p>I like to use <code>avrdude<\/code> for programming my AVR\u00e2\u20ac\u2122s. It\u00e2\u20ac\u2122s got support for pretty much every possible programming method supported by the AVR CPUs and has a good command line interface. A command line interface is very important when you use <a href=\"?p=239\">Makefiles to act as your IDE<\/a>.<\/p>\n<p>Here, for example, is a little bit of a Makefile from an AVR-based project:<\/p>\n<pre class=\"sourceCode Makefile\"><code class=\"sourceCode makefile\"><span class=\"dt\">TARGET     <\/span><span class=\"st\">:= projectname<\/span>\n<span class=\"dt\">MCU        <\/span><span class=\"st\">:= atmega88<\/span>\n<span class=\"dt\">PROGDEVICE <\/span><span class=\"st\">:= usb<\/span>\n<span class=\"dt\">DUDEMODE   <\/span><span class=\"st\">:= dragon_jtag<\/span>\n\n<span class=\"dv\">default:<\/span> upload\n\n<span class=\"co\"># I&#39;m leaving out the compiler part that actually makes you a .elf file<\/span>\n<span class=\"co\"># to program<\/span>\n\n<span class=\"co\"># avrdude needs a .hex file to burn, objcopy can extract parts of a<\/span>\n<span class=\"co\"># .elf file and convert them to intel-hex format<\/span>\n<span class=\"ch\">%<\/span>.hex<span class=\"ch\">:<\/span> <span class=\"ch\">%<\/span>.elf\n    avr-objcopy --strip-all --strip-debug <span class=\"ch\">\\<\/span>\n        <span class=\"ch\">-<\/span><span class=\"bn\">-only-section<\/span><span class=\"ch\">=<\/span>text --only-<span class=\"dt\">section<\/span><span class=\"st\">=data <\/span><span class=\"ch\">\\<\/span>\n        <span class=\"ch\">-<\/span><span class=\"bn\">-output-target<\/span><span class=\"ch\">=<\/span>ihex <span class=\"ch\">$<\/span>&lt; <span class=\"ch\">$<\/span>@\n\nupload-<span class=\"ch\">%:<\/span> <span class=\"ch\">%<\/span>.hex\n    avrdude -p <span class=\"ch\">$(<\/span><span class=\"dt\">PROGDEVICE<\/span><span class=\"ch\">)<\/span> -c <span class=\"ch\">$(<\/span><span class=\"dt\">DUDEMODE<\/span><span class=\"ch\">)<\/span> <span class=\"ch\">\\<\/span>\n        <span class=\"ch\">-<\/span><span class=\"bn\">U<\/span> flash<span class=\"ch\">:<\/span>w<span class=\"ch\">:$<\/span>&lt;\n\n<span class=\"dv\">upload:<\/span> upload-<span class=\"ch\">$(<\/span><span class=\"dt\">TARGET<\/span><span class=\"ch\">)<\/span><\/code><\/pre>\n<p>That\u00e2\u20ac\u2122s all pretty standard Makefile fare; make a hex file, then burn it. A nice automated way of getting your program into a device. However, there is another component to consider when programming a microcontroller; its so-called \u00e2\u20ac\u0153fuses\u00e2\u20ac\u009d. These have differing functions on different devices, but they often control clock source, memory protection, allowed programming methods. The AVR is no exception. <code>avrdude<\/code> can program these fuses for you. For example:<\/p>\n<pre><code>avrdude -p $(PROGDEVICE) -c $(DUDEMODE) \\\n    -U lfuse:w:0xc2:m \\\n    -U hfuse:w:0x91:m \\\n    -U efuse:w:0xff:m<\/code><\/pre>\n<p>This programs the low fuse, the high fuse and the extended fuse.<\/p>\n<p>What\u00e2\u20ac\u2122s wrong then? The Makefile is the wrong place for this information. What goes in the chip is described by the source files, not by the Makefile. Why should the fuse bytes be any different from the program bytes? This is particularly relevant when we consider that often the program will rely on a particular fuse configuration. Further, when we make a binary release, we don\u00e2\u20ac\u2122t want the receiver to need our development enviornment to be able to program a device; or even the <code>Makefile<\/code>.<\/p>\n<p>Ideally we want to be able to store the fuse values in source code, translate those values to special sections in the elf file (where they are permantly documented as part of the release) and burn them from the Makefile. Since avr-libc v1.6, we can do so.<\/p>\n<p>Step 1 then: get them from the source file to the elf file.<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\"><span class=\"ot\">#include &lt;avr\/io.h&gt;<\/span>\n<span class=\"ot\">#include &lt;avr\/fuse.h&gt;<\/span>\n\n<span class=\"co\">\/\/ Fuses are inverse logic, so should be combined with AND (&amp;) not OR<\/span>\n<span class=\"co\">\/\/ (|) as you would normally<\/span>\nFUSES = {\n<span class=\"ot\">#   if FUSE_MEMORY_SIZE == 1<\/span>\n    <span class=\"co\">\/\/  Low Fuse Byte (e.g. ATmega88)<\/span>\n    <span class=\"co\">\/\/   FUSE_CKSEL0<\/span>\n    <span class=\"co\">\/\/   FUSE_CKSEL1<\/span>\n    <span class=\"co\">\/\/   FUSE_CKSEL2<\/span>\n    <span class=\"co\">\/\/   FUSE_CKSEL3<\/span>\n    <span class=\"co\">\/\/   FUSE_SUT0<\/span>\n    <span class=\"co\">\/\/   FUSE_SUT1<\/span>\n    <span class=\"co\">\/\/   FUSE_BODEN<\/span>\n    <span class=\"co\">\/\/   FUSE_BODLEVEL<\/span>\n    .low = LFUSE_DEFAULT,\n<span class=\"ot\">#   elif FUSE_MEMORY_SIZE == 2<\/span>\n    <span class=\"co\">\/\/  High Fuse Byte (e.g. ATmega88)<\/span>\n    <span class=\"co\">\/\/   FUSE_BOOTRST<\/span>\n    <span class=\"co\">\/\/   FUSE_BOOTSZ0<\/span>\n    <span class=\"co\">\/\/   FUSE_BOOTSZ1<\/span>\n    <span class=\"co\">\/\/   FUSE_EESAVE<\/span>\n    <span class=\"co\">\/\/   FUSE_CKOPT<\/span>\n    <span class=\"co\">\/\/   FUSE_SPIEN<\/span>\n    <span class=\"co\">\/\/   FUSE_WDTON<\/span>\n    <span class=\"co\">\/\/   FUSE_RSTDISBL<\/span>\n    .high = HFUSE_DEFAULT,\n<span class=\"ot\">#   elif FUSE_MEMORY_SIZE == 3<\/span>\n    .extended = EFUSE_DEFAULT,\n<span class=\"ot\">#   else<\/span>\n<span class=\"ot\">#       error &quot;No support for more than three fuse bytes&quot;<\/span>\n<span class=\"ot\">#   endif<\/span>\n}<\/code><\/pre>\n<p>The <code>avr\/fuse.h<\/code> creates the <code>FUSES<\/code> symbol along with the other constants to make this work. You would set <code>.low<\/code>, <code>.high<\/code> and <code>.extended<\/code> to whatever suited your project \u00e2\u20ac\u201c I\u00e2\u20ac\u2122ve simply left them at the defaults here. I\u00e2\u20ac\u2122d suggest you put this code in a separate module, then link it with the rest of your application. Here\u00e2\u20ac\u2122s what you might get in your elf (I used an empty <code>main()<\/code>):<\/p>\n<pre><code>$ avr-nm --numeric-sort --demangle fuses.elf &gt; fuses.sym\n\nfuses.elf:     file format elf32-avr\n\nSections:\nIdx Name          Size      VMA       LMA       File off  Algn\n  0 .text         00000050  00000000  00000000  00000074  2**1\n                  CONTENTS, ALLOC, LOAD, READONLY, CODE\n  1 .fuse         00000003  00820000  00820000  000000c4  2**0\n                  CONTENTS, ALLOC, LOAD, DATA\n  2 .stab         00000aec  00000000  00000000  000000c8  2**2\n                  CONTENTS, READONLY, DEBUGGING\n  3 .stabstr      000007a7  00000000  00000000  00000bb4  2**0\n                  CONTENTS, READONLY, DEBUGGING\n  4 .comment      00000011  00000000  00000000  0000135b  2**0\n                  CONTENTS, READONLY\n\n   text    data     bss     dec     hex filename\n   0x50     0x3     0x0      83      53 fuses.elf\n   0x50     0x3     0x0      83      53 (TOTALS)<\/code><\/pre>\n<p>Note in particular the new section <code>.fuse<\/code>, which is (not surprisingly), three bytes long; note also that its load address (LMA) is set well outside the memory space of any AVR (purposefully \u00e2\u20ac\u201c you will never program them to normal memory). Let\u00e2\u20ac\u2122s have a look at what\u00e2\u20ac\u2122s in that section.<\/p>\n<pre><code>$ avr-objdump -s --section=.fuse fuses.elf \n\nfuses.elf:     file format elf32-avr\n\nContents of section .fuse:\n 820000 0000f9                               ...             <\/code><\/pre>\n<p>There we go: 0x00, 0x00, 0xf9. Three fuse bytes store in the elf file and accessible from the command line.<\/p>\n<p>With a bit of Makefile magic, we can pull them out and into a variable ready for programming.<\/p>\n<pre class=\"sourceCode Makefile\"><code class=\"sourceCode makefile\"><span class=\"dv\">upload-fuses:<\/span> <span class=\"dt\">FUSES <\/span><span class=\"st\">= <\/span><span class=\"ch\">$(<\/span><span class=\"dt\">shell avr-objdump -s --section=.fuse $(TARGET<\/span><span class=\"ch\">)<\/span><span class=\"st\">.elf <\/span>\n    | tail -1 | awk &#39;{print substr<span class=\"ch\">($$<\/span>2,1,2<span class=\"ch\">)<\/span>,substr<span class=\"ch\">($$<\/span>2,3,2<span class=\"ch\">)<\/span>,substr<span class=\"ch\">($$<\/span>2,5,2<span class=\"ch\">)<\/span>}&#39;<span class=\"ch\">)<\/span>\n<span class=\"dv\">upload-fuses:<\/span> <span class=\"ch\">$(<\/span><span class=\"dt\">TARGET<\/span><span class=\"ch\">)<\/span>.elf\n    avrdude -p <span class=\"ch\">$(<\/span><span class=\"dt\">PROGDEVICE<\/span><span class=\"ch\">)<\/span> -c <span class=\"ch\">$(<\/span><span class=\"dt\">DUDEMODE<\/span><span class=\"ch\">)<\/span> <span class=\"ch\">\\<\/span>\n        <span class=\"ch\">$(<\/span><span class=\"kw\">if<\/span><span class=\"st\"> <\/span><span class=\"ch\">$(<\/span><span class=\"kw\">word<\/span><span class=\"st\"> 1,<\/span><span class=\"ch\">$(<\/span><span class=\"dt\">FUSES<\/span><span class=\"ch\">))<\/span><span class=\"st\">,-U lfuse:w:0x<\/span><span class=\"ch\">$(<\/span><span class=\"kw\">word<\/span><span class=\"st\"> 1,<\/span><span class=\"ch\">$(<\/span><span class=\"dt\">FUSES<\/span><span class=\"ch\">))<\/span><span class=\"st\">:m<\/span><span class=\"ch\">)<\/span> <span class=\"ch\">\\<\/span>\n        <span class=\"ch\">$(<\/span><span class=\"kw\">if<\/span><span class=\"st\"> <\/span><span class=\"ch\">$(<\/span><span class=\"kw\">word<\/span><span class=\"st\"> 2,<\/span><span class=\"ch\">$(<\/span><span class=\"dt\">FUSES<\/span><span class=\"ch\">))<\/span><span class=\"st\">,-U hfuse:w:0x<\/span><span class=\"ch\">$(<\/span><span class=\"kw\">word<\/span><span class=\"st\"> 2,<\/span><span class=\"ch\">$(<\/span><span class=\"dt\">FUSES<\/span><span class=\"ch\">))<\/span><span class=\"st\">:m<\/span><span class=\"ch\">)<\/span> <span class=\"ch\">\\<\/span>\n        <span class=\"ch\">$(<\/span><span class=\"kw\">if<\/span><span class=\"st\"> <\/span><span class=\"ch\">$(<\/span><span class=\"kw\">word<\/span><span class=\"st\"> 3,<\/span><span class=\"ch\">$(<\/span><span class=\"dt\">FUSES<\/span><span class=\"ch\">))<\/span><span class=\"st\">,-U efuse:w:0x<\/span><span class=\"ch\">$(<\/span><span class=\"kw\">word<\/span><span class=\"st\"> 3,<\/span><span class=\"ch\">$(<\/span><span class=\"dt\">FUSES<\/span><span class=\"ch\">))<\/span><span class=\"st\">:m<\/span><span class=\"ch\">)<\/span><\/code><\/pre>\n<p>That\u00e2\u20ac\u2122s all a bit hairy, but is mindlessly copy-and-pasteable between projects; it makes use of a little-known facility of Makefiles called <a href=\"http:\/\/www.gnu.org\/software\/make\/manual\/make.html#Target_002dspecific\">target-specific variables<\/a>. This lets you set a variable based on the target being built. Unusually, I\u00e2\u20ac\u2122m not using it here for its intended purpose, the variable FUSES is not target-specific at all. However, target specific variables, by their nature, have to be evaluated at the time the target runs. That means we can defer the running of the \u00e2\u20ac\u02dcshell\u00e2\u20ac\u2122 command line used to generate FUSES until after we are sure the elf file is available. If we used a normal global makefile variable, it would likely fail because the elf file doesn\u00e2\u20ac\u2122t exist until the makefile generates it.<\/p>\n<p>The recipe to actually program the fuses is a little bit convoluted too, but it\u00e2\u20ac\u2122s written so that it will flexibly handle any number of fuses from one to three \u00e2\u20ac\u201c if no third byte exists in the elf, then no \u00e2\u20ac\u0153<code>-U efuse:...<\/code>\u00e2\u20ac\u009d will be included on the command line.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I like to use avrdude for programming my AVR\u00e2\u20ac\u2122s. It\u00e2\u20ac\u2122s got support for pretty much every possible programming method supported by the AVR CPUs and has a good command line interface. A command line interface is very important when you use Makefiles to act as your IDE. Here, for example, is a little bit of\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.fussylogic.co.uk\/blog\/?p=740\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[39,37,6],"_links":{"self":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/740"}],"collection":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=740"}],"version-history":[{"count":9,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/740\/revisions"}],"predecessor-version":[{"id":874,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/740\/revisions\/874"}],"wp:attachment":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=740"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=740"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=740"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}