Arduino Forum

Using Arduino => Microcontrollers => Topic started by: JakeSoft on Jan 26, 2016, 11:41 pm

Title: Resettings Fuses And Lock Bits
Post by: JakeSoft on Jan 26, 2016, 11:41 pm
I've been using Arduino for several years now and I'm just getting into the more hardcore aspects such as setting fuses and lock bits. I've done a lot of reading, but I'm still confused.

I'm sure this has been answered before, but here goes.

I'm working with 3.3V Pro Minis clocked at 8 MHz with the ATMega328p chips.

It looks like you can set the lock bits over the serial interface using AVRDUDE, but I'm not clear on a few things about what happens after that:

1) If flash read and write are both disabled, then you can't use SPI to read or write the flash. However, can the arduino boot loader still do it? Meaning, the boot loader could still be used to upload sketches. Some sources say no, some suggest yes. I don't want to brick an MCU finding out.

2) Once the lock bits are set, is the only way to clear them with the use of an additional device other than the FTDI breakout that I use to upload sketches? I.e. something like the USBtinyISP?
Title: Re: Resettings Fuses And Lock Bits
Post by: westfw on Jan 27, 2016, 02:05 am
Quote
It looks like you can set the lock bits over the serial interface using AVRDUDE,
No, you can only set the lock bits using the ISP interface and an external programmer.  A bootloader CANNOT change the fuses or lock bits.  (it might SAY that it has done so, for compatibility with programming SW.  But it can't.)

Quote
If flash read and write are both disabled, then you can't use SPI to read or write the flash.
There are three sets of "lock bits."  One controls access by the programming interface, one controls programatic access to the bootloader section, and one controls programatic access to the applications section.  The way I read the documentation, the bootloader would work even if the SPI access is disabled.   But you probably need to risk a chip to be sure...

There's another fuse that disables SPI programming, which would mean that you would need to connect the chip to a High Voltage Parallel Programmer in order to erase it.

Title: Re: Resettings Fuses And Lock Bits
Post by: JakeSoft on Jan 27, 2016, 03:20 am
No, you can only set the lock bits using the ISP interface and an external programmer.  A bootloader CANNOT change the fuses or lock bits.  (it might SAY that it has done so, for compatibility with programming SW.  But it can't.)
Thanks for the reply. I think you're right about that it's faking compatibility with some of the AVRDUDE commands. While connected via FTDI to the normal programming interface on the Pro Mini, if I enter this command:

Code: [Select]

avrdude -patmega328p -carduino -PCOM3 -b57600 -Ulock:r:d:\hexfiles\lockbyte.txt:h


I get a text file out that reads:

Code: [Select]

0x0


If I'm reading the 328p data sheet right, that would mean that all the memory protections are turned on and the chip should not be able to accept a program. That's clearly not the case.

There are three sets of "lock bits."  One controls access by the programming interface, one controls programatic access to the bootloader section, and one controls programatic access to the applications section.  The way I read the documentation, the bootloader would work even if the SPI access is disabled.   But you probably need to risk a chip to be sure...
Maybe I'll risk a cheap clone. I treasure my genuine boards too much to risk them.

There's another fuse that disables SPI programming, which would mean that you would need to connect the chip to a High Voltage Parallel Programmer in order to erase it.
Yeah, I'm not touching that one with a 10-foot pole!
Title: Re: Resettings Fuses And Lock Bits
Post by: JakeSoft on Jan 27, 2016, 04:00 am
Ok, so I'm guessing if I get the aforementioned USBtinyISP programmer, then wire it up something like this:




Then maybe I just might be able to use AVRDUDE to read and write fuses and lock bits properly.

To recover and make the chip writable again in the case I activate flash memory protection, I think I can recover by burning the bootloader from the arduino IDE. Right?

Assuming ISP is still connected as above, from within the Arduino IDE:
1) Tools-->Board --> Arduino Pro or Pro Mini
2) Tools-->Processor --> ATMega328 (3V, 8 MHz)
3) Tools-->Programmer-->USBTinyISP
4) Tools--> Burn Bootloader

As I understand it, part of the bootloader burning process is to perform a chip erase, which will reset the fuses and lock bits back to arduino defaults. I just have to be careful not to disable ISP programming by flipping that protection fuse. Am I getting any of this right?
Title: Re: Resettings Fuses And Lock Bits
Post by: dmjlambert on Jan 27, 2016, 06:02 am
I think you are heading the right direction.   There are fuse calculators online which can help you figure out the fuse values to try.   Have a look at the ATmega328P data sheet.   Ask questions about any specific values you wonder about. 

In the Arduino IDE preferences you can check show verbose output on upload.   Then when you burn the bootloader (which also sets fuses) you will be shown the avrdude commands used during the process.   Copy those commands to a notepad and use them as models.   

Don't use the Raw pin of the Arduino during programming, just connect the 5V from the programmer to the VCC pin of the Arduino.

Title: Re: Resettings Fuses And Lock Bits
Post by: JakeSoft on Jan 28, 2016, 04:52 am
Ok, I think I'm figuring this stuff out. I've spent several hours studying the ATMega328p datasheet and the AVRDUDE documentation as well as various forum posts.

The fuse defaults for Arduino can be gleaned from boards.txt:

Code: [Select]

pro.name=Arduino Pro or Pro Mini

pro.upload.tool=avrdude
pro.upload.protocol=arduino

pro.bootloader.tool=avrdude
pro.bootloader.unlock_bits=0x3F
pro.bootloader.lock_bits=0x0F
...
## Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega328
menu.cpu.pro.8MHzatmega328=ATmega328 (3.3V, 8 MHz)

menu.cpu.pro.8MHzatmega328.upload.maximum_size=30720
menu.cpu.pro.8MHzatmega328.upload.speed=57600

menu.cpu.pro.8MHzatmega328.bootloader.low_fuses=0xFF
menu.cpu.pro.8MHzatmega328.bootloader.high_fuses=0xDA
menu.cpu.pro.8MHzatmega328.bootloader.extended_fuses=0x05
menu.cpu.pro.8MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex


I'm not sure what "unlock_bits" does, it's not mentioned in the ATMega328p data sheet, but the rest is pretty clear.

So, I whipped up a batch file to try when my Usbtiny ISP arrives (ordered it yesterday).

Code: [Select]

@rem Erase chip
avrdude -p atmega328p -c usbtiny -b57600 -e

@rem Upload the program
avrdude -p atmega328p -c usbtiny -b57600 -D -U flash:w:d:\hexfiles\MyProgram.hex:i

@rem Set Low Fuse byte exactly as Arduno does (all disabled, apparently)
avrdude -p atmega328p -c usbtiny -b57600 -D -u -U lfuse:w:0xFF:m

@rem Set High Fuse Byte to disable bootloader and just run the MyProgram directly
avrdude -p atmega328p -c usbtiny -b57600 -D -u -U hfuse:w:0xDF:m

@rem Set extended fuse to enable brownout detection at ~2.7V (Exactly the same as Arduino defaults)
avrdude -p atmega328p -c usbtiny -b57600 -D -u -U efuse:w:0x05:m

@rem Lock down the flash to disable read/write
avrdude -p atmega328p -c usbtiny -b57600 -D -u -U lock:w:0xFC:m


Now, I was careful to make sure the High fuse byte has SPIEN set to 0, meaning that serial programming is enabled.
The only other change in that byte was that I disabled the bootloader to allow my program run directly by clearing (setting to 1) the bits for BOOTRST (bit 0), BOOTSZ0 (bit 1), and BOOTSZ1 (bit 2).

So, the High fuse byte looks like this:
RSTDISBL = 1 (meaning external reset enabled)
DWEN     = 1 (meaning debug wire disabled)
SPIEN    = 0 (meaning serial programming is enabled)
WDTON    = 1 (meaing watchdog timer is not always enabled)
EESAVE   = 1 (meaning EEPROM will not be preserved during chip erase)
BOOTSZ1  = 1 (not needed since BOOTRST is not set to enable bootloader)
BOOTSZ2  = 1 (not needed since BOOTRST is not set to enable bootloader)
BOOTRST  = 1 (meaning a bootloader is not used and program should start immeidately after reset)

I may first try to burn the bootloader first from the IDE as described earlier just to test the ISP is working.

I know this is a monster post, but I really want to make sure I've got my ducks in a row and there is a lot that needs to be right. I've done my homework, I just need it graded.
Title: Re: Resettings Fuses And Lock Bits
Post by: dmjlambert on Jan 28, 2016, 05:46 am
B+, good job!
Title: Re: Resettings Fuses And Lock Bits
Post by: westfw on Jan 28, 2016, 07:47 am
See also http://www.engbedded.com/fusecalc (http://www.engbedded.com/fusecalc)
Atmel Studio will also give you a nice GUI fuse calculator as part of the tools/device programming menu - you can use it with the 'simulator' even with no actual device attached, and no project open.
They seem to agree with your values!

Quote
I'm not sure what "unlock_bits" does, it's not mentioned in the ATMega328p data sheet
When you do a "burn bootloader" operation, the IDE uses avrdude in three steps:
1) Erase the chip and set the the  lock bits to the "unlock_bits" value.
2) upload the bootloader code.
3) Set the lock bits to the "lock_bits" value, to protect the bootloader from damaging itself, or being read by the application.
Now, (1) is a bit overkill, since erasing the chip also erases the lock bits.  And I don't see the value of preventing the application from reading the bootloader.   But this is what it does.

Now, I few additional details:
Quote
avrdude -p atmega328p -c usbtiny -b57600 -D -u -U efuse:w:0x05:m
You probably don't need to specify the bitrate for a USB-connected programmer.
efuse has "unused" bits, and avrdude may want them set to "1" instead of "0", making the efuse value 0xFD instead of 5.
You can put multiple "-U" commands on a single line, and this might be a good idea, because some USB devices reset and re-enumerate between commands, and they might not be "available" for back-to-back commands in a batch file.  (there's actually a bug open for the IDE when used with the Atmel Dragon programmer, because that three-step process can happen too fast for the dragon/windows combination.)
Title: Re: Resettings Fuses And Lock Bits
Post by: JakeSoft on Jan 29, 2016, 01:23 am
Thanks for the replies again, guys. I may have to try out that emulator. I didn't know there was such a thing. It would be nice to have a sandbox where I can try things out without risking a physical chip.

I made some updates based on the comments.

- Agree that I probably don't need to specify a baud rate for a USB device.
- Changed efuse to 0xFD to avoid setting unused upper bits.

Code: [Select]


@rem Erase chip
avrdude -p atmega328p -c usbtiny -e

@rem Upload the program
avrdude -p atmega328p -c usbtiny -D -U flash:w:d:\hexfiles\MyProgram.hex:i

@rem Set Low Fuse byte exactly as Arduno does (all disabled, apparently)
avrdude -p atmega328p -c usbtiny -D -u -U lfuse:w:0xFF:m

@rem Set High Fuse Byte to disable bootloader and just run the MyProgram directly
avrdude -p atmega328p -c usbtiny -D -u -U hfuse:w:0xDF:m

@rem Set extended fuse to enable brownout detection at ~2.7V (Exactly the same as Arduino defaults except upper two bits are not cleared to zero)
avrdude -p atmega328p -c usbtiny -D -u -U efuse:w:0xFD:m

@rem Lock down the flash to disable read/write
avrdude -p atmega328p -c usbtiny -D -u -U lock:w:0xFC:m


So, am I correct in my understanding that when a chip erase is performed, the lock byte get reset, but not the fuse bytes? So, unlike the lock byte, you can just set the Fuse bytes whenever you want willy-nilly?

Also, if I leave this as separate commands, I assume reset will be pulled low on the MCU for each command and then returned to high afterward. This would allow my program to potentially execute between commands. If my sketch used the programming pins for I/O, could this potentially damage the programmer if they were suddenly to go high, for example?
Title: Re: Resettings Fuses And Lock Bits
Post by: westfw on Jan 29, 2016, 01:38 am
Quote
you can just set the Fuse bytes whenever you want willy-nilly?
Yes.

Quote
This would allow my program to potentially execute between commands.
Well, not if the first command was the chip erase.   Erased memory on an AVR is a relative inconsequential near-noop.
If you use the programming pins for other purposes, you're supposed to include some isolation circuitry (documented in some app note) to make sure you can still do ISP programming.
Title: Re: Resettings Fuses And Lock Bits
Post by: JakeSoft on Jan 29, 2016, 02:44 am
Well, not if the first command was the chip erase.   Erased memory on an AVR is a relative inconsequential near-noop.
If you use the programming pins for other purposes, you're supposed to include some isolation circuitry (documented in some app note) to make sure you can still do ISP programming.

Hmm... I wonder if I could mitigate by using the -E option to specify that reset should stay low after programming. That would give me time to disconnect power from the MCU and unplug it from the programmer.

For example:
Code: [Select]

avrdude -p atmega328p -c usbtiny -D -E reset -U flash:w:d:\hexfiles\MyProgram.hex:i


Title: Re: Resettings Fuses And Lock Bits
Post by: avocadobeta on Jan 29, 2016, 06:21 pm
Hi!

I am playing with ATmega chips for two weeks using Arduino IDE, Atmel Studio 7, CodeBlocks, Eclipse just to have fun. I also read datasheets and internet forums. After two weeks I finally realized that when you download bootloader from Arduino then it will set LB1 and LB2 to "0" that means you cannot write anything to flash. The only possibility is to erase the whole memory using avrdude or reload program via Arduino. The reason is to protect software from reverse engineering.
To play with fuses I use very good program AVR-burn-o-mat - http://avr8-burn-o-mat.brischalle.de - GNU license.
Title: Re: Resettings Fuses And Lock Bits
Post by: CrossRoads on Jan 29, 2016, 06:40 pm
"when you download bootloader from Arduino then it will set LB1 and LB2 to "0""

I disagree.   Look at boards.txt:

uno.bootloader.unlock_bits=0x3F

uno.bootloader.lock_bits=0x0F


That is the unlocked state.

Title: Re: Resettings Fuses And Lock Bits
Post by: avocadobeta on Jan 29, 2016, 06:46 pm
0 means locked
Title: Re: Resettings Fuses And Lock Bits
Post by: avocadobeta on Jan 29, 2016, 06:53 pm
Just check lock bits after downloading bootloader.

avrdude -p... -c... U:lock:r....

page 271 in datasheet
Bit 7 6 5 4 3 2 1 0
Rd - - BLB12 BLB11 BLB02 BLB01 LB2 LB1
Title: Re: Resettings Fuses And Lock Bits
Post by: CrossRoads on Jan 29, 2016, 06:56 pm
"
ATmega88A/88PA/168A/168PA/328/328Pprovides six

Lock bits. These can be left unprogrammed ("1") or can be programmed ("0") to obtain the additional features

listed in Table 28-2. The Lock bits can only be erased to "1" with the Chip Erase command."
0x3F = 0011 1111 - so all 6 bits unlocked.  I don't know what you  have set up that is causing them to lock. A standard bootload using the IDE will not lock them.
Title: Re: Resettings Fuses And Lock Bits
Post by: avocadobeta on Jan 29, 2016, 07:04 pm
i've got 0x0f in lock bits after loading bootloader from Arduino IDE and I was unable to load something to my ATmega328P from Atmel Studio. After erasing memory by avrdude lock bits have been 0x3f..

Title: Re: Resettings Fuses And Lock Bits
Post by: avocadobeta on Jan 29, 2016, 07:17 pm
I think everything is OK. Just it is difficult to find problems when you play with different tools. If you are using only Arduino IDE evething is OK. If you want to play you must have fun to find something ...
Title: Re: Resettings Fuses And Lock Bits
Post by: JakeSoft on Jan 30, 2016, 01:24 am
i've got 0x0f in lock bits after loading bootloader from Arduino IDE and I was unable to load something to my ATmega328P from Atmel Studio. After erasing memory by avrdude lock bits have been 0x3f..


That much at least makes sense. The upper two lock bits aren't used anyway, so it probably doesn't matter what those are set to. It looks like the lower six bits are all "cleared" to their "unprogrammed" state after erase and set to 1. That seems to agree with the datasheet I've been reading.
Title: Re: Resettings Fuses And Lock Bits
Post by: westfw on Jan 30, 2016, 04:41 am
Quote
Rd - - BLB12 BLB11 BLB02 BLB01 LB2 LB1
Right.  And the "Burn Bootloader" command sets that byte to 0x0F (0b001111), which means that it has zero'ed (enabled)
BLB12 and BLB11 (*not* LB2/LB1)
Having BLB1 set to zero means "SPM is not allowed to write to the Boot Loader section, and LPM executing from the Application section is not allowed to read from the Boot Loader section." according to the data sheet,
 
BLB0 is 0b11, meaning "No restrictions for SPM or LPM accessing the Application section."
and LB is 0b11, meaning "No memory lock features enabled."


 
Title: Re: Resettings Fuses And Lock Bits
Post by: JakeSoft on Feb 21, 2016, 08:22 pm
I wired up my USBTinyISP as shown in post #3, but I don't think the programmer is even working.

I get the same error when I attempt to burn bootloader from the Arduino IDE or use AVRDUDE command line:

avrdude: initialization failed, rc=-1
             Double check connections and try again, or use -F to override
             this check.


Command line was:
avrdude -patmega328p -cusbtiny -Uflash:r:d:\hexfiles\tinybackup.hex:i

Operating system is Windows 7 Pro, 64-bit

Connecting to a Pro Mini 3.3V @ 8MHz.

I have the blink sketch uploaded to the Pro mini and when I run the command line, I can see that the steady blinking LED is interrupted momentarily, so that makes me think that at least reset is being pulled low briefly. Any ideas?
Title: Re: Resettings Fuses And Lock Bits
Post by: JakeSoft on Feb 21, 2016, 08:33 pm
I wired up my USBTinyISP as shown in post #3, but I don't think the programmer is even working.

I get the same error when I attempt to burn bootloader from the Arduino IDE or use AVRDUDE command line:

avrdude: initialization failed, rc=-1
             Double check connections and try again, or use -F to override
             this check.


Command line was:
avrdude -patmega328p -cusbtiny -Uflash:r:d:\hexfiles\tinybackup.hex:i

Operating system is Windows 7 Pro, 64-bit

Connecting to a Pro Mini 3.3V @ 8MHz.

I have the blink sketch uploaded to the Pro mini and when I run the command line, I can see that the steady blinking LED is interrupted momentarily, so that makes me think that at least reset is being pulled low briefly. Any ideas?
Disregard. I think I've got it working now. Right after I posted this, I found this article: https://learn.adafruit.com/usbtinyisp/help (https://learn.adafruit.com/usbtinyisp/help)

Using the -B32 trick on the command line did the trick!