summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/avr/avr/eeprom.h
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2009-08-06 14:52:07 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2009-08-06 14:52:07 +0000
commit04a62dce21e861c7ad9c989d50d7bc662b5405c6 (patch)
tree7d7163d025bd2aa17802e3dc2c0c3c5de2ae56df /cpukit/score/cpu/avr/avr/eeprom.h
parent2009-08-06 Chris Johns <chrisj@rtems.org> (diff)
downloadrtems-04a62dce21e861c7ad9c989d50d7bc662b5405c6.tar.bz2
2009-08-05 Josh Switnicki <josh.switnicki@utoronto.ca>
* Makefile.am: added AVR specific Header files to score/cpu/avr/avr. These are from avr-libc 1.6 and assumed to exist by AVR applications. * preinstall.am: Regenerated.
Diffstat (limited to 'cpukit/score/cpu/avr/avr/eeprom.h')
-rw-r--r--cpukit/score/cpu/avr/avr/eeprom.h423
1 files changed, 423 insertions, 0 deletions
diff --git a/cpukit/score/cpu/avr/avr/eeprom.h b/cpukit/score/cpu/avr/avr/eeprom.h
new file mode 100644
index 0000000000..3247cb0a3c
--- /dev/null
+++ b/cpukit/score/cpu/avr/avr/eeprom.h
@@ -0,0 +1,423 @@
+/* Copyright (c) 2002, 2003, 2004, 2007 Marek Michalkiewicz
+ Copyright (c) 2005, 2006 Bjoern Haase
+ Copyright (c) 2008 Atmel Corporation
+ Copyright (c) 2008 Wouter van Gulik
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ 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. */
+
+/* $Id$ */
+
+#ifndef _AVR_EEPROM_H_
+#define _AVR_EEPROM_H_ 1
+
+#include <avr/io.h>
+#include <stddef.h> /* size_t */
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __ATTR_PURE__
+# ifdef __DOXYGEN__
+# define __ATTR_PURE__
+# else
+# define __ATTR_PURE__ __attribute__((__pure__))
+# endif
+#endif
+
+#if (! (defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)) )
+uint16_t __eerd_word (const uint16_t *, uint8_t (*)(const uint8_t *))
+ __ATTR_PURE__;
+uint32_t __eerd_dword (const uint32_t *, uint8_t (*)(const uint8_t *))
+ __ATTR_PURE__;
+void __eerd_block (void *, const void *, size_t, uint8_t (*)(const uint8_t *));
+
+void __eewr_word (uint16_t *, uint16_t, void (*)(uint8_t *, uint8_t));
+void __eewr_dword (uint32_t *, uint32_t, void (*)(uint8_t *, uint8_t));
+void __eewr_block (void *, const void *, size_t, void (*)(uint8_t *, uint8_t));
+#endif /* (! (defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)) ) */
+
+#if !E2END && !defined(__DOXYGEN__)
+# ifndef __COMPILING_AVR_LIBC__
+# warning "Device does not have EEPROM available."
+# endif
+ /* Omit below for chips without EEPROM. */
+
+#else
+
+/** \defgroup avr_eeprom <avr/eeprom.h>: EEPROM handling
+ \code #include <avr/eeprom.h> \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. But this functions are not wait until
+ SELFPRGEN in SPMCSR becomes zero. Do this manually, if your
+ softwate contains the Flash burning.
+
+ \note As these functions modify IO registers, they are known to be
+ non-reentrant. If any of these functions are used from both,
+ standard and interrupt context, the applications must ensure
+ proper protection (e.g. by disabling interrupts before accessing
+ them).
+
+ \note All write functions force erase_and_write programming mode.
+ */
+
+/** \def EEMEM
+ \ingroup avr_eeprom
+ Attribute expression causing a variable to be allocated within the
+ .eeprom section. */
+#define EEMEM __attribute__((section(".eeprom")))
+
+
+/* Register definitions */
+
+/* Check for aliases. */
+#if !defined(EEWE) && defined(EEPE)
+# define EEWE EEPE
+#endif
+
+#if !defined(EEMWE) && defined(EEMPE)
+# define EEMWE EEMPE
+#endif
+
+#if !defined(EECR) && defined(DEECR)
+/* AT86RF401 */
+# define EECR DEECR
+# define EEAR DEEAR
+# define EEARL DEEAR
+# define EEDR DEEDR
+# define EERE EER
+# define EEWE EEL
+# define EEMWE EEU
+#endif
+
+
+#if !defined(EECR) || !defined(EEDR) || !defined(EEARL)
+
+# if !defined(__EEPROM_REG_LOCATIONS__) \
+ && !defined(EEPROM_REG_LOCATIONS_OVERRIDE)
+ /* 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.
+ */
+# error "Unknown EEPROM register(s) location."
+# endif
+
+/* If needed, 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
+# endif
+
+# define CONCAT1(a, b) CONCAT2(a, b)
+# define CONCAT2(a, b) a ## b
+# define HEXNR CONCAT1(0x, __EEPROM_REG_LOCATIONS__)
+
+# undef EECR
+# define EECR _SFR_IO8((HEXNR >> 16) & 0xFF)
+
+# undef EEDR
+# define EEDR _SFR_IO8((HEXNR >> 8) & 0xFF)
+
+# undef EEAR
+# define EEAR _SFR_IO8(HEXNR & 0xFF)
+
+# undef EEARH
+
+# undef EEARL
+# define EEARL EEAR
+
+#endif
+
+
+/** \def eeprom_is_ready
+ \ingroup avr_eeprom
+ \returns 1 if EEPROM is ready for a new read/write operation, 0 if not.
+ */
+#if defined(__DOXYGEN__)
+# define eeprom_is_ready()
+#elif defined(DEECR)
+# define eeprom_is_ready() bit_is_clear(DEECR, BSY)
+#else
+# define eeprom_is_ready() bit_is_clear(EECR, EEWE)
+#endif
+
+
+/** \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())
+
+
+/** \ingroup avr_eeprom
+ Read one byte from EEPROM address \a __p.
+ */
+__ATTR_PURE__ static __inline__ uint8_t eeprom_read_byte (const uint8_t *__p)
+{
+ do {} while (!eeprom_is_ready ());
+#if E2END <= 0xFF
+ EEARL = (size_t)__p;
+#else
+ EEAR = (size_t)__p;
+#endif
+ /* Use inline assembly below as some AVRs have problems with accessing
+ EECR with STS instructions. For example, see errata for ATmega64.
+ The code below also assumes that EECR and EEDR are in the I/O space.
+ */
+ uint8_t __result;
+ __asm__ __volatile__
+ (
+ "/* START EEPROM READ CRITICAL SECTION */ \n\t"
+ "sbi %1, %2 \n\t"
+ "in %0, %3 \n\t"
+ "/* END EEPROM READ CRITICAL SECTION */ \n\t"
+ : "=r" (__result)
+ : "i" (_SFR_IO_ADDR(EECR)),
+ "i" (EERE),
+ "i" (_SFR_IO_ADDR(EEDR))
+ );
+ return __result;
+}
+
+/** \ingroup avr_eeprom
+ Read one 16-bit word (little endian) from EEPROM address \a __p.
+ */
+__ATTR_PURE__ static __inline__ uint16_t eeprom_read_word (const uint16_t *__p)
+{
+#if (! (defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)) )
+ return __eerd_word (__p, eeprom_read_byte);
+#else
+ /* If ATmega256x device, do not call function. */
+ union
+ {
+ uint16_t word;
+ struct
+ {
+ uint8_t lo;
+ uint8_t hi;
+ } byte;
+ } x;
+
+ x.byte.lo = eeprom_read_byte ((const uint8_t *)__p);
+ x.byte.hi = eeprom_read_byte ((const uint8_t *)__p + 1);
+ return x.word;
+#endif
+}
+
+/** \ingroup avr_eeprom
+ Read one 32-bit double word (little endian) from EEPROM address \a __p.
+ */
+__ATTR_PURE__ static __inline__
+uint32_t eeprom_read_dword (const uint32_t *__p)
+{
+#if (! (defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)) )
+ return __eerd_dword (__p, eeprom_read_byte);
+#else
+ /* If ATmega256x device, do not call function. */
+ union
+ {
+ uint32_t dword;
+ struct
+ {
+ uint8_t byte0;
+ uint8_t byte1;
+ uint8_t byte2;
+ uint8_t byte3;
+ } byte;
+ } x;
+
+ x.byte.byte0 = eeprom_read_byte ((const uint8_t *)__p);
+ x.byte.byte1 = eeprom_read_byte ((const uint8_t *)__p + 1);
+ x.byte.byte2 = eeprom_read_byte ((const uint8_t *)__p + 2);
+ x.byte.byte3 = eeprom_read_byte ((const uint8_t *)__p + 3);
+ return x.dword;
+#endif
+}
+
+/** \ingroup avr_eeprom
+ Read a block of \a __n bytes from EEPROM address \a __src to SRAM
+ \a __dst.
+ */
+static __inline__ void
+eeprom_read_block (void *__dst, const void *__src, size_t __n)
+{
+#if (! (defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)) )
+ __eerd_block (__dst, __src, __n, eeprom_read_byte);
+#else
+ /* If ATmega256x device, do not call function. */
+ while (__n--)
+ {
+ *(char *)__dst++ = eeprom_read_byte(__src++);
+ }
+#endif
+}
+
+/** \ingroup avr_eeprom
+ Write a byte \a __value to EEPROM address \a __p.
+ */
+static __inline__ void eeprom_write_byte (uint8_t *__p, uint8_t __value)
+{
+ do {} while (!eeprom_is_ready ());
+
+#if defined(EEPM0) && defined(EEPM1)
+ EECR = 0; /* Set programming mode: erase and write. */
+#elif defined(EEPM0) || defined(EEPM1)
+# warning "Unknown EECR register, eeprom_write_byte() has become outdated."
+#endif
+
+#if E2END <= 0xFF
+ EEARL = (size_t)__p;
+#else
+ EEAR = (size_t)__p;
+#endif
+ EEDR = __value;
+
+ __asm__ __volatile__ (
+ "/* START EEPROM WRITE CRITICAL SECTION */\n\t"
+ "in r0, %[__sreg] \n\t"
+ "cli \n\t"
+ "sbi %[__eecr], %[__eemwe] \n\t"
+ "sbi %[__eecr], %[__eewe] \n\t"
+ "out %[__sreg], r0 \n\t"
+ "/* END EEPROM WRITE CRITICAL SECTION */"
+ :
+ : [__eecr] "i" (_SFR_IO_ADDR(EECR)),
+ [__sreg] "i" (_SFR_IO_ADDR(SREG)),
+ [__eemwe] "i" (EEMWE),
+ [__eewe] "i" (EEWE)
+ : "r0"
+ );
+}
+
+/** \ingroup avr_eeprom
+ Write a word \a __value to EEPROM address \a __p.
+ */
+static __inline__ void eeprom_write_word (uint16_t *__p, uint16_t __value)
+{
+#if (! (defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)) )
+ __eewr_word (__p, __value, eeprom_write_byte);
+#else
+ /* If ATmega256x device, do not call function. */
+ union
+ {
+ uint16_t word;
+ struct
+ {
+ uint8_t lo;
+ uint8_t hi;
+ } byte;
+ } x;
+
+ x.word = __value;
+ eeprom_write_byte ((uint8_t *)__p, x.byte.lo);
+ eeprom_write_byte ((uint8_t *)__p + 1, x.byte.hi);
+#endif
+}
+
+/** \ingroup avr_eeprom
+ Write a 32-bit double word \a __value to EEPROM address \a __p.
+ */
+static __inline__ void eeprom_write_dword (uint32_t *__p, uint32_t __value)
+{
+#if (! (defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)) )
+ __eewr_dword (__p, __value, eeprom_write_byte);
+#else
+ /* If ATmega256x device, do not call function. */
+ union
+ {
+ uint32_t dword;
+ struct
+ {
+ uint8_t byte0;
+ uint8_t byte1;
+ uint8_t byte2;
+ uint8_t byte3;
+ } byte;
+ } x;
+
+ x.dword = __value;
+ eeprom_write_byte ((uint8_t *)__p, x.byte.byte0);
+ eeprom_write_byte ((uint8_t *)__p + 1, x.byte.byte1);
+ eeprom_write_byte ((uint8_t *)__p + 2, x.byte.byte2);
+ eeprom_write_byte ((uint8_t *)__p + 3, x.byte.byte3);
+#endif
+}
+
+/** \ingroup avr_eeprom
+ Write a block of \a __n bytes to EEPROM address \a __dst from \a __src.
+ \note The argument order is mismatch with common functions like strcpy().
+ */
+static __inline__ void
+eeprom_write_block (const void *__src, void *__dst, size_t __n)
+{
+#if (! (defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)) )
+ __eewr_block (__dst, __src, __n, eeprom_write_byte);
+#else
+ /* If ATmega256x device, do not call function. */
+ while (__n--)
+ eeprom_write_byte (__dst++, *(uint8_t *)__src++);
+#endif
+}
+
+/** \name IAR C compatibility defines */
+/*@{*/
+
+/** \def _EEPUT
+ \ingroup avr_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. Compatibility define for IAR C. */
+#define _EEGET(var, addr) (var) = eeprom_read_byte ((const uint8_t *)(addr))
+
+/*@}*/
+
+#endif /* E2END || defined(__DOXYGEN__) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_AVR_EEPROM_H */