Sanity check: does eeprom_write_byte disable interrupts?

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

Hi all,

 

I tried to trace the source code for eeprom_write_byte (beginning at avr/eeprom.h) but got lost on the way...

Does this function (macro?) automatically disable interrupts during the write operation? Crude tests I did with an Arduino suggest that it doesn't, but I'd rather have an authoritative answer.

 

Thanks!

 

Last Edited: Mon. Oct 12, 2015 - 12:18 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just run it in the Simulator. You will be able to see for yourself.
A confession. I have never worried. I have just assumed that no-one in their right mind would violate the EEPROM setup timed sequence. It is important to disable interrupts before doing this 4-cycle "unlock". There is no need for them to be disabled during the actual eeprom write.

David.

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

Thanks David, I agree in principle, though I've seen too many cases where Right Mind had nothing to do with the actual code wink

I actually have too little experience with the Atmel Studio simulator, this may be a good place to start.

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

Ok... now I really don't understand smiley

 

I looked in the assembly listing (the .lss output file) for the eeprom_write_byte routine and there I found a definite cli. It also saves and restores SREG to re-enable interrupts as needed.

 

The thing is, since a write operation to EEPROM is supposed to take ~3ms, and it's non-blocking, one would expect that two consecutive eeprom_write_bytes would cause an interference (2nd write will not be performed). e.g. from the ATtiny85's datasheet, page 17: "While the device is busy with programming, it is not possible to do any other EEPROM operations." But in real life, it appears to work nonetheless. What did I miss?
"

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

Again, I have not looked. But the second write will have to wait for the BUSY to clear before it can do its 4-cycle unlock.
I would guess that the Simulator will simulate the eeprom write operation. i.e. you can put a breakpoint at the start of the second 4-cycle. And see how long the first write took.

Yes, I am sure that mistakes can happen. I just think that this will be so fundamental that no library author (or silicon designer) would overlook it.

Please let us know if you have discovered a bug.

David.

Last Edited: Mon. Oct 12, 2015 - 01:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried to trace the source code for eeprom_write_byte (beginning at avr/eeprom.h) but got lost on the way...

It's not that complex is it?

 

http://svn.savannah.nongnu.org/v...

 

Almost all of that is the:

#if  __AVR_XMEGA__	

case which just leaves this for tiny/mega:

1:	sbic	_SFR_IO_ADDR (EECR), EEWE
	rjmp	1b

# if	 defined (EEPM0) && defined (EEPM1)
	; Set programming mode: erase and write.
	out	_SFR_IO_ADDR (EECR), __zero_reg__
# elif	 defined (EEPM0) || defined (EEPM1)
#  error	/* Unknown EECR register.	*/
# endif

# ifdef	 EEARH
#  if	  E2END > 0xFF
	out	_SFR_IO_ADDR (EEARH), addr_hi
#  else
	; This is for chips like ATmega48: the EEAR8 bit must be cleaned.
	out	_SFR_IO_ADDR (EEARH), __zero_reg__
#  endif
# endif
	out	_SFR_IO_ADDR (EEARL), addr_lo
	out	_SFR_IO_ADDR (EEDR), r18
	in	__tmp_reg__, _SFR_IO_ADDR (SREG)
	cli
	sbi	_SFR_IO_ADDR (EECR), EEMWE
	sbi	_SFR_IO_ADDR (EECR), EEWE
	out	_SFR_IO_ADDR (SREG), __tmp_reg__
	adiw	addr_lo, 1
	ret

So the answer is "yes".

 

one would expect that two consecutive eeprom_write_bytes would cause an interference (2nd write will not be performed). e.g. from the ATtiny85's datasheet, page 17: "While the device is busy with programming, it is not possible to do any other EEPROM operations." But in real life, it appears to work nonetheless. What did I miss?

What makes you say that? The eeprom_write_byte starts with:

1:	sbic	_SFR_IO_ADDR (EECR), EEWE
	rjmp	1b

That waits until the EEPROM is ready to perform the operation so if it is still busy from "last time" it waits here (but at this stage interrupts are enabled).

 

By the way, in this day and age no one should be calling eeprom_write_byte() directly. You should always use eeprom_update_byte() in preference.

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

Does this function (macro?) automatically disable interrupts during the write operation?

Well, it does disable interrupts ... during the critical period.  Just as the datasheet suggests, right?

Caution: An interrupt between step 5 and step 6 will make the write cycle fail, since the
EEPROM Master Write Enable will time-out. If an interrupt routine accessing the EEPROM is
interrupting another EEPROM access, the EEAR or EEDR Register will be modified, causing the
interrupted EEPROM access to fail. It is recommended to have the Global Interrupt Flag cleared
during all the steps to avoid these problems.

 

If indeed there are two writes in a row, it will eventually be done and not discarded.  You have to wait for the second byte.

 

Most work nowadays will use the "update" functions rather than the "write" functions, to avoid writing a new value that is the same as the existing value.

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

clawson wrote:

It's not that complex is it?

http://svn.savannah.nongnu.org/v...

 

Heh, as my math teachers used to say, "the final answer is less important, show me how you got there" smiley

 

clawson wrote:

What makes you say that? The eeprom_write_byte starts with:

1:	sbic	_SFR_IO_ADDR (EECR), EEWE
	rjmp	1b

That waits until the EEPROM is ready to perform the operation so if it is still busy from "last time" it waits here (but at this stage interrupts are enabled).

 

Ok. It's my very partial knowledge of the instruction set I guess. Problem solved - thanks!

 

clawson wrote:

By the way, in this day and age no one should be calling eeprom_write_byte() directly. You should always use eeprom_update_byte() in preference.

 

That is also true. The thing is, I'm studying the source code of Arduino in depth (for some wiki I'm writing), and there they're still using write. Following from there I got here...

 

Thank you all!