AVR: best practice regarding fuse settings - Page 1
Forum section: electronics / general

author: AndyC_772
author_rank: Super Contributor
timestamp: July 10, 2014, 06:26:01 pm
content: Hi all,I normally turn to PICs when looking for a small microcontroller for a project, but I now have a project which for various reasons requires an AVR. So today, I've been doing the whole where-does-this-wire-go? thing with AVR Studio and a JTAGICE III.It took a while before I could get anything to download and run, which had me (metaphorically) banging my head against the wall for half the afternoon. When the target, IDE, compiler and PC interface are all new, it's hard to know what to do when a simple 'hello world' pin wiggler won't even start running, much less actually work. But to cut a long story short...I started by modifying some example code which set the configuration fuses thus:Code:FUSES = {.extended = 0xFF,.high = 0xDC,.low = 0xC2,};... which seemed right, as I defined them using the programming window in AVR Studio.As a general rule, I like to include all a device's configuration within the source files, rather than having to program them separately - but those of you familiar with the AVR will probably have spotted my bug already.In my fuse settings, DWEN is not configured to allow debugWire to work. So it doesn't. Or rather, it works just fine right up until the point where the fuses get programmed, and then it doesn't work any more and I get a very unhelpful error message from AVR Studio, which is clearly upset and confused. I was too.I thought I'd bricked my AVR, as I could neither debug it nor talk to it over SPI. To recover it, I eventually discovered that I had to comment out my fuse settings, then download my code again - which worked, fortunately. This then let me exit the debugger gracefully, which in turn makes DWEN inactive and allows SPI access once more. If I just set the fuses directly using the AVR Studio programming window, and don't set them in the code at all, then it all works fine.In the PIC world, configuration settings are handled by individual compiler directives - one per setting - and the general advice is to let the IDE handle the one that enables debugging. It gets set when debugging, and cleared for normal operation, with no change to the source code required. It's simply left out of the code and gets handled by the IDE.I can't figure out how to do this on the AVR, though. It appears that I must either activate DWEN if I want to debug, or deactivate it for production. I guess I could do this with a #ifdef, but that seems untidy.Am I doing something dumb here?

author: dannyf
author_rank: Super Contributor
timestamp: July 10, 2014, 07:16:16 pm
content: Use macros instead of magic numbers.

author: Bored@Work
author_rank: Super Contributor
timestamp: July 10, 2014, 07:57:22 pm
content: Don't try to set DWEN as part of normal fuse settings. DWEN is evil. In fact, the whole debugWire enable/disable is evil. Only set DWEN (implicitly) by starting/enabling an interactive debugging session in the IDE. And don't forget to disable debugging when you are done with it as the last action in the debugging session.debugWire enabled means you have no reset pin. That prevents some methods of programming - all programming methods which require reset, like, for example, the popular ISP programming. And without being able to program you also can't program fuses, i.e. you can't turn DWEN off ... The way to get rid of DWEN is that the debugWire protocol contains a command to turn off DWEN. I.e. when that command is sent via debugWire then debugWire effectively commits suicide and returns the AVR to normal operation.Atmel is very proud of this fuckup. It fails, for example, if the debugging session crashes, leaving the AVR with DWEN on, but no debugWire session to disable DWEN.

author: AndyC_772
author_rank: Super Contributor
timestamp: July 10, 2014, 08:13:38 pm
content: Quote from: Bored@Work on July 10, 2014, 07:57:22 pmThat's exactly what I want to achieve. I just don't know the proper syntax to set and clear the other fuses as per the requirements of my application, but to leave DWEN under control of the IDE.

author: thm_w
author_rank: Super Contributor
timestamp: July 12, 2014, 12:35:55 am
content: http://www.nongnu.org/avr-libc/user-manual/group__avr__fuse.htmlCode:FUSES ={.low = LFUSE_DEFAULT,.high = (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN),.extended = EFUSE_DEFAULT,};Scroll down to fuses section in your appropriate io include file, for example:https://android.googlesource.com/toolchain/avr-libc/+/edcf5bc1c8da8cc4c8b560865d2a54b73c1b51d3/avr-libc-1.7.1/include/avr/iom328p.hDetermine low/high/extended bits your hex values equate to, and add them in.

author: dannyf
author_rank: Super Contributor
timestamp: July 12, 2014, 01:47:57 am
content: Being able to embed fuse settings in the hex file is one of the few things Microchip got right.Atmel unfortunately got it wrong.

author: eneuro
author_rank: Super Contributor
timestamp: July 12, 2014, 09:13:13 am
content: Quote from: AndyC_772 on July 10, 2014, 06:26:01 pmSometimes fuses calculators are unable to suggest that there are a few another fuses that must be changed to get for example desired BOD level and they have to be modified according to AVR datasheetWhen started write code on AVRs simply used debuging using LED & light sensor connected to scope which started send bits in Morse code after eg. 10 seconds of normal program executionSo, I could watch critical variables which were set while microcontroller runs at full speed and no need to set debug fuses.It is easy also log this data using simple LPT optoisolated interface with photodiode and a few lines of code to postproces Morse code bits on PC and output to text file

author: AndyC_772
author_rank: Super Contributor
timestamp: July 12, 2014, 10:28:34 am
content: Quote from: thm_w on July 12, 2014, 12:35:55 amThanks for the link. It does, however, seem to confirm that setting fuses is an 'all-or-nothing' thing, so there really is no way to specify the state of all the fuses *except* DWEN. It's a pretty horrible omission to find on day 1 of trying to use a new tool chain IMHO.Quote from: eneuro on July 12, 2014, 09:13:13 amYikes, rather you than me. Fortunately my design has a UART interface, so I can drive debug information out of that and either connect it to a PC or decode it with my scope in real time.

author: bingo600
author_rank: Super Contributor
timestamp: July 12, 2014, 10:29:01 am
content: I tend to look at :http://www.engbedded.com/fusecalcWhen i need to define the fuses , and it even has avrdude output (for my linux)I havent gotten around to "this modern nonsense"Of embedding fuses in the hexfileWell engbedded is rather nice/Bingo

author: AndyC_772
author_rank: Super Contributor
timestamp: July 12, 2014, 10:31:32 am
content: Quote from: bingo600 on July 12, 2014, 10:29:01 amHow else do you provide a file to a manufacturer for mass production that includes all the information they need?

author: dannyf
author_rank: Super Contributor
timestamp: July 12, 2014, 12:00:36 pm
content: QuoteIt can be effective but probably not that efficient. I use blinking leds from time to time to indicate simple conditions.Otherwise, Uart or lcds are more useful - a lcd interface can be constructed with 2-3 lines (fewer if you can tolerate lower speed).

author: Psi
author_rank: Super Contributor
timestamp: July 12, 2014, 12:57:21 pm
content: You can encode two different debug situations on one output really easy but just toggling once for A and twice for B.It's easy to differentiate between a pulse and a state change on the scope by just looking at the waveform.

author: eneuro
author_rank: Super Contributor
timestamp: July 12, 2014, 09:03:01 pm
content: Quote from: dannyf on July 12, 2014, 12:00:36 pmYep I2C LCD can be used but on AVR DIP8 ATTiny85 in many projects where I2C is not needed if you have HV programmer you can use even disabled RESET pin to send debug data directly to PC of course at much higher speeds than in this video, where Morse code delays were choosen to be able debug this thing just looking at output PWM diode without any additional equipment in realtime environmentHowever, I have also this magic light sensor and it is easy connect it toxoscope, point it close to this debug diode and we can see what is going on inside our AVR without touching it and using only pocket calculator

author: dannyf
author_rank: Super Contributor
timestamp: July 12, 2014, 09:08:16 pm
content: Just put a logic analyzer on the pin, either uart or spi or i2c or whatever you want. Most logic analyzers can decode many of the popular protocols and you don't even need to count the pulses yourself. Much faster and simpler than a coupler + scope.

author: TerminalJack505
author_rank: Super Contributor
timestamp: July 12, 2014, 09:19:40 pm
content: If you go with a high pin count (>= 44) AVR then you can ditch debugWire and use JTAG for debugging.

author: AndyC_772
author_rank: Super Contributor
timestamp: July 13, 2014, 02:05:49 pm
content: Maybe, but in this case the specific AVR chip is already prescribed for other, non-technical reasons. Given free choice, I'd have used a roughly equivalent PIC and not had this problem.

author: thm_w
author_rank: Super Contributor
timestamp: July 14, 2014, 09:55:37 pm
content: Quote from: AndyC_772 on July 12, 2014, 10:28:34 amI'm a bit confused here. The FUSES directive should be pre-processor, which is placing these settings into the output file of the project:QuoteQuoteThere is no way to not set a fuse value when writing to the register. As far as I can remember, DWEN fuse was an automatic process where it enables it when starting debugging and disabled when you select "stop debugging".Maybe there is some bug with priorities of which fuse setting is applied first, no idea.Anyway, could you just IF out that that section out of your code when compiled for debugging? Or have one fuse config for debug and one for release.Might give it a try later.edit: related threadhttp://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=138340

author: thm_w
author_rank: Super Contributor
timestamp: July 15, 2014, 05:59:31 pm
content: I didn't have a working debugWire setup, but was able to get the FUSES code working. When you start a debug session it does not program the fuses. Fuses are only programmed if you go to production programming, and check the checkbox for Fuses. So I suspect there is something else preventing your debug session from working.Is the reset line free of capacitors, pullup if exists is 10k or greater?side note: EFUSE_DEFAULT was defined as "()" which didn't compile for me and had to add the appropriate macro in.

author: eneuro
author_rank: Super Contributor
timestamp: July 15, 2014, 09:19:46 pm
content: Quote from: thm_w on July 14, 2014, 09:55:37 pmJust wrote template AVR-GCC with FUSES defined to test this and see where in output hex/binary file they are placedFuses defined in C source codeprosmps.cbefore main after included headers:QuoteAdded my fuses settings tomakefileand they are passed during compilation to C source file as defined constants LFUSE, HFUSE, EFUSE:QuoteThere ismakelog usingavr-gccunder Linux:QuoteLooks good and now we are searching where in output hex/binary file (added target for binary output too to my makefile to get row .bin ).Now searching for those defined fuses during compilation: -DLFUSE=0x42-DHFUSE=0xdc-DEFUSE=0xff. It is easy to find them while this template program with empty main is only 95 bytes long for ATTINY85:QuoteQuoteIt looks like those fuses are last 3 bytes in output program in this order:LFUSE HFUSE EFUSEso in this case last 3 bytes in my binary file are:0x42 0xdc 0xffLast byte is this 0xFF extended fuseI've no idea for the moment howto tell manufacturer to extract those fuses bytes from this output hex or binary file, however it is easy and a few lines of code in C to do for me to generateavrdudeLinux command from such binary output file to program device (ATTINY85) and then write those fuses tooIsn't it manufacturer dependent how to prepare I guess binary (or maybe ihex) files for production programming?It looks like this information about fuses is in output file, but who knows how reuse it on production line?

author: thm_w
author_rank: Super Contributor
timestamp: July 15, 2014, 10:28:34 pm
content: Quote from: eneuro on July 15, 2014, 09:19:46 pmCoolQuoteYes, it seems so, some may include EEPROM data, etc.There are proprietary command line tools for AVRISP, which is what I would use for production:http://support.atmel.com/bin/customer.exe?=&action=viewKbEntry&id=776In previous comment I was using the programming window in avr studio 6, and jtagice2, not very production friendly.

author: eneuro
author_rank: Super Contributor
timestamp: July 16, 2014, 10:16:11 am
content: Quote from: thm_w on July 15, 2014, 10:28:34 pmBy production I mean send it to manufaturer and let it go and have my PCBs soldered with AVR devices on PCB programmed in factoryAt home it is easy to automate this and put additional sections in output hex/binary file.QuoteI've added a few more sections like.fusel .fuseh .fuseeand.fuseat the end to automate this things:QuoteIt adds a few extra descriptive text bytes to output hex/binary file, but it easy to find them and extract from binary file , so.elfis not needed tooFrom .elffile it is strightforward:QuoteIf you don't need them simply remove choosen sections when creating output hex/binary from compiled .elf with .eeprom section tooQuoteI've also removed this fuse description tag.fuse_tagand left those well defined sections for indyvidual fuse & version sections.ver .fusel .fuseh .fuseefor my automation tools.Quote

author: westfw
author_rank: Super Contributor
timestamp: July 17, 2014, 02:13:52 am
content: Quotei've seen noise over on avrfreaks that implies that atmel thinks that the .elfisthe proper "production" file format. For actual "production", of course, you provide whatever the manufacturer asks for. Since I think the ability to include fuse values in the .elf is relatively new, it wouldn't surprise me if the most common format is a separate .hex file for each fuse value. (avrdude would support that, I think. Though I doubt whether many production shops use avrdude.)Surely someone has some kind of production programmer and can look this up in the manual?

author: eneuro
author_rank: Super Contributor
timestamp: July 17, 2014, 09:16:18 am
content: Quote from: westfw on July 17, 2014, 02:13:52 amI think it is time to ask PCB manufacturer what they are expect to provide for automated MCUs programming during productionIt could be nice when PCB is made and electrical tests are made, to be able to do something even more tricky:power this PCB up, measure voltage on given MCU pin (eg. AVref with external voltage reference which might slightly differ from unit to unit and resistors used) than find section.avrefin my output binary (eg. tagAVREF:) and... overwrite default setting (eg. 3.74V for TL431I with resistors) so this way I can provide something like... binary program template, but when PCB is made additional calibration is made and in this example.avreftwo bytes long (uint16_t) 374 number (3.74V*100) overwritten with exact measured 369 (3.69V*100) while it is AVref value on one of those manufactured PCBs.However, I have no idea if such MCU programming process with additional data passed to output binary program file is even possible at factory for smaller series lets say 100-1000 PCBs during PCB manufacturing and doing electrical test?

author: con-f-use
author_rank: Unknown
timestamp: July 17, 2014, 09:55:21 am
content: Code:FUSES = {.extended = 0xff,.high = 0xdc,.low = 0x42,};Excuse my ignorance, but what does avrdude do with fuse settings like this in your source code (.hex file when compiled)? Under which circumstances does it set the fuses on your uC, when they were specified like this?

author: AndyC_772
author_rank: Super Contributor
timestamp: July 17, 2014, 10:09:33 am
content: Quote from: eneuro on July 17, 2014, 09:16:18 amNormally, for any kind of volume, I would send out the MCUs to a programming company, who have fully automated equipment to unpack the devices, program them, then re-reel them or load them back into trays. The machines used for this process are basically converted pick & place assembly machines, but instead of loading chips onto PCBs, they're inserted into an array of special ZIF sockets instead.The chips will come back all identical, of course. If per-chip calibration is needed, I'd be expected to provide a test jig that performed any testing and reprogramming necessary, and would have to pay by the hour for the operator's time. Needless to say this pushes up the cost of the assembly and test process, but if it can be included as part of a wider automated functional test process, then the extra cost isn't too high provided the calibration step is quick.

author: eneuro
author_rank: Super Contributor
timestamp: July 18, 2014, 01:22:16 am
content: Quote from: con-f-use on July 17, 2014, 09:55:21 amI didn't looked too much for such things intoavrdudedocumentation so far and to ensure it will behave exactly on my PC Linux based automated programmer the way I want it, I wrote my own factory tools which reads binary AVR file with those additional sections but declared different using attribute section statements in my C source file:Quoteand without.fusesection just in the case ifavrdudewanted to do something strange during programmingThiseneurotoolssoftware simply reads compiled binary AVR file and parses it and outputs to Linuxshellscript commands needed to reflash device and program fuses if needed based on its contents and additional passed parameters if needed to calibrate it.It can take this input binary file as template, substitute defined sections with eg. measured voltages and write changed binary file to reflash device with calibrated data put into these defined sections.This tool simply loads binary program to memory, scans for tags and when they are found I can change them and write new program without recompilation-just set calibration data for mentionedAVrefs, I2C assigned adress, etc. sections.Quote from: AndyC_772 on July 17, 2014, 10:09:33 amThank you for this hint with test jigI've included in my MCUs source code section.idwhich could be PCB serial number identifier for example, so I could have MCUs reflashed with calibrated data linked to PCB, but while they are again back on reel, how PCB assembly factory will know that MCU is for given PCB?Is it possible to get something like electrical test detail log with PCB serial number if any and voltage measured by PCB manufacturer?Than based on those automated measurements I could use my software to generate binary program file to reflash MCU for given PCB.I'm thinking on other option too-operator or software in factory has barcode scanner, scans PCB serial number, puts it into WWW form interface on my WEB page with electrical test result and in real time my tools provide needed binary program code to reflash MCU before final assembly.This step with external MCU programming and re-real seams to be additional logistics challenge.Maybe for specific 8pin MCUs it makes sense to try to make DIY machine with a few optical encoders and OpenCV USB camera app to rewind such reel and reflash those small MCUs and be independent-wait only for electrical tests results, update calibration data and assighn IDs and make final PCB assembly?Will see, If I had electrical tests logs with PCB serial numbers in text file than, reflashing MCU does not have to take too much time-a few seconds for ATTiny85 reflash even using LPT dapa pararel port