Reading fuses from firmware - wrong values when executing

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've a weird problem - reading fuses - mainly the lock fuse to ensure that the device is protected before running code properly.

Chip ATMEGA32A.

If I used the JTAG II debugger, and stop the code just before the function runs, the result is correct.
If I let the code run to a break point just after the read fuse LPM instruction ( or anywhere beyond ) then the result is incorrect.

There are no interrupts running - the three calls to 'boot_lock_get_fuse_bits' is early on in 'main'.
I read lock, high and low fuses.

I noticed this first in a production device having only just implimented the lock check ( even though the fuses were read, the results were not being used ).
Just before the lock bits were read is a conditional block that reads the eeprom. When options were such that the eeprom was read the fuse read was incorrect. If the options ignored the eeprom call, then the result was correct.
I assumed that there was some interaction but cannot see why.

If I insert a reasonable delay before reading the locks then the result is ok.
However - if I try to fix it by moving the code to right after the ports are initialised in main, ( no eeprom activity yet - the problem still exists in the production device ( except when debugging - perhaps because of the halt at 'main' itself. Again this may be because the production device has a bootloader which runs and does a write to the eeprom before entering main.
I can't see why this is occuring - I have another product that reads the fuses fine - although the code is probably sufficiently different ( not yet cross examined ).

I cant see where the LPM is affected by eeprom activity - but perhaps Ive missed something.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Post a minimal program that exhibits your symptoms.

Are you using very fierce lockbit settings?

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, I will make a strip down file, see if it has the problem and post.
When testing with the JTAG debugger no lock bits are set - it reads 0xFF when it works, 0x94 when it fails.

In production the lock bits are set of 0xFC, no further read/ verification to protect code.

So far it's quite repeatable.
The assembly code looks ok.
Rob

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This code is stripped down - behaves slightly differently but still exhibits the problem. fuseread 1 and fuse read 2 should end up the same. If the eeprom wite occurs then they are not ( fuseread2 is 0x94) however interestingly 'lock' itself ends up correct.

A delay after the eeprom rite appears to fix it in the original code. I hope this code highlights the problem.


#include 
#include  // for reading fuses
#include 



unsigned char EEMEM EE_resetdeviceflag;
unsigned char low,ext,high,lock;

unsigned char disabled = 0;
unsigned char fuseread1,fuseread2;


int main (void)
{

// Read fuses ...  new position. Reads FF with debugger

 	lock = boot_lock_fuse_bits_get ( GET_LOCK_BITS);

	fuseread1 = lock;

	eeprom_write_byte  ( &EE_resetdeviceflag  , 0x00 ) ; // This Line changes things 

 // *** Failed if eeprom write occurred just before accessing fuses
 // Works if sinle step

 	low = boot_lock_fuse_bits_get ( GET_LOW_FUSE_BITS);
 	high = boot_lock_fuse_bits_get ( GET_HIGH_FUSE_BITS);
 	lock = boot_lock_fuse_bits_get ( GET_LOCK_BITS);

	fuseread2 = lock;

while (1)
{

//	lock reads correct but fuseread2 reads 0x94 or 0xFF
	if (lock != 0xFC )
	{ disabled = 1;}

}






} // End Main
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This from the mega16 datasheet but probably similar in all AVR datasheets:

Quote:
25.8.8 EEPROM Write Prevents Writing to SPMCR
Note that an EEPROM write operation will block all software programming to Flash. Reading the Fuses and Lock bits from software will alsobe prevented during the EEPROM write operation. It is recommended that the user checks the status bit (EEWE) in the EECR Register and verifies that the bit is cleared before writing to the SPMCR Register.

Therefore, after the eeprom_write_byte() add a call to eeprom_busy_wait().

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thankyou! !! :)

I clearly missed it despite looking!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Although ... it is perhaps interesting that the code snippet ( when run with the eeprom write ) doesn't give the answers I would expect. If the second lock bit is corrupt - then examining 'lock' after all events should be corrupt as is 'fuseread2' however lock ends up at FF ( as it is from the first read ) and fuseread2 is the erroneous value.

Of interest to those curious... but I will add the check!