Understanding Lock Bits, Fuse Bits and Code Security

Hi All,
I have been reading and researching Atmega328p lock and fuse bits for quite some time now, however I am not sure I have all the information correct. From my understanding:

  • Lock and Fuse bits can be set by an ISP programmer
  • Lock and Fuse bits can be set to use the reset pin as a DIO pin
    This should prevent programming from ISP (as reset has to be held low for this?) However, even with reset pin as a DIO, the bootloader could accept code through uart etc and write to the program space internally, is this correct??
  • A High Voltage programmer could be used to modify fuses even when the reset fuse has been put low
    Does this mean if you programmed the lock bits for complete security, a high voltage programmer could change these fuses and still read the flash memory? Does using a HVP clear the memory??

Some other related questions I have are:
What is the "DWEN" debugWIRE fuse for?
Do all the memory read / write protection fuses also apply to the EEPROM? Can the EEPROM be read externally or only by the arduino code itself??
The fuses for Atmega16u4 are similar, however there is no reset disable fuse, can this processor also be locked from reading from memory externally?

I have various project ideas that could make use of changing these fuse and lock bits, however one of them would involve storing a user password on the arduino, is it possible to set these fuses in a way that prevents someone reading out the memory and finding this passcode? Lets say they have many different arduinos + Passcodes and can find the bytes that change between them. Obviously there is always going to be a way, what I am wanting to know is, is it as simple as connecting a HVP, changing the read protection lock bits and then reading out the memory?? Would it be safer to store this passcode in EEPROM?

Thanks in advance for your time to read this and sorry there are so many questions! :smile:

@mruser
You may find some answers of your queries from the following description.

1. A Fuse Bit (in the context of ATmega328P Microcontroller) can be conceptually visualized as a ‘Jumper Wire’ which has two conditions:

(a) Unbroken (Unprogrammed state: returns 1 when reading the fuse bit)
(b) Broken (Programmed state: returns 0 when reading the fuse bit)

2. A Fuse Bit configures the Operational Mode/Functional Mode of the microcontroller (MCU) at the time of the 1st power up initialization when no instruction has yet been executed. For example: the fuse bit named CKDIV8, when it is in programmed state, defines the frequency of the system clock (clkSYS) equal to “Oscillator Frequency/8”. If CKDIV fuse bit is programmed, the switch K2 of Fig-1 is closed and K1 is opened. As a result, the frequency of the system clock (clkSYS) is Y1/8 = 2 MHz. In Arduino UNO, the CKDIV fuse bit is in unprogrammed state. Hence, the MCU is running at Y1 = 16 MHz (Fig-2). It may be noted here that the programmed state of the CKDIV fuse can be override using Program Instruction and CLKPR Register. (See Step-8.)
ckdiv8
Figure-1: Role of fuse bit CKDIV8 in the determination of system clock frequency

3. There are 24 fuse bits inside ATmega328P MCU of which only 19 are active. The value of a fuse bit remains unchanged even in ‘Chip Erase’ process during Programming Session. These 24 fuse bits are organized as:

(a) Extended Fuse Byte (EF), (b) High Fuse Byte (HF), and (c) Low Fuse Byte (LF).

4. The state (programmed or Unprogrammed) of a fuse bit can be altered using Parallel Programmer like TOP2013 and the like. The state can also be changed using ISP; but, it is not recommended. Read operation on a fuse bit returns 0 if the fuse bit is in programmed state; otherwise, 1 is returned.

5. The state of a fuse bit must be altered before “Programming the Lock Bits” associated with read/write protections of Flash Memory and EEPROM Memory of the MCU. Once, the lock bits are programmed, the state of the fuse bit cannot be changed. The option that is left is to erase the chip (chip erase brings the lock bits back to their default values) and then set the fuse bits.

6. Fuse Bit Structure of ATmega328P MCU (Fig-2)
fusebits
Figure-2:

7. RSTDISABL(HF7) Fuse Bit : External Reset is not allowed when programmed

(1) When this fuse bit is at unprogrammed state, Pin-1 of ATmega328P (Fig-3) works as a Reset Pin to receive external RESET signal for the MCU.
rstdisFuseBit
Figure-3:

(2) If we want to use Pin-1 as a digital IO line (PC6) or an interrupt pin (PCINT14), the RSTDISABL bit must be at programmed state. The choice of option between PC6 and PCINT14 is made by program instruction.

8. Override CKDIV's Current Programmed State (programmed) in UNO
(1) The system clock frequency (clkSYS) of the UNO Board can be brought down from 16 MHz (CKDIV is unprogrammed) to lower frequencies by a clock Prescaler. The division factors are 1/1, 1/2, 1/4, 1/8, 1/16, 1/32, 1/64, 1/128, and 1/256 (Fig-4).

fsb
Figure-4:

(2) When the chip is shipped to the customer from the factory, the manufacturer sets the clock Prescaler at division factor 1/8 with the help of CKDIV Fuse Bit. In the case of Arduino UNO, the clock Prescaler has been changed to 1/1 by reprogramming CKDIV bit. Now, in the Arduino UNO board, operating clock of the CPU is 16 MHz which is designated as clckSYS (system clock).

(3) Procedures to get 1 MHz for clkSYS
a. The division factor is implemented with the help of the following CLKPR (Clock Prescaler, Fig-5) Register of the MCU. CLKPR is an EEPROM type (non-volatile) Register.
CLKPR
Figure-5:

b. Enable CLKCE (Clk Change Enable) bit by putting LH at this bit. During this process, bit values for the remaining 7-bit should be 0s.

c. Now read data sheets of ATmega328P and find that the pattern 0100 for the CLKPS[3:0] (Clock Prescaler Select) bits will implement 1/16 division factor. Let us write this value into CLKPR Register with CLKPCE-bit at LL.

d. In Step-2, CLPCE-bit was at LH, and it remains at LH-state until the write process of Step-c is completed. It takes about four clock cycles after which the CLKPCE-bit automatically assumes LL-state.

(4) Arduino Codes (execute on UNO Kit and check that L's blinking interval has changed from that of clkSYS = 16 MHz.

void setup() 
{
  pinMode(13, OUTPUT);
  CLKPR = 0x80;  //1000 0000
  CLKPR = 0x04;  //0000 0100   1/16
}

void loop() 
{
  digitalWrite(13, !digitalRead(13));
  delay(1000);    //1000 is 1000 ms when clkSYS = 16 MHz; 
}
1 Like

The only way to clear the lock bits is a full chip erase.
However, the lock bits will not normally prevent the code from being read by the bootloader.

Thank you so much all! This has helped so so much!
My next related question would be how does the High Voltage Programmer work? Is it just "forcing" a full chip erase, regardless of the RSTDISABL fuse?
Also, is there any known way to externally read the EEPROM, such as through the Parallel programmer? Is it accessible in the same way as flash memory or is it it's own little private section of the microcontroller?

I am drawing your kind attention to the following Table:

Yes, if you set BLB Mode 4, it may prevent the bootloader from reading the application, but it will also break the normal "upload" procedure.

The "normal" lock procedure for an AVR is to set the "lock bits" to 0 ("mode 3") and remove the bootloader, all of which requires a hardware programmer based upload procedure not included in the IDE.

2 Likes

This is true. If you try to upload with arduino IDE but specifying BLB mode 3, the upload will report as failed as it can't verify the sketch, but will it still run as normal on the arduino or will the IDE abort and call the full reset function?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.