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

Reply via email to