Hi all.
I like the rewrite. It looks good. My only concern is not
only code size. There is a second question: this functions
are not a normal C functions. That is:
. No argument type control at compile time. For expamle,
the expressions like
eeprom_write_block ("Apple", s, sizeof("Apple"));
eeprom_write_dword (3.14159, 0);
do not type any warnings.
. It is impossible to get address of eeprom function
to inderect call.
. Avr-gcc can not to optimize the EEPROM reading, like it
can do this in case of SRAM.
Summarizes the Eric's "eeprom.h" and all ideas from above
(Wouter, Shaun, Rick) I have prepare two projects.
Project 1.
It is a very simple: use an inderect calls (not indirect
registers). It is eliminates big space expense and notes
above: eeprom functions are pure functions. It is needed
to add only 6 very short functions into Avr-libc. At this
moment this project is ready for test. I can to commite
at this week-end.
Project 2.
Use a set of high quality asm functions. This is not only
space effective, also it is fast. Now the set of funtions is
ready for test. Some efforts are needed to include into
Avr-libc: I am not happy to do this manualy.
In attach the "eeprom.h" of project 1.
Opinions?
Thanks,
Dmitry.
/* 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>
/** \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 existence of EEPROM peripheral. */
#if E2END == 0
# error "Device does not have EEPROM available!"
#endif
/* 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)
# 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
/* 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
#ifndef __ATTR_PURE__
# ifdef __DOXYGEN__
# define __ATTR_PURE__
# else
# define __ATTR_PURE__ __attribute__((__pure__))
# endif
#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
__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
EECR |= (1 << EERE);
return EEDR;
}
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 *));
__ATTR_PURE__ static inline uint16_t eeprom_read_word (const uint16_t *__p)
{
return __eerd_word (__p, eeprom_read_byte);
}
__ATTR_PURE__ static inline uint32_t eeprom_read_dword (const uint32_t *__p)
{
return __eerd_dword (__p, eeprom_read_byte);
}
static inline void
eeprom_read_block (void *__dst, const void *__src, size_t __n)
{
__eerd_block (__dst, __src, __n, eeprom_read_byte);
}
inline static void eeprom_write_byte (uint8_t *__p, uint8_t __value)
{
do {} while (!eeprom_is_ready ());
#if E2END <= 0xFF
EEARL = (uint8_t)__p;
#else
EEAR = (uint16_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"
);
}
void __eewr_word (uint16_t *, uint16_t, void (*)(uint8_t *, uint8_t));
void __eewr_dword (uint32_t *, uint16_t, void (*)(uint8_t *, uint8_t));
void __eewr_block (void *, const void *, size_t, void (*)(uint8_t *, uint8_t));
static inline void eeprom_write_word (uint16_t *__p, uint16_t __value)
{
__eewr_word (__p, __value, eeprom_write_byte);
}
static inline void eeprom_write_dword (uint32_t *__p, uint32_t __value)
{
__eewr_dword (__p, __value, eeprom_write_byte);
}
static inline void
eeprom_write_block (void *__dst, const void *__src, size_t __n)
{
__eewr_block (__dst, __src, __n, eeprom_write_byte);
}
#endif /* !_AVR_EEPROM_H */
_______________________________________________
AVR-libc-dev mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/avr-libc-dev