Index: include/avr/eeprom.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/eeprom.h,v retrieving revision 1.12 diff -u -r1.12 eeprom.h --- include/avr/eeprom.h 13 Jan 2005 10:56:10 -0000 1.12 +++ include/avr/eeprom.h 10 Jul 2005 18:27:14 -0000 @@ -35,7 +35,11 @@ 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_ @@ -45,7 +49,40 @@ #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 @@ -63,34 +100,56 @@ 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 (void *pointer_eeprom, + const 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. */ @@ -106,45 +165,163 @@ #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 (void *pointer_eeprom, + const 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 + { + /* 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. */ - -extern void eeprom_write_block (const void *buf, void *addr, size_t n); + Write a block of \c size bytes to EEPROM address \c pointer_eeprom from + \c pointer_ram. */ -#ifdef __cplusplus +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 + { + 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" ); + } } -#endif /address@hidden/ @@ -154,13 +331,13 @@ /** \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)) Index: include/avr/iocan128.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/iocan128.h,v retrieving revision 1.12 diff -u -r1.12 iocan128.h --- include/avr/iocan128.h 9 Jul 2005 14:01:11 -0000 1.12 +++ include/avr/iocan128.h 10 Jul 2005 18:27:17 -0000 @@ -124,6 +124,14 @@ #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) Index: include/avr/iom165.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/iom165.h,v retrieving revision 1.4 diff -u -r1.4 iom165.h --- include/avr/iom165.h 9 Jul 2005 14:01:11 -0000 1.4 +++ include/avr/iom165.h 10 Jul 2005 18:27:18 -0000 @@ -120,6 +120,14 @@ #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 Index: include/avr/iom169.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/iom169.h,v retrieving revision 1.21 diff -u -r1.21 iom169.h --- include/avr/iom169.h 9 Jul 2005 14:01:11 -0000 1.21 +++ include/avr/iom169.h 10 Jul 2005 18:27:19 -0000 @@ -115,6 +115,14 @@ #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) Index: include/avr/iom325.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/iom325.h,v retrieving revision 1.5 diff -u -r1.5 iom325.h --- include/avr/iom325.h 9 Jul 2005 14:01:11 -0000 1.5 +++ include/avr/iom325.h 10 Jul 2005 18:27:20 -0000 @@ -119,6 +119,15 @@ #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 Index: include/avr/iom3250.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/iom3250.h,v retrieving revision 1.5 diff -u -r1.5 iom3250.h --- include/avr/iom3250.h 9 Jul 2005 14:01:11 -0000 1.5 +++ include/avr/iom3250.h 10 Jul 2005 18:27:21 -0000 @@ -123,6 +123,14 @@ #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 Index: include/avr/iom645.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/iom645.h,v retrieving revision 1.5 diff -u -r1.5 iom645.h --- include/avr/iom645.h 9 Jul 2005 14:01:11 -0000 1.5 +++ include/avr/iom645.h 10 Jul 2005 18:27:22 -0000 @@ -119,6 +119,14 @@ #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 Index: include/avr/iom6450.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/iom6450.h,v retrieving revision 1.5 diff -u -r1.5 iom6450.h --- include/avr/iom6450.h 9 Jul 2005 14:01:11 -0000 1.5 +++ include/avr/iom6450.h 10 Jul 2005 18:27:22 -0000 @@ -123,6 +123,14 @@ #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 Index: include/avr/iomx8.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/iomx8.h,v retrieving revision 1.8 diff -u -r1.8 iomx8.h --- include/avr/iomx8.h 9 Jul 2005 14:01:11 -0000 1.8 +++ include/avr/iomx8.h 10 Jul 2005 18:27:23 -0000 @@ -208,6 +208,14 @@ 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 */ Index: libc/misc/Makefile.am =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/libc/misc/Makefile.am,v retrieving revision 1.2 diff -u -r1.2 Makefile.am --- libc/misc/Makefile.am 17 Jul 2003 19:52:23 -0000 1.2 +++ libc/misc/Makefile.am 10 Jul 2005 18:27:23 -0000 @@ -30,13 +30,13 @@ 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 \ @@ -48,6 +48,12 @@ 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 @@ -58,3 +64,8 @@ $(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 -u -r1.3 eeprom.S --- libc/misc/eeprom.S 17 Jul 2003 19:52:23 -0000 1.3 +++ libc/misc/eeprom.S 10 Jul 2005 18:27:23 -0000 @@ -36,6 +36,53 @@ #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... */ @@ -43,78 +90,52 @@ #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"? */ + ld __tmp_reg__,X+ /* 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 + ld __tmp_reg__,X+ /* Increment x register */ in __tmp_reg__, _SFR_IO_ADDR(SREG) cli ; /* no ints between setting EEMWE and EEWE */ sbi _SFR_IO_ADDR(EECR), EEMWE @@ -124,118 +145,39 @@ #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 */