avr-chat
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-chat] Re: EEprom Read on Tiny13


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.
........
#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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]