diff --git a/build/build.xml b/build/build.xml index 3059b7739..3294d204a 100644 --- a/build/build.xml +++ b/build/build.xml @@ -406,6 +406,10 @@ + + + + diff --git a/build/windows/eeprom.h b/build/windows/eeprom.h new file mode 100644 index 000000000..61c38a727 --- /dev/null +++ b/build/windows/eeprom.h @@ -0,0 +1,442 @@ +/* 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: eeprom.h,v 1.21.2.6 2008/08/19 22:10:39 arcanum Exp $ */ + +#ifndef _AVR_EEPROM_H_ +#define _AVR_EEPROM_H_ 1 + +#include +#include /* size_t */ +#include + +#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 : 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. 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 = (uint8_t)__p; +#else + EEAR = (uint16_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. */ + char *_myDstPtr; + char *_mySrcPtr; + + _myDstPtr = (char *)__dst; + _mySrcPtr = (char *)__src; + while (__n--) + { + //* Jul 6, 2010 modifed by Mark Sproul to work with the 2560 + // *(char *)__dst++ = eeprom_read_byte((const uint8_t *)__src++); + *_myDstPtr = eeprom_read_byte((const uint8_t *)_mySrcPtr); + _myDstPtr++; + _mySrcPtr++; + } +#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 = (unsigned)__p; +#else + EEAR = (unsigned)__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. */ + uint8_t *_myDstPtr; + uint8_t *_mySrcPtr; + + //* Jul 6, 2010 modifed by Mark Sproul to work with the 2560 + _myDstPtr = (uint8_t *)__dst; + _mySrcPtr = (uint8_t *)__src; + + while (__n--) + { + // eeprom_write_byte((uint8_t *)__dst++, *(uint8_t *)__src++); + eeprom_write_byte(_myDstPtr++, *_mySrcPtr++); + } +#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 */