Date: Mon, 22 Oct 2007 09:47:02 +0200
From: Robert von Knobloch <[EMAIL PROTECTED]>
Subject: [avr-chat] EEprom Read on Tiny13
To: avr-chat@nongnu.org
Message-ID: <[EMAIL PROTECTED]>
Content-Type: text/plain; charset=UTF-8
I have solved my problem reading the EEPROM. Here is the answer in case
it helps anyone.
The library functions, defined in "avr-libc-1.4.6/libc/misc/eeprom.S"
always write a 16-Bit address to the EEAR register. This is expressly
forbidden in the Tiny13 datasheet and is the cause of my problems.
My solution was to edit eeprom.S and recompile avr-libc with the
following amendments (starred):
This breaks the current eeprom indeed.
However I don see a reason why we need the EEARH to be explicitly
defined? Unless it's undefined by mistake.
........
#define _EELABEL(x) CONCAT1(__,CONCAT1(x, CONCAT1
(_,__EEPROM_REG_LOCATIONS__)))
/* the same library is used for 2313 and 8515 for now -
I hope writing 0 to non-existent EEARH doesn't hurt... */
/* AVR Data sheet fot ATTiny13 forbids writing to this reserved address
- RvK */
/* Therefore comment out the next 3 lines ******* This may break other
devices ******* */
// #ifndef EEARH
// #define EEARH (EEARL+1)
// #endif
#ifdef L_eeprom_read_byte
/* read one byte from EEPROM.
addr = r26:r27, result = __tmp_reg__
Post increment r26:r27. */
.section .text.eeprom, "ax", @progbits
.global _EELABEL(eeprom_read_byte)
_EELABEL(eeprom_read_byte):
sbic _SFR_IO_ADDR(EECR), EEWE
rjmp _EELABEL(eeprom_read_byte) /* make sure EEPROM is ready */
#ifdef EEARH
out _SFR_IO_ADDR(EEARH),r27
#endif
out _SFR_IO_ADDR(EEARL),r26
sbi _SFR_IO_ADDR(EECR), EERE
// adiw r26,1 /* Increment x register */ /* ******* Wrong place
for the address increment -RvK ******* */
in __tmp_reg__, _SFR_IO_ADDR(EEDR)
ret
#endif /* L_eeprom_read_byte */
This might seems wrong if optimizing for speed. But it is smaller when
using read word and read block in the same time project, and there is no
penalty using just one of them.
There is however a small win to make. Now the actual copying from
zero_reg to a usable register is done using in the header file as a part
of a block assembler.
We could do an assembler instruction in the header file like this:
call eeprom_read_byte
in result, _SFR_IO_ADDR(EEDR)
Where result would be assigned by the compiler. This replaces the __tmp_reg__ move and
the "in __tmp_reg__ , SFR_IO_ADDR(EEDR)" could be gone from the assembler file
saving one instruction.
This would (in some/most? cases) eliminate the extra move from __tmp_reg__ to a
compiler usable location. This could save a cycle per eeprom_read_byte call! It
would also enable us to make eeprom_read_word return data as a real C function
(returning in r24:r25) at no extra cost.
But it would cost us one instruction extra in eeprom_read_block.
And it's not so elegant to do the read of EEDR after the call is done. But I
think it could work.
Down side is that this is smaller only when we can use in/out instructions on
EE registers. If atmel ever decides to move the EE register out of the in/out
range then we have a serious problem.
HTH
Wouter
_______________________________________________
AVR-chat mailing list
AVR-chat@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-chat