/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See the file COPYING * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Copyright (C) 2010 Frank van Maarseveen */ #ifndef _EEPROM_H #define _EEPROM_H #include #include "types.h" #include "hardware.h" /* * A slot is the eeprom address of a 2 byte word. Any slot from EE_SLOT_BASE * up to but excluding EE_SLOT_END can asynchronously be updated by this * module, providing backing store for variables in RAM. Any other slot can * be updated outside interrupt context only and it may take significant time * if eeprom is currently being programmed. * * The file hardware.h should define EE_SLOT_BASE and EE_SLOT_END. Example: * * #define EE_SLOT_BASE (0x0010 >> 1) * #define EE_TEMP_MIN (0 + EE_SLOT_BASE) * #define EE_TEMP_MAX (1 + EE_SLOT_BASE) * #define EE_SLOT_END (2 + EE_SLOT_BASE) * * Example code using this: * * uint16_t temp_min, temp_max; * ee_init(0, 0); * ee_init16(EE_TEMP_MIN, &temp_min, 0xffff); * ee_init16(EE_TEMP_MAX, &temp_max, 0x0000); * * To update (in- and outside interrupt context): * * ee_min16(EE_TEMP_MIN, &temp_min, value); * ee_max16(EE_TEMP_MAX, &temp_max, value); * * A timer should flush data to eeprom at regular interval: * * ee_sync(); * * This only starts the eeprom writing. To make sure it is finished call either * ee_wait() or ee_cleanup(). Larger variables are referred to by their * starting slot number. Slot EE_SLOT_END - 1 can be used for an object up to * 63 bytes large. * * This module needs to be able to detect an erased eeprom or eeprom contents * version mismatch: EE_SLOT_INTERNAL can be defined to a slot (default zero) * for maintaining this internal state. This does not need to be inside the * [EE_SLOT_BASE..EE_SLOT_END> range. */ #ifndef EE_SLOT_INTERNAL # define EE_SLOT_INTERNAL 0 # if EE_SLOT_INTERNAL >= EE_SLOT_BASE && EE_SLOT_INTERNAL < EE_SLOT_END # error default for EE_SLOT_INTERNAL overlaps with user defined slot range, please define manually. # endif #endif /* * Notes: * - All ee_init*() calls must be first. Only ee_read() can be called safely * between ee_init() and ee_init16()/ee_init32(). * - slot must be EE_SLOT_BASE..EE_SLOT_END - 1 * - len must be 0..63. * - min/max functions, ee_sync() and ee_write()/ee_write_async() can be * called from interrupt context. * - When not in interrupt context it is allowed to call ee_read() and * ee_write() with arbitrary (out of range) slot values. * - ee_read() is callable from interrupt context but may take milliseconds * to complete when eeprom is currently being programmed. */ void ee_init(uint8_t version, uint8_t reset_slot_end); void ee_read(uint8_t slot, void *buf, uint8_t len); void ee_write_async(uint8_t slot, void *buf, uint8_t len); void ee_write_generic(uint8_t slot, void *buf, uint8_t len); void ee_init16(uint8_t slot, uint16_t *ptr, uint16_t value); void ee_min16(uint8_t slot, uint16_t *ptr, uint16_t value); void ee_max16(uint8_t slot, uint16_t *ptr, uint16_t value); void ee_set16(uint8_t slot, uint16_t *ptr, uint16_t value); void ee_init32(uint8_t slot, uint32_t *ptr, uint32_t value); void ee_min32(uint8_t slot, uint32_t *ptr, uint32_t value); void ee_max32(uint8_t slot, uint32_t *ptr, uint32_t value); void ee_set32(uint8_t slot, uint32_t *ptr, uint32_t value); void ee_sync(void); bool_t ee_busy(void); void ee_wait(void); void ee_cleanup(void); __attribute__((always_inline)) static inline void ee_write(uint8_t slot, void *buf, uint8_t len) { if (slot >= EE_SLOT_BASE && slot < EE_SLOT_END) ee_write_async(slot, buf, len); else ee_write_generic(slot, buf, len); } #endif