Committer:
Sergunb
Date:
Mon Sep 04 12:04:13 2017 +0000
Revision:
0:8f0d870509fe
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sergunb 0:8f0d870509fe 1 // This file has been prepared for Doxygen automatic documentation generation.
Sergunb 0:8f0d870509fe 2 /*! \file ********************************************************************
Sergunb 0:8f0d870509fe 3 *
Sergunb 0:8f0d870509fe 4 * Atmel Corporation
Sergunb 0:8f0d870509fe 5 *
Sergunb 0:8f0d870509fe 6 * \li File: eeprom.c
Sergunb 0:8f0d870509fe 7 * \li Compiler: IAR EWAAVR 3.10c
Sergunb 0:8f0d870509fe 8 * \li Support mail: avr@atmel.com
Sergunb 0:8f0d870509fe 9 *
Sergunb 0:8f0d870509fe 10 * \li Supported devices: All devices with split EEPROM erase/write
Sergunb 0:8f0d870509fe 11 * capabilities can be used.
Sergunb 0:8f0d870509fe 12 * The example is written for ATmega48.
Sergunb 0:8f0d870509fe 13 *
Sergunb 0:8f0d870509fe 14 * \li AppNote: AVR103 - Using the EEPROM Programming Modes.
Sergunb 0:8f0d870509fe 15 *
Sergunb 0:8f0d870509fe 16 * \li Description: Example on how to use the split EEPROM erase/write
Sergunb 0:8f0d870509fe 17 * capabilities in e.g. ATmega48. All EEPROM
Sergunb 0:8f0d870509fe 18 * programming modes are tested, i.e. Erase+Write,
Sergunb 0:8f0d870509fe 19 * Erase-only and Write-only.
Sergunb 0:8f0d870509fe 20 *
Sergunb 0:8f0d870509fe 21 * $Revision: 1.6 $
Sergunb 0:8f0d870509fe 22 * $Date: Friday, February 11, 2005 07:16:44 UTC $
Sergunb 0:8f0d870509fe 23 ****************************************************************************/
Sergunb 0:8f0d870509fe 24 #include "grbl.h"
Sergunb 0:8f0d870509fe 25 #ifdef AVRTARGET
Sergunb 0:8f0d870509fe 26 #include <avr/io.h>
Sergunb 0:8f0d870509fe 27 #include <avr/interrupt.h>
Sergunb 0:8f0d870509fe 28 /* These EEPROM bits have different names on different devices. */
Sergunb 0:8f0d870509fe 29 #ifndef EEPE
Sergunb 0:8f0d870509fe 30 #define EEPE EEWE //!< EEPROM program/write enable.
Sergunb 0:8f0d870509fe 31 #define EEMPE EEMWE //!< EEPROM master program/write enable.
Sergunb 0:8f0d870509fe 32 #endif
Sergunb 0:8f0d870509fe 33
Sergunb 0:8f0d870509fe 34 /* These two are unfortunately not defined in the device include files. */
Sergunb 0:8f0d870509fe 35 #define EEPM1 5 //!< EEPROM Programming Mode Bit 1.
Sergunb 0:8f0d870509fe 36 #define EEPM0 4 //!< EEPROM Programming Mode Bit 0.
Sergunb 0:8f0d870509fe 37
Sergunb 0:8f0d870509fe 38 /* Define to reduce code size. */
Sergunb 0:8f0d870509fe 39 #define EEPROM_IGNORE_SELFPROG //!< Remove SPM flag polling.
Sergunb 0:8f0d870509fe 40 #endif
Sergunb 0:8f0d870509fe 41 #ifdef WIN32
Sergunb 0:8f0d870509fe 42 #include <stdio.h>
Sergunb 0:8f0d870509fe 43 #include <string.h>
Sergunb 0:8f0d870509fe 44 #endif
Sergunb 0:8f0d870509fe 45 #ifdef STM32F103C8
Sergunb 0:8f0d870509fe 46 #include <string.h>
Sergunb 0:8f0d870509fe 47 #include "stm32eeprom.h"
Sergunb 0:8f0d870509fe 48 #include "settings.h"
Sergunb 0:8f0d870509fe 49 #endif
Sergunb 0:8f0d870509fe 50 #if defined(WIN32) || defined (STM32F103C8)
Sergunb 0:8f0d870509fe 51 unsigned char EE_Buffer[0x400];
Sergunb 0:8f0d870509fe 52 #endif
Sergunb 0:8f0d870509fe 53 #if defined(WIN32)
Sergunb 0:8f0d870509fe 54 #ifndef NOEEPROMSUPPORT
Sergunb 0:8f0d870509fe 55 void eeprom_flush()
Sergunb 0:8f0d870509fe 56 {
Sergunb 0:8f0d870509fe 57 FILE *out = fopen("eeprom.bin", "wb");
Sergunb 0:8f0d870509fe 58 fwrite(EE_Buffer, 1, 0x400, out);
Sergunb 0:8f0d870509fe 59 fclose(out);
Sergunb 0:8f0d870509fe 60 }
Sergunb 0:8f0d870509fe 61 #endif
Sergunb 0:8f0d870509fe 62 void eeprom_init()
Sergunb 0:8f0d870509fe 63 {
Sergunb 0:8f0d870509fe 64 #ifndef NOEEPROMSUPPORT
Sergunb 0:8f0d870509fe 65 FILE *in = fopen("eeprom.bin", "rb");
Sergunb 0:8f0d870509fe 66 if (in != NULL)
Sergunb 0:8f0d870509fe 67 {
Sergunb 0:8f0d870509fe 68 fread(EE_Buffer, 1, 0x400, in);
Sergunb 0:8f0d870509fe 69 fclose(in);
Sergunb 0:8f0d870509fe 70 }
Sergunb 0:8f0d870509fe 71 else
Sergunb 0:8f0d870509fe 72 {
Sergunb 0:8f0d870509fe 73 memset(EE_Buffer, 0xff, 0x400);
Sergunb 0:8f0d870509fe 74 }
Sergunb 0:8f0d870509fe 75 #else
Sergunb 0:8f0d870509fe 76 memset(EE_Buffer, 0x0, 0x400);
Sergunb 0:8f0d870509fe 77 #endif
Sergunb 0:8f0d870509fe 78 }
Sergunb 0:8f0d870509fe 79 #endif
Sergunb 0:8f0d870509fe 80
Sergunb 0:8f0d870509fe 81 #ifdef STM32F103C8
Sergunb 0:8f0d870509fe 82 #ifndef NOEEPROMSUPPORT
Sergunb 0:8f0d870509fe 83 void eeprom_flush()
Sergunb 0:8f0d870509fe 84 {
Sergunb 0:8f0d870509fe 85 uint32_t nAddress = EEPROM_START_ADDRESS;
Sergunb 0:8f0d870509fe 86 uint16_t *pBuffer = (uint16_t *)EE_Buffer;
Sergunb 0:8f0d870509fe 87 uint16_t nSize = PAGE_SIZE;
Sergunb 0:8f0d870509fe 88
Sergunb 0:8f0d870509fe 89 FLASH_Status FlashStatus = FLASH_COMPLETE;
Sergunb 0:8f0d870509fe 90
Sergunb 0:8f0d870509fe 91 /* Erase Page0 */
Sergunb 0:8f0d870509fe 92 FlashStatus = FLASH_ErasePage(EEPROM_START_ADDRESS);
Sergunb 0:8f0d870509fe 93
Sergunb 0:8f0d870509fe 94 /* If erase operation was failed, a Flash error code is returned */
Sergunb 0:8f0d870509fe 95 if (FlashStatus != FLASH_COMPLETE)
Sergunb 0:8f0d870509fe 96 {
Sergunb 0:8f0d870509fe 97 return;
Sergunb 0:8f0d870509fe 98 }
Sergunb 0:8f0d870509fe 99
Sergunb 0:8f0d870509fe 100 while (nSize > 0)
Sergunb 0:8f0d870509fe 101 {
Sergunb 0:8f0d870509fe 102 if (*pBuffer != 0xffff)
Sergunb 0:8f0d870509fe 103 {
Sergunb 0:8f0d870509fe 104 FLASH_ProgramHalfWord(nAddress, *pBuffer++);
Sergunb 0:8f0d870509fe 105 }
Sergunb 0:8f0d870509fe 106 else
Sergunb 0:8f0d870509fe 107 {
Sergunb 0:8f0d870509fe 108 pBuffer++;
Sergunb 0:8f0d870509fe 109 }
Sergunb 0:8f0d870509fe 110 if (*pBuffer != 0xffff)
Sergunb 0:8f0d870509fe 111 {
Sergunb 0:8f0d870509fe 112 FLASH_ProgramHalfWord(nAddress + 2, *pBuffer++);
Sergunb 0:8f0d870509fe 113 }
Sergunb 0:8f0d870509fe 114 else
Sergunb 0:8f0d870509fe 115 {
Sergunb 0:8f0d870509fe 116 pBuffer++;
Sergunb 0:8f0d870509fe 117 }
Sergunb 0:8f0d870509fe 118 nSize -= 4;
Sergunb 0:8f0d870509fe 119 nAddress += 4;
Sergunb 0:8f0d870509fe 120 }
Sergunb 0:8f0d870509fe 121 }
Sergunb 0:8f0d870509fe 122 void eeprom_init()
Sergunb 0:8f0d870509fe 123 {
Sergunb 0:8f0d870509fe 124 uint16_t VarIdx = 0;
Sergunb 0:8f0d870509fe 125 uint8_t *pTmp = EE_Buffer;
Sergunb 0:8f0d870509fe 126
Sergunb 0:8f0d870509fe 127 for (VarIdx = 0; VarIdx < PAGE_SIZE; VarIdx++)
Sergunb 0:8f0d870509fe 128 {
Sergunb 0:8f0d870509fe 129 *pTmp++ = (*(__IO uint8_t*)(EEPROM_START_ADDRESS + VarIdx));
Sergunb 0:8f0d870509fe 130 }
Sergunb 0:8f0d870509fe 131
Sergunb 0:8f0d870509fe 132 if (EE_Buffer[0] != SETTINGS_VERSION)
Sergunb 0:8f0d870509fe 133 {
Sergunb 0:8f0d870509fe 134 pTmp = EE_Buffer;
Sergunb 0:8f0d870509fe 135
Sergunb 0:8f0d870509fe 136 for (VarIdx = 0; VarIdx < PAGE_SIZE; VarIdx++)
Sergunb 0:8f0d870509fe 137 {
Sergunb 0:8f0d870509fe 138 *pTmp++ = 0xFF;
Sergunb 0:8f0d870509fe 139 }
Sergunb 0:8f0d870509fe 140 }
Sergunb 0:8f0d870509fe 141 }
Sergunb 0:8f0d870509fe 142 #endif
Sergunb 0:8f0d870509fe 143 #endif
Sergunb 0:8f0d870509fe 144
Sergunb 0:8f0d870509fe 145 /*! \brief Read byte from EEPROM.
Sergunb 0:8f0d870509fe 146 *
Sergunb 0:8f0d870509fe 147 * This function reads one byte from a given EEPROM address.
Sergunb 0:8f0d870509fe 148 *
Sergunb 0:8f0d870509fe 149 * \note The CPU is halted for 4 clock cycles during EEPROM read.
Sergunb 0:8f0d870509fe 150 *
Sergunb 0:8f0d870509fe 151 * \param addr EEPROM address to read from.
Sergunb 0:8f0d870509fe 152 * \return The byte read from the EEPROM address.
Sergunb 0:8f0d870509fe 153 */
Sergunb 0:8f0d870509fe 154 unsigned char eeprom_get_char( unsigned int addr )
Sergunb 0:8f0d870509fe 155 {
Sergunb 0:8f0d870509fe 156 #ifdef AVRTARGET
Sergunb 0:8f0d870509fe 157 do {} while( EECR & (1<<EEPE) ); // Wait for completion of previous write.
Sergunb 0:8f0d870509fe 158 EEAR = addr; // Set EEPROM address register.
Sergunb 0:8f0d870509fe 159 EECR = (1<<EERE); // Start EEPROM read operation.
Sergunb 0:8f0d870509fe 160 return EEDR; // Return the byte read from EEPROM.
Sergunb 0:8f0d870509fe 161 #endif
Sergunb 0:8f0d870509fe 162 #if defined(WIN32) || defined(STM32F103C8)
Sergunb 0:8f0d870509fe 163 return EE_Buffer[addr];
Sergunb 0:8f0d870509fe 164 #endif
Sergunb 0:8f0d870509fe 165 }
Sergunb 0:8f0d870509fe 166
Sergunb 0:8f0d870509fe 167 /*! \brief Write byte to EEPROM.
Sergunb 0:8f0d870509fe 168 *
Sergunb 0:8f0d870509fe 169 * This function writes one byte to a given EEPROM address.
Sergunb 0:8f0d870509fe 170 * The differences between the existing byte and the new value is used
Sergunb 0:8f0d870509fe 171 * to select the most efficient EEPROM programming mode.
Sergunb 0:8f0d870509fe 172 *
Sergunb 0:8f0d870509fe 173 * \note The CPU is halted for 2 clock cycles during EEPROM programming.
Sergunb 0:8f0d870509fe 174 *
Sergunb 0:8f0d870509fe 175 * \note When this function returns, the new EEPROM value is not available
Sergunb 0:8f0d870509fe 176 * until the EEPROM programming time has passed. The EEPE bit in EECR
Sergunb 0:8f0d870509fe 177 * should be polled to check whether the programming is finished.
Sergunb 0:8f0d870509fe 178 *
Sergunb 0:8f0d870509fe 179 * \note The EEPROM_GetChar() function checks the EEPE bit automatically.
Sergunb 0:8f0d870509fe 180 *
Sergunb 0:8f0d870509fe 181 * \param addr EEPROM address to write to.
Sergunb 0:8f0d870509fe 182 * \param new_value New EEPROM value.
Sergunb 0:8f0d870509fe 183 */
Sergunb 0:8f0d870509fe 184 void eeprom_put_char( unsigned int addr, unsigned char new_value )
Sergunb 0:8f0d870509fe 185 {
Sergunb 0:8f0d870509fe 186 #ifdef AVRTARGET
Sergunb 0:8f0d870509fe 187 char old_value; // Old EEPROM value.
Sergunb 0:8f0d870509fe 188 char diff_mask; // Difference mask, i.e. old value XOR new value.
Sergunb 0:8f0d870509fe 189
Sergunb 0:8f0d870509fe 190 cli(); // Ensure atomic operation for the write operation.
Sergunb 0:8f0d870509fe 191
Sergunb 0:8f0d870509fe 192 do {} while( EECR & (1<<EEPE) ); // Wait for completion of previous write.
Sergunb 0:8f0d870509fe 193 #ifndef EEPROM_IGNORE_SELFPROG
Sergunb 0:8f0d870509fe 194 do {} while( SPMCSR & (1<<SELFPRGEN) ); // Wait for completion of SPM.
Sergunb 0:8f0d870509fe 195 #endif
Sergunb 0:8f0d870509fe 196
Sergunb 0:8f0d870509fe 197 EEAR = addr; // Set EEPROM address register.
Sergunb 0:8f0d870509fe 198 EECR = (1<<EERE); // Start EEPROM read operation.
Sergunb 0:8f0d870509fe 199 old_value = EEDR; // Get old EEPROM value.
Sergunb 0:8f0d870509fe 200 diff_mask = old_value ^ new_value; // Get bit differences.
Sergunb 0:8f0d870509fe 201
Sergunb 0:8f0d870509fe 202 // Check if any bits are changed to '1' in the new value.
Sergunb 0:8f0d870509fe 203 if( diff_mask & new_value ) {
Sergunb 0:8f0d870509fe 204 // Now we know that _some_ bits need to be erased to '1'.
Sergunb 0:8f0d870509fe 205
Sergunb 0:8f0d870509fe 206 // Check if any bits in the new value are '0'.
Sergunb 0:8f0d870509fe 207 if( new_value != 0xff ) {
Sergunb 0:8f0d870509fe 208 // Now we know that some bits need to be programmed to '0' also.
Sergunb 0:8f0d870509fe 209
Sergunb 0:8f0d870509fe 210 EEDR = new_value; // Set EEPROM data register.
Sergunb 0:8f0d870509fe 211 EECR = (1<<EEMPE) | // Set Master Write Enable bit...
Sergunb 0:8f0d870509fe 212 (0<<EEPM1) | (0<<EEPM0); // ...and Erase+Write mode.
Sergunb 0:8f0d870509fe 213 EECR |= (1<<EEPE); // Start Erase+Write operation.
Sergunb 0:8f0d870509fe 214 } else {
Sergunb 0:8f0d870509fe 215 // Now we know that all bits should be erased.
Sergunb 0:8f0d870509fe 216
Sergunb 0:8f0d870509fe 217 EECR = (1<<EEMPE) | // Set Master Write Enable bit...
Sergunb 0:8f0d870509fe 218 (1<<EEPM0); // ...and Erase-only mode.
Sergunb 0:8f0d870509fe 219 EECR |= (1<<EEPE); // Start Erase-only operation.
Sergunb 0:8f0d870509fe 220 }
Sergunb 0:8f0d870509fe 221 } else {
Sergunb 0:8f0d870509fe 222 // Now we know that _no_ bits need to be erased to '1'.
Sergunb 0:8f0d870509fe 223
Sergunb 0:8f0d870509fe 224 // Check if any bits are changed from '1' in the old value.
Sergunb 0:8f0d870509fe 225 if( diff_mask ) {
Sergunb 0:8f0d870509fe 226 // Now we know that _some_ bits need to the programmed to '0'.
Sergunb 0:8f0d870509fe 227
Sergunb 0:8f0d870509fe 228 EEDR = new_value; // Set EEPROM data register.
Sergunb 0:8f0d870509fe 229 EECR = (1<<EEMPE) | // Set Master Write Enable bit...
Sergunb 0:8f0d870509fe 230 (1<<EEPM1); // ...and Write-only mode.
Sergunb 0:8f0d870509fe 231 EECR |= (1<<EEPE); // Start Write-only operation.
Sergunb 0:8f0d870509fe 232 }
Sergunb 0:8f0d870509fe 233 }
Sergunb 0:8f0d870509fe 234
Sergunb 0:8f0d870509fe 235 sei(); // Restore interrupt flag state.
Sergunb 0:8f0d870509fe 236 #endif
Sergunb 0:8f0d870509fe 237 #if defined(WIN32) || defined(STM32F103C8)
Sergunb 0:8f0d870509fe 238 EE_Buffer[addr] = new_value;
Sergunb 0:8f0d870509fe 239 #endif
Sergunb 0:8f0d870509fe 240 }
Sergunb 0:8f0d870509fe 241
Sergunb 0:8f0d870509fe 242 // Extensions added as part of Grbl
Sergunb 0:8f0d870509fe 243
Sergunb 0:8f0d870509fe 244
Sergunb 0:8f0d870509fe 245 void memcpy_to_eeprom_with_checksum(unsigned int destination, char *source, unsigned int size) {
Sergunb 0:8f0d870509fe 246 unsigned char checksum = 0;
Sergunb 0:8f0d870509fe 247 for(; size > 0; size--) {
Sergunb 0:8f0d870509fe 248 checksum = (checksum << 1) || (checksum >> 7);
Sergunb 0:8f0d870509fe 249 checksum += *source;
Sergunb 0:8f0d870509fe 250 eeprom_put_char(destination++, *(source++));
Sergunb 0:8f0d870509fe 251 }
Sergunb 0:8f0d870509fe 252 eeprom_put_char(destination, checksum);
Sergunb 0:8f0d870509fe 253 #if defined(WIN32) || defined(STM32F103C8)
Sergunb 0:8f0d870509fe 254 #ifndef NOEEPROMSUPPORT
Sergunb 0:8f0d870509fe 255 eeprom_flush();
Sergunb 0:8f0d870509fe 256 #endif
Sergunb 0:8f0d870509fe 257 #endif
Sergunb 0:8f0d870509fe 258 }
Sergunb 0:8f0d870509fe 259
Sergunb 0:8f0d870509fe 260 int memcpy_from_eeprom_with_checksum(char *destination, unsigned int source, unsigned int size) {
Sergunb 0:8f0d870509fe 261 unsigned char data, checksum = 0;
Sergunb 0:8f0d870509fe 262 for(; size > 0; size--) {
Sergunb 0:8f0d870509fe 263 data = eeprom_get_char(source++);
Sergunb 0:8f0d870509fe 264 checksum = (checksum << 1) || (checksum >> 7);
Sergunb 0:8f0d870509fe 265 checksum += data;
Sergunb 0:8f0d870509fe 266 *(destination++) = data;
Sergunb 0:8f0d870509fe 267 }
Sergunb 0:8f0d870509fe 268 return(checksum == eeprom_get_char(source));
Sergunb 0:8f0d870509fe 269 }
Sergunb 0:8f0d870509fe 270
Sergunb 0:8f0d870509fe 271 // end of file