Index: include/avr/eeprom.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/eeprom.h,v retrieving revision 1.12 diff -U12 -r1.12 eeprom.h --- include/avr/eeprom.h 13 Jan 2005 10:56:10 -0000 1.12 +++ include/avr/eeprom.h 30 Jul 2005 18:13:08 -0000 @@ -26,144 +26,353 @@ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* $Id: eeprom.h,v 1.12 2005/01/13 10:56:10 joerg_wunsch Exp $ */ /* eeprom.h Contributors: Created by Marek Michalkiewicz - eeprom_write_word and eeprom_write_block added by Artur Lipowski + eeprom_write_word and eeprom_write_block added by Artur Lipowski + + Complete rewrite using the original interface by Bjoern Haase + . Contributed with kind permission of + Robert Bosch GmbH. */ #ifndef _EEPROM_H_ #define _EEPROM_H_ 1 #define __need_size_t #include #include + +#ifdef __AVR_MEGA__ +#define XCALL "call" +#else +#define XCALL "rcall" +#endif + #include +#ifndef __EEPROM_REG_LOCATIONS__ +/** \def __EEPROM_REG_LOCATIONS__ + \ingroup avr_eeprom + In order to be able to work without a requiring a multilib + approach for dealing with controllers having the EEPROM registers + at different positions in memory space, the eeprom functions evaluate + __EEPROM_REG_LOCATIONS__: It is assumed to be defined by + the device io header and contains 6 uppercase hex digits encoding the + addresses of EECR,EEDR and EEAR. + First two letters: EECR address. + Second two letters: EEDR address. + Last two letters: EEAR address. + The default 1C1D1E corresponds to the + register location that is valid for most controllers. The value + of this define symbol is used for appending it to the base name of the + assembler functions. */ +#define __EEPROM_REG_LOCATIONS__ 1C1D1E +#endif +#define _STR2(EXP) _STR1(EXP) +#define _STR1(EXP) #EXP +#define _REG_LOCATION_SUFFIX _STR2(__EEPROM_REG_LOCATIONS__) + +#ifndef CR_TAB +#define CR_TAB "\n\t" +#endif + /** \defgroup avr_eeprom EEPROM handling \code #include \endcode This header file declares the interface to some simple library routines suitable for handling the data EEPROM contained in the AVR microcontrollers. The implementation uses a simple polled mode interface. Applications that require interrupt-controlled EEPROM access to ensure that no time will be wasted in spinloops will have to deploy their own implementation. \note All of the read/write functions first make sure the EEPROM is ready to be accessed. Since this may cause long delays if a write operation is still pending, time-critical applications should first poll the EEPROM e. g. using eeprom_is_ready() before attempting any actual I/O. - \note This library will \e not work with the following devices since these - devices have the EEPROM IO ports at different locations: - - - AT90CAN128 - - ATmega48 - - ATmega88 - - ATmega165 - - ATmega168 - - ATmega169 - - ATmega325 - - ATmega3250 - - ATmega645 - - ATmega6450 + \note This header file declares inline functions that call the + assembler subroutines directly. This prevents that the compiler + generates push/pops for the call-clobbered registers. This way + also a specific calling convention could be used for the eeprom + routines by passing values in __tmp_reg__, eeprom addresses in X + and memory addresses in Z registers. Method is optimized for code + size. + + \note Presently supported are two locations of the EEPROM register + set: 0x1F,0x20,0x21 and 0x1C,0x1D,0x1E + (see ::__EEPROM_REG_LOCATIONS__). */ -#if defined(__AVR_AT90CAN128__) || defined(__AVR_ATmega48__) ||\ - defined(__AVR_ATmega88__) || defined(__AVR_ATmega165__) ||\ - defined(__AVR_ATmega168__) || defined(__AVR_ATmega169__) ||\ - defined(__AVR_ATmega325__) || defined(__AVR_ATmega3250__) ||\ - defined(__AVR_ATmega645__) || defined(__AVR_ATmega6450__) -# warning "The functions from are not supported on this MCU." -#endif + +/* forward declarations of the inline functions so that doxygen does + not get confused by the attribute expression. */ + +uint8_t static inline __attribute__ ((always_inline)) +eeprom_read_byte (const uint8_t *addr); + +uint16_t static inline __attribute__ ((always_inline)) +eeprom_read_word (const uint16_t *addr); + +void static inline __attribute__ ((always_inline)) +eeprom_read_block (const void *pointer_eeprom, + void *pointer_ram, + size_t size); + +void static inline __attribute__ ((always_inline)) +eeprom_write_byte (uint8_t *addr,uint8_t value); + +void static inline __attribute__ ((always_inline)) +eeprom_write_word (uint16_t *addr,uint16_t value); + +void static inline __attribute__ ((always_inline)) +eeprom_write_block (void *pointer_eeprom, + const void *pointer_ram, + size_t size); /** \name avr-libc declarations */ /address@hidden/ +/** \def EEMEM + \ingroup avr_eeprom + Attribute expression causing a variable to be allocated within the .eeprom + section. */ +#define EEMEM __attribute__((section(".eeprom"))) + /** \def eeprom_is_ready \ingroup avr_eeprom \returns 1 if EEPROM is ready for a new read/write operation, 0 if not. */ #define eeprom_is_ready() bit_is_clear(EECR, EEWE) /** \def eeprom_busy_wait \ingroup avr_eeprom Loops until the eeprom is no longer busy. \returns Nothing. */ #define eeprom_busy_wait() do {} while (!eeprom_is_ready()) -#ifdef __cplusplus -extern "C" { -#endif /** \ingroup avr_eeprom Read one byte from EEPROM address \c addr. */ -extern uint8_t eeprom_read_byte (const uint8_t *addr); +uint8_t +eeprom_read_byte (const uint8_t *addr) +{ + uint8_t result; + asm ( XCALL " __eeprom_read_byte_" _REG_LOCATION_SUFFIX CR_TAB + "mov %1,__tmp_reg__" + : "+x" (addr), + "=r" (result) + : ); + return result; +} /** \ingroup avr_eeprom Read one 16-bit word (little endian) from EEPROM address \c addr. */ - -extern uint16_t eeprom_read_word (const uint16_t *addr); +uint16_t +eeprom_read_word (const uint16_t *addr) +{ + uint16_t result; + asm ( XCALL " __eeprom_read_byte_" _REG_LOCATION_SUFFIX CR_TAB + "mov %A1,__tmp_reg__" CR_TAB + XCALL " __eeprom_read_byte_" _REG_LOCATION_SUFFIX CR_TAB + "mov %B1,__tmp_reg__" + : "+x" (addr), + "=r" (result) + : ); + return result; +} /** \ingroup avr_eeprom - Read a block of \c n bytes from EEPROM address \c addr to - \c buf. */ - -extern void eeprom_read_block (void *buf, const void *addr, size_t n); + Read a block of \c n bytes from EEPROM address \c pointer_eeprom to + \c pointer_ram. For constant n <= 256 bytes a library function is used. + For block sizes unknown at compile time or block sizes > 256 an inline + loop is expanded. */ + +void +eeprom_read_block (const void *pointer_eeprom, + void *pointer_ram, + size_t n) +{ + if (!__builtin_constant_p (n) + || n > 256) + { + uint8_t *p_ram = (uint8_t *) pointer_ram; + uint8_t *p_eeprom = (uint8_t *) pointer_eeprom; + + while (n) + { + uint8_t value; + + asm ( XCALL " __eeprom_read_byte_" _REG_LOCATION_SUFFIX CR_TAB + "mov %1,__tmp_reg__" + : "+x" (p_eeprom), + "=r" (value) + : ); + *p_ram = value; + p_ram += 1; + + n -= 1; + } + } + else + { + if (n != 0) + { + if (n == 256) + { + asm volatile ( + XCALL " __eeprom_read_block_" _REG_LOCATION_SUFFIX + : "+x" (pointer_eeprom), + "=z" (pointer_ram) + : "z" (pointer_ram) + : "memory"); + } + else + { + /* Needed in order to truncate to 8 bit. */ + uint8_t len; + len = (uint8_t) n; + + asm volatile ( + "mov __zero_reg__,%2" CR_TAB + XCALL " __eeprom_read_block_" _REG_LOCATION_SUFFIX + : "+x" (pointer_eeprom), + "=z" (pointer_ram) + : "r" (len), + "z" (pointer_ram) + : "memory"); + } + } + } +} /** \ingroup avr_eeprom - Write a byte \c val to EEPROM address \c addr. */ + Write a byte \c value to EEPROM address \c addr. */ -extern void eeprom_write_byte (uint8_t *addr, uint8_t val); +void +eeprom_write_byte (uint8_t *addr,uint8_t value) +{ + asm volatile ( + "mov __tmp_reg__,%1" CR_TAB + XCALL " __eeprom_write_byte_" _REG_LOCATION_SUFFIX + : "+x" (addr) + : "r" (value) + : "memory" + ); +} /** \ingroup avr_eeprom - Write a word \c val to EEPROM address \c addr. */ + Write a word \c value to EEPROM address \c addr. */ -extern void eeprom_write_word (uint16_t *addr, uint16_t val); +void +eeprom_write_word (uint16_t *addr,uint16_t value) +{ + asm volatile ( + "mov __tmp_reg__,%A1" CR_TAB + XCALL " __eeprom_write_byte_" _REG_LOCATION_SUFFIX CR_TAB + "mov __tmp_reg__,%B1" CR_TAB + XCALL " __eeprom_write_byte_" _REG_LOCATION_SUFFIX + : "+x" (addr) + : "r" (value) + : "memory" + ); +} /** \ingroup avr_eeprom - Write a block of \c n bytes to EEPROM address \c addr from - \c buf. */ + Write a block of \c size bytes to EEPROM address \c pointer_eeprom from + \c pointer_ram. */ -extern void eeprom_write_block (const void *buf, void *addr, size_t n); +void +eeprom_write_block (void *pointer_eeprom, + const void *pointer_ram, + size_t size) +{ + if (!__builtin_constant_p (size) + || size > 256) + { + uint8_t *p_ram = (uint8_t *) pointer_ram; + uint8_t *p_eeprom = (uint8_t *) pointer_eeprom; + + while (size) + { + uint8_t value; + value = *p_ram; + p_ram ++; + asm volatile ( + "mov __tmp_reg__,%1" CR_TAB + XCALL " __eeprom_write_byte_" _REG_LOCATION_SUFFIX + : "+x" (p_eeprom) + : "r" (value) + : "memory" + ); + size -= 1; + } + } + else + { + if (size != 0) + { + if (size == 256) + { + asm volatile ( + XCALL " __eeprom_write_block_" _REG_LOCATION_SUFFIX + : "+x" (pointer_eeprom), + "=z" (pointer_ram) + : "z" (pointer_ram) + : "memory" ); + } + else + { + uint8_t len; + len = (uint8_t) size; + + asm volatile ( + "mov __zero_reg__,%2" CR_TAB + XCALL " __eeprom_write_block_" _REG_LOCATION_SUFFIX + : "+x" (pointer_eeprom), + "=z" (pointer_ram) + : "r" (len), + "z" (pointer_ram) + : "memory" ); + } -#ifdef __cplusplus + } + } } -#endif /address@hidden/ /** \name IAR C compatibility defines */ /address@hidden/ /** \def _EEPUT \ingroup avr_eeprom - Write a byte to EEPROM. */ + Write a byte to EEPROM. Compatibility define for IAR C. */ #define _EEPUT(addr, val) eeprom_write_byte ((uint8_t *)(addr), (uint8_t)(val)) /** \def _EEGET \ingroup avr_eeprom - Read a byte from EEPROM. */ + Read a byte from EEPROM. Compatibility define for IAR C. */ #define _EEGET(var, addr) (var) = eeprom_read_byte ((uint8_t *)(addr)) /address@hidden/ #endif /* _EEPROM_H_ */ Index: include/avr/iocan128.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/iocan128.h,v retrieving revision 1.13 diff -U12 -r1.13 iocan128.h --- include/avr/iocan128.h 28 Jul 2005 17:41:00 -0000 1.13 +++ include/avr/iocan128.h 30 Jul 2005 18:13:11 -0000 @@ -115,24 +115,32 @@ /* RegDef: EEPROM Control Register */ #define EECR _SFR_IO8(0x1F) /* RegDef: EEPROM Data Register */ #define EEDR _SFR_IO8(0x20) /* RegDef: EEPROM Address Register */ #define EEAR _SFR_IO16(0x21) #define EEARL _SFR_IO8(0x21) #define EEARH _SFR_IO8(0x22) +/* 6-char sequence denoting where to find the EEPROM registers in memory space. + Adresses denoted in hex syntax with uppercase letters. Used by the EEPROM + subroutines. + First two letters: EECR address. + Second two letters: EEDR address. + Last two letters: EEAR address. */ +#define __EEPROM_REG_LOCATIONS__ 1F2021 + /* RegDef: General Timer/Counter Control Register */ #define GTCCR _SFR_IO8(0x23) /* RegDef: Timer/Counter Control Register A */ #define TCCR0A _SFR_IO8(0x24) /* RegDef: Timer/Counter Register */ #define TCNT0 _SFR_IO8(0x26) /* RegDef: Output Compare Register A */ #define OCR0A _SFR_IO8(0x27) Index: include/avr/iom165.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/iom165.h,v retrieving revision 1.4 diff -U12 -r1.4 iom165.h --- include/avr/iom165.h 9 Jul 2005 14:01:11 -0000 1.4 +++ include/avr/iom165.h 30 Jul 2005 18:13:12 -0000 @@ -111,24 +111,32 @@ #define EERE 0 #define EEWE 1 #define EEMWE 2 #define EERIE 3 #define EEDR _SFR_IO8(0X20) /* Combine EEARL and EEARH */ #define EEAR _SFR_IO16(0x21) #define EEARL _SFR_IO8(0x21) #define EEARH _SFR_IO8(0X22) +/* 6-char sequence denoting where to find the EEPROM registers in memory space. + Adresses denoted in hex syntax with uppercase letters. Used by the EEPROM + subroutines. + First two letters: EECR address. + Second two letters: EEDR address. + Last two letters: EEAR address. */ +#define __EEPROM_REG_LOCATIONS__ 1F2021 + #define GTCCR _SFR_IO8(0x23) #define PSR10 0 #define PSR2 1 #define TSM 7 #define TCCR0A _SFR_IO8(0x24) #define CS00 0 #define CS01 1 #define CS02 2 #define WGM01 3 #define COM0A0 4 #define COM0A1 5 Index: include/avr/iom169.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/iom169.h,v retrieving revision 1.21 diff -U12 -r1.21 iom169.h --- include/avr/iom169.h 9 Jul 2005 14:01:11 -0000 1.21 +++ include/avr/iom169.h 30 Jul 2005 18:13:13 -0000 @@ -106,24 +106,32 @@ /* General Purpose I/O Register 0 */ #define GPIOR0 _SFR_IO8(0x1E) #define EECR _SFR_IO8(0x1F) #define EEDR _SFR_IO8(0X20) /* Combine EEARL and EEARH */ #define EEAR _SFR_IO16(0x21) #define EEARL _SFR_IO8(0x21) #define EEARH _SFR_IO8(0X22) +/* 6-char sequence denoting where to find the EEPROM registers in memory space. + Adresses denoted in hex syntax with uppercase letters. Used by the EEPROM + subroutines. + First two letters: EECR address. + Second two letters: EEDR address. + Last two letters: EEAR address. */ +#define __EEPROM_REG_LOCATIONS__ 1F2021 + /* General Timer/Counter Control Register */ #define GTCCR _SFR_IO8(0x23) /* Timer/Counter Control Register A */ #define TCCR0A _SFR_IO8(0x24) /* Timer/Counter Register */ #define TCNT0 _SFR_IO8(0x26) /* Output Compare Register A */ #define OCR0A _SFR_IO8(0x27) Index: include/avr/iom325.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/iom325.h,v retrieving revision 1.5 diff -U12 -r1.5 iom325.h --- include/avr/iom325.h 9 Jul 2005 14:01:11 -0000 1.5 +++ include/avr/iom325.h 30 Jul 2005 18:13:13 -0000 @@ -110,24 +110,33 @@ #define EERE 0 #define EEWE 1 #define EEMWE 2 #define EERIE 3 #define EEDR _SFR_IO8(0X20) /* Combine EEARL and EEARH */ #define EEAR _SFR_IO16(0x21) #define EEARL _SFR_IO8(0x21) #define EEARH _SFR_IO8(0X22) +/* 6-char sequence denoting where to find the EEPROM registers in memory space. + Adresses denoted in hex syntax with uppercase letters. Used by the EEPROM + subroutines. + First two letters: EECR address. + Second two letters: EEDR address. + Last two letters: EEAR address. */ +#define __EEPROM_REG_LOCATIONS__ 1F2021 + + #define GTCCR _SFR_IO8(0x23) #define PSR10 0 #define PSR2 1 #define TSM 7 #define TCCR0A _SFR_IO8(0x24) #define CS00 0 #define CS01 1 #define CS02 2 #define WGM01 3 #define COM0A0 4 #define COM0A1 5 Index: include/avr/iom3250.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/iom3250.h,v retrieving revision 1.5 diff -U12 -r1.5 iom3250.h --- include/avr/iom3250.h 9 Jul 2005 14:01:11 -0000 1.5 +++ include/avr/iom3250.h 30 Jul 2005 18:13:17 -0000 @@ -114,24 +114,32 @@ #define EERE 0 #define EEWE 1 #define EEMWE 2 #define EERIE 3 #define EEDR _SFR_IO8(0X20) /* Combine EEARL and EEARH */ #define EEAR _SFR_IO16(0x21) #define EEARL _SFR_IO8(0x21) #define EEARH _SFR_IO8(0X22) +/* 6-char sequence denoting where to find the EEPROM registers in memory space. + Adresses denoted in hex syntax with uppercase letters. Used by the EEPROM + subroutines. + First two letters: EECR address. + Second two letters: EEDR address. + Last two letters: EEAR address. */ +#define __EEPROM_REG_LOCATIONS__ 1F2021 + #define GTCCR _SFR_IO8(0x23) #define PSR10 0 #define PSR2 1 #define TSM 7 #define TCCR0A _SFR_IO8(0x24) #define CS00 0 #define CS01 1 #define CS02 2 #define WGM01 3 #define COM0A0 4 #define COM0A1 5 Index: include/avr/iom645.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/iom645.h,v retrieving revision 1.5 diff -U12 -r1.5 iom645.h --- include/avr/iom645.h 9 Jul 2005 14:01:11 -0000 1.5 +++ include/avr/iom645.h 30 Jul 2005 18:13:17 -0000 @@ -110,24 +110,32 @@ #define EERE 0 #define EEWE 1 #define EEMWE 2 #define EERIE 3 #define EEDR _SFR_IO8(0X20) /* Combine EEARL and EEARH */ #define EEAR _SFR_IO16(0x21) #define EEARL _SFR_IO8(0x21) #define EEARH _SFR_IO8(0X22) +/* 6-char sequence denoting where to find the EEPROM registers in memory space. + Adresses denoted in hex syntax with uppercase letters. Used by the EEPROM + subroutines. + First two letters: EECR address. + Second two letters: EEDR address. + Last two letters: EEAR address. */ +#define __EEPROM_REG_LOCATIONS__ 1F2021 + #define GTCCR _SFR_IO8(0x23) #define PSR10 0 #define PSR2 1 #define TSM 7 #define TCCR0A _SFR_IO8(0x24) #define CS00 0 #define CS01 1 #define CS02 2 #define WGM01 3 #define COM0A0 4 #define COM0A1 5 Index: include/avr/iom6450.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/iom6450.h,v retrieving revision 1.5 diff -U12 -r1.5 iom6450.h --- include/avr/iom6450.h 9 Jul 2005 14:01:11 -0000 1.5 +++ include/avr/iom6450.h 30 Jul 2005 18:13:17 -0000 @@ -114,24 +114,32 @@ #define EERE 0 #define EEWE 1 #define EEMWE 2 #define EERIE 3 #define EEDR _SFR_IO8(0X20) /* Combine EEARL and EEARH */ #define EEAR _SFR_IO16(0x21) #define EEARL _SFR_IO8(0x21) #define EEARH _SFR_IO8(0X22) +/* 6-char sequence denoting where to find the EEPROM registers in memory space. + Adresses denoted in hex syntax with uppercase letters. Used by the EEPROM + subroutines. + First two letters: EECR address. + Second two letters: EEDR address. + Last two letters: EEAR address. */ +#define __EEPROM_REG_LOCATIONS__ 1F2021 + #define GTCCR _SFR_IO8(0x23) #define PSR10 0 #define PSR2 1 #define TSM 7 #define TCCR0A _SFR_IO8(0x24) #define CS00 0 #define CS01 1 #define CS02 2 #define WGM01 3 #define COM0A0 4 #define COM0A1 5 Index: include/avr/iomx8.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/iomx8.h,v retrieving revision 1.8 diff -U12 -r1.8 iomx8.h --- include/avr/iomx8.h 9 Jul 2005 14:01:11 -0000 1.8 +++ include/avr/iomx8.h 30 Jul 2005 18:13:17 -0000 @@ -199,24 +199,32 @@ #define EEDR _SFR_IO8(0X20) /* Combine EEARL and EEARH */ #define EEAR _SFR_IO16(0x21) #define EEARL _SFR_IO8(0x21) #define EEARH _SFR_IO8(0X22) /* Even though EEARH is not used by the mega48, the EEAR8 bit in the register must be written to 0, according to the datasheet, hence the EEARH register must be defined for the mega48. */ +/* 6-char sequence denoting where to find the EEPROM registers in memory space. + Adresses denoted in hex syntax with uppercase letters. Used by the EEPROM + subroutines. + First two letters: EECR address. + Second two letters: EEDR address. + Last two letters: EEAR address. */ +#define __EEPROM_REG_LOCATIONS__ 1F2021 + #define GTCCR _SFR_IO8 (0x23) /* GTCCR */ #define TSM 7 #define PSRASY 1 #define PSRSYNC 0 #define TCCR0A _SFR_IO8 (0x24) /* TCCR0A */ #define COM0A1 7 #define COM0A0 6 #define COM0B1 5 Index: libc/misc/Makefile.am =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/libc/misc/Makefile.am,v retrieving revision 1.2 diff -U12 -r1.2 Makefile.am --- libc/misc/Makefile.am 17 Jul 2003 19:52:23 -0000 1.2 +++ libc/misc/Makefile.am 30 Jul 2005 18:13:17 -0000 @@ -21,40 +21,51 @@ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. ## Process this file with automake to generate Makefile.in noinst_LIBRARIES = lib.a -lib_a_asm_sources = \ +eeprom_asm_sources = \ ee_rb.S \ ee_rblk.S \ - ee_rw.S \ ee_wb.S \ - ee_ww.S \ - ee_wblk.S \ + ee_wblk.S + +lib_a_asm_sources = \ itoa.S \ ltoa.S \ mulsi10.S \ mul10.S \ ultoa.S \ utoa.S lib_a_SOURCES = $(lib_a_asm_sources) lib_a_asm_objs = $(lib_a_asm_sources:%.S=%.o) +lib_a_LIBADD = $(eeprom_asm_sources:%.S=%.1F2021.o) \ + $(eeprom_asm_sources:%.S=%.1C1D1E.o) + +lib_a_DEPENDENCIES = $(eeprom_asm_sources:%.S=%.1F2021.o) \ + $(eeprom_asm_sources:%.S=%.1C1D1E.o) + # must be added to the package, but automake doesn't know it as source # file until now EXTRA_DIST = eeprom.S # content of AVRLIB_CFLAGS and AVRLIB_ASFLAGS is determined by configure # according to the multilib subdir (see acinclude.m4 in top directory) $(lib_a_asm_objs): %.o: %.S $(COMPILE) $(AVRLIB_ASFLAGS) -c $< -o $@ +%.1C1D1E.o: %.S + $(COMPILE) $(AVRLIB_ASFLAGS) -c $< -o $@ -DEEPROM_REG_LOCATIONS_OVERRIDE=1C1D1E + +%.1F2021.o: %.S + $(COMPILE) $(AVRLIB_ASFLAGS) -c $< -o $@ -DEEPROM_REG_LOCATIONS_OVERRIDE=1F2021 Index: libc/misc/eeprom.S =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/libc/misc/eeprom.S,v retrieving revision 1.3 diff -U12 -r1.3 eeprom.S --- libc/misc/eeprom.S 17 Jul 2003 19:52:23 -0000 1.3 +++ libc/misc/eeprom.S 30 Jul 2005 18:13:17 -0000 @@ -27,216 +27,158 @@ POSSIBILITY OF SUCH DAMAGE. */ /* eeprom.S Contributors: Created by Marek Michalkiewicz eeprom_write_word and eeprom_write_block added by Artur Lipowski */ #include "macros.inc" #include "ctoasm.inc" +#include "avr/io.h" +#ifndef __EEPROM_REG_LOCATIONS__ +/* 6-byte string denoting where to find the EEPROM registers in memory space. + Adresses denoted in hex syntax with uppercase letters. Used by the EEPROM + subroutines. + First two letters: EECR address. + Second two letters: EEDR address. + Last two letters: EEAR address. */ +#define __EEPROM_REG_LOCATIONS__ 1C1D1E +#endif + +/* As long as we don't have a proper multilib environment: Let's make it + possible to override the locations defined in the io headers. */ +#ifdef EEPROM_REG_LOCATIONS_OVERRIDE + +#undef __EEPROM_REG_LOCATIONS__ +#define __EEPROM_REG_LOCATIONS__ EEPROM_REG_LOCATIONS_OVERRIDE + +#define HEXNR CONCAT1(0x , EEPROM_REG_LOCATIONS_OVERRIDE) + +#ifdef EECR +#undef EECR +#define EECR _SFR_IO8((HEXNR >> 16) & 0xFF) +#endif + +#ifdef EEDR +#undef EEDR +#define EEDR _SFR_IO8((HEXNR >> 8) & 0xFF ) +#endif + +#ifdef EEAR +#undef EEAR +#define EEAR _SFR_IO8(HEXNR & 0xFF) +#endif + +#ifdef EEARH +#undef EEARH +#endif + +#ifdef EEARL +#undef EEARL +#define EEARL EEAR +#endif + +#endif + +#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... */ #ifndef EEARH #define EEARH (EEARL+1) #endif -#define addr_hi rP0 -#define addr_lo rP1 -#define res_hi rP0 -#define res_lo rP1 #ifdef L_eeprom_read_byte -/* read one byte from EEPROM */ -/* uint8_t eeprom_read_byte(const uint8_t *addr); */ -/* addr = r25:r24, result = r25(=0):r24 */ +/* read one byte from EEPROM. + addr = r26:r27, result = __tmp_reg__ + Post increment r26:r27. */ + +#define addr_hi r27 +#define addr_lo r26 +#define res_lo __tmp_reg__ .section .text - .global _U(eeprom_read_byte) + .global _EELABEL(eeprom_read_byte) -_U(eeprom_read_byte): +_EELABEL(eeprom_read_byte): sbic _SFR_IO_ADDR(EECR), EEWE - rjmp _U(eeprom_read_byte) /* make sure EEPROM is ready */ + rjmp _EELABEL(eeprom_read_byte) /* make sure EEPROM is ready */ #ifdef EEARH out _SFR_IO_ADDR(EEARH), addr_hi #endif out _SFR_IO_ADDR(EEARL), addr_lo sbi _SFR_IO_ADDR(EECR), EERE - clr res_hi /* gcc wants result extended to "int"? */ + adiw r26,1 /* Increment x register */ in res_lo, _SFR_IO_ADDR(EEDR) ret #endif /* L_eeprom_read_byte */ -#ifdef L_eeprom_read_word -/* read a little endian 16-bit word from EEPROM */ -/* uint16_t eeprom_read_word(const uint16_t *addr); */ -/* addr = r25:r24, result = r25:r24 */ - - .global _U(eeprom_read_word) - -_U(eeprom_read_word): - sbic _SFR_IO_ADDR(EECR), EEWE - rjmp _U(eeprom_read_word) /* make sure EEPROM is ready */ -#ifdef EEARH - out _SFR_IO_ADDR(EEARH), addr_hi -#endif - out _SFR_IO_ADDR(EEARL), addr_lo - sbi _SFR_IO_ADDR(EECR), EERE - adiw addr_lo, 1 - in __tmp_reg__, _SFR_IO_ADDR(EEDR) -#ifdef EEARH - out _SFR_IO_ADDR(EEARH), addr_hi -#endif - out _SFR_IO_ADDR(EEARL), addr_lo - sbi _SFR_IO_ADDR(EECR), EERE - mov res_lo, __tmp_reg__ - in res_hi, _SFR_IO_ADDR(EEDR) - ret -#endif /* L_eeprom_read_word */ - -#undef res_hi -#undef res_lo #ifdef L_eeprom_write_byte -/* write a byte to EEPROM */ -/* void eeprom_write_byte(uint8_t *addr, uint8_t val); */ -/* addr = r25:r24, val = r22 */ -#define val rP3 +/* write a byte to EEPROM + Address in r26:r27, value in __tmp_reg__ + Post increment r26:r27. */ +#define addr_hi r27 +#define addr_lo r26 +#define val __tmp_reg__ - .global _U(eeprom_write_byte) + .global _EELABEL(eeprom_write_byte) -_U(eeprom_write_byte): +_EELABEL(eeprom_write_byte): sbic _SFR_IO_ADDR(EECR), EEWE - rjmp _U(eeprom_write_byte) /* make sure EEPROM is ready */ + rjmp _EELABEL(eeprom_write_byte) /* make sure EEPROM is ready */ #ifdef EEARH out _SFR_IO_ADDR(EEARH), addr_hi #endif out _SFR_IO_ADDR(EEARL), addr_lo out _SFR_IO_ADDR(EEDR), val + adiw r26,1 /* Increment x register */ in __tmp_reg__, _SFR_IO_ADDR(SREG) cli ; /* no ints between setting EEMWE and EEWE */ sbi _SFR_IO_ADDR(EECR), EEMWE sbi _SFR_IO_ADDR(EECR), EEWE out _SFR_IO_ADDR(SREG), __tmp_reg__ ret #undef val #endif /* L_eeprom_write_byte */ -#ifdef L_eeprom_write_word -/* write a word to EEPROM */ -/* void eeprom_write_word (uint16_t *addr, uint16_t val); */ -/* addr = r25:r24, val = r23:r22 */ -#define val_hi rP2 -#define val_lo rP3 - - .global _U(eeprom_write_word) - -_U(eeprom_write_word): - ser rTI0 ; set flag to indicate that - ; the first (LSB) byte will be written - in __tmp_reg__, _SFR_IO_ADDR(SREG) -eeprom_write_word_start: - sbic _SFR_IO_ADDR(EECR), EEWE - rjmp eeprom_write_word_start ; make sure EEPROM is ready -#ifdef EEARH - out _SFR_IO_ADDR(EEARH), addr_hi -#endif - out _SFR_IO_ADDR(EEARL), addr_lo - out _SFR_IO_ADDR(EEDR), val_lo - cli ; no ints between setting EEMWE and EEWE - sbi _SFR_IO_ADDR(EECR), EEMWE - sbi _SFR_IO_ADDR(EECR), EEWE - out _SFR_IO_ADDR(SREG), __tmp_reg__ - sbrs rTI0, 0 ; if flag is cleared it means that - ret ; we write both bytes - - subi addr_lo, lo8(-1) ; prepare to writie MSB - sbci addr_hi, hi8(-1) - mov val_lo, val_hi - clr rTI0 ; clear flag to indicate that - rjmp eeprom_write_word_start ; the second (MSB) byte will be written - -#undef val_hi -#undef val_lo -#endif /* L_eeprom_write_word */ - #undef addr_hi #undef addr_lo -#define buf_hi rP0 -#define buf_lo rP1 -#define addr_hi rP2 -#define addr_lo rP3 -#define n_hi rP4 -#define n_lo rP5 #ifdef L_eeprom_read_block -/* read a block of bytes from EEPROM */ -/* void eeprom_read_block(void *buf, const void *addr, size_t n); */ -/* buf = r25:r24, addr = r23:r22, n = r21:r20 */ - - .global _U(eeprom_read_block) - -_U(eeprom_read_block): - cp n_lo, __zero_reg__ - cpc n_hi, __zero_reg__ - breq eeprom_read_block_done - LOAD_X(buf_lo, buf_hi) -eeprom_read_block_busy: - sbic _SFR_IO_ADDR(EECR), EEWE - rjmp eeprom_read_block_busy /* make sure EEPROM is ready */ -eeprom_read_block_loop: -#ifdef EEARH - out _SFR_IO_ADDR(EEARH), addr_hi -#endif - out _SFR_IO_ADDR(EEARL), addr_lo - sbi _SFR_IO_ADDR(EECR), EERE - subi addr_lo, lo8(-1) - sbci addr_hi, hi8(-1) - in __tmp_reg__, _SFR_IO_ADDR(EEDR) - st X+, __tmp_reg__ - subi n_lo, lo8(1) - sbci n_hi, hi8(1) - brne eeprom_read_block_loop -eeprom_read_block_done: +/* read a block of n (maximum 256) bytes from EEPROM + ram_buffer = r30:r31, eeprom_addr = r26:r27, n = __zero_reg__ + an initial value of 0 in __zero_reg__ correspond to a value of n == 256. */ + + .global _EELABEL(eeprom_read_block) + .global _EELABEL(eeprom_read_byte) + +_EELABEL(eeprom_read_block): + XCALL _EELABEL(eeprom_read_byte) + st z+,__tmp_reg__ + dec __zero_reg__ + brne _EELABEL(eeprom_read_block) ret #endif /* L_eeprom_read_block */ #ifdef L_eeprom_write_block -/* write a block of bytes to EEPROM */ -/* void eeprom_write_block (const void *buf, void *addr, size_t n); */ -/* buf = r25:r24, addr = r23:r22, n = r21:r20 */ - - .global _U(eeprom_write_block) - -_U(eeprom_write_block): - cp n_lo, __zero_reg__ ; check if really there is something to write - cpc n_hi, __zero_reg__ - breq eeprom_write_block_done - LOAD_X(buf_lo, buf_hi) - in buf_lo, _SFR_IO_ADDR(SREG) ; reuse buf_lo as the SREG temporary storage -eeprom_write_block_busy: - sbic _SFR_IO_ADDR(EECR), EEWE - rjmp eeprom_write_block_busy ; make sure EEPROM is ready -#ifdef EEARH - out _SFR_IO_ADDR(EEARH), addr_hi -#endif - out _SFR_IO_ADDR(EEARL), addr_lo - ld __tmp_reg__, X+ - out _SFR_IO_ADDR(EEDR), __tmp_reg__ - cli ; no ints between setting EEMWE and EEWE - sbi _SFR_IO_ADDR(EECR), EEMWE - sbi _SFR_IO_ADDR(EECR), EEWE - out _SFR_IO_ADDR(SREG), buf_lo - subi addr_lo, lo8(-1) - sbci addr_hi, hi8(-1) - subi n_lo, lo8(1) - sbci n_hi, hi8(1) - brne eeprom_write_block_busy -eeprom_write_block_done: +/* Write a block of n (maximum 256) bytes to EEPROM + ram_pointer = r30:r31, eeprom_addr = r26:r27, n = __zero_reg__ + an initial value of 0 in __zero_reg__ correspond to a value of n == 256. */ + + .global _EELABEL(eeprom_write_block) + .global _EELABEL(eeprom_write_byte) + +_EELABEL(eeprom_write_block): + ld __tmp_reg__,z+ + XCALL _EELABEL(eeprom_write_byte) + dec __zero_reg__ + brne _EELABEL(eeprom_write_block) ret #endif /* L_eeprom_write_block */ .end