attiny2313 EEPROM library code larger again

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

Just looking at my code to see where the bytes have gone, and I noticed this EEPROM READ BYTE code from WinAVR 2010.01.10

	out	0x1f, r1	; 31
	out	0x1e, r24	; 30
	sbi	0x1c, 0	; 28
	eor	r25, r25
	in	r24, 0x1d	; 29

The first "out" instruction sets the High Byte of the address to zero. Or it would, if the High Byte of the address was defined on an ATTINY2313. Actually, register ox1f is reserved. The "eor" sets the high byte of the data byte to zero. Or it would, if the data byte had a high byte.

The good thing is that each processor is separately declared in EEPROM.h, so unique code can be used for each processor. The bad thing (apart from using the wrong code) is that eeprom_read_byte is no longer static inline, which adds another 4 bytes.

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

melbourne wrote:
The first "out" instruction sets the High Byte of the address to zero. Or it would, if the High Byte of the address was defined on an ATTINY2313.

The relevant part of source ([avr-libc-1.6.8]\libc\misc\eerd_byte.S):
1:	sbic	_SFR_IO_ADDR (EECR), EEWE
	rjmp	1b
# 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
	sbi	_SFR_IO_ADDR (EECR), EERE
	clr	ret_hi
	in	ret_lo, _SFR_IO_ADDR (EEDR)
	ret

This is compiled through some make magic which mangles the source name and is also responsible for adding the proper compile-line switches, although I am unable to decipher how does this exactly work.

Apparently, in this case something goes wrong for this process and EEARH gets defined, even if it is not defined in iotn2313.h. You might want to submit a bug report on avr-libc tracker.

Clearing of r25 may seem redundant but I am afraid this is required by the avr-gcc ABI, that the actual value returned from a function is at least of width int regardless of the declared type. I haven't found a definitive avr-gcc ABI documentation so far :-( .

Quote:
The bad thing (apart from using the wrong code) is that eeprom_read_byte is no longer static inline, which adds another 4 bytes.

If you use a lot of eeprom_read_byte() calls in your program, this actually saves space at the cost of slightly slower execution and 2 bytes on the stack.

JW

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

wek wrote:

Clearing of r25 may seem redundant but I am afraid this is required by the avr-gcc ABI, that the actual value returned from a function is at least of width int regardless of the declared type. I haven't found a definitive avr-gcc ABI documentation so far :-( .
...
If you use a lot of eeprom_read_byte() calls in your program, this actually saves space at the cost of slightly slower execution and 2 bytes on the stack.

JW

That's unfortunate. The Word Alignment makes sense (using r24 instead of r25), but sign extending something that is declared as char seems perverse. I wonder if internally GCC is now 16 bit char with demotion instead of 8 bit with promotion?

If you use a lot of eeprom_read_byte, you can wrap it in a non-inline wrapper. On the other hand, if you use only 1 eeprom_read_byte, can you get rid of the "ret" in the non-inline version? I suspect that there have been different opinions about that over the years. In any case, I'm shifting to using more in-line assembly for eeprom: I can't afford the extra bytes.

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

Quote:

I haven't found a definitive avr-gcc ABI documentation so far

Here:

http://www.nongnu.org/avr-libc/u...

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

clawson wrote:
Quote:

I haven't found a definitive avr-gcc ABI documentation so far

Here:

http://www.nongnu.org/avr-libc/u...


I am aware of that section. However, its wording is ambiguous and has been recently changed quite substantially. Current wording is (emphasis by me):
Quote:
Return values: 8-bit in r24 (not r25!) [...]. 8-bit return values are zero/sign-extended to 16 bits by the called function (unsigned char is more efficient than signed char - just clr r25).
The "not r25" contradicts "called function extends", and the older wording was "caller extends".

I know in the *nix word the definitive documentation is the source, but I hoped for something in between this lousy one and that complicated one ;-)

JW