|
From: | Wouter van Gulik |
Subject: | [avr-chat] Re: EEprom Read on Tiny13 |
Date: | Mon, 22 Oct 2007 22:50:20 +0200 |
User-agent: | Thunderbird 1.5.0.13 (X11/20070824) |
Date: Mon, 22 Oct 2007 09:47:02 +0200 From: Robert von Knobloch <address@hidden> Subject: [avr-chat] EEprom Read on Tiny13 To: address@hidden Message-ID: <address@hidden> 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.
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......... #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 otherdevices ******* */ // #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 */
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
[Prev in Thread] | Current Thread | [Next in Thread] |