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 */