Sergey Pastor / grbl1
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers eeprom.c Source File

eeprom.c

Go to the documentation of this file.
00001 // This file has been prepared for Doxygen automatic documentation generation.
00002 /*! \file ********************************************************************
00003 *
00004 * Atmel Corporation
00005 *
00006 * \li File:               eeprom.c
00007 * \li Compiler:           IAR EWAAVR 3.10c
00008 * \li Support mail:       avr@atmel.com
00009 *
00010 * \li Supported devices:  All devices with split EEPROM erase/write
00011 *                         capabilities can be used.
00012 *                         The example is written for ATmega48.
00013 *
00014 * \li AppNote:            AVR103 - Using the EEPROM Programming Modes.
00015 *
00016 * \li Description:        Example on how to use the split EEPROM erase/write
00017 *                         capabilities in e.g. ATmega48. All EEPROM
00018 *                         programming modes are tested, i.e. Erase+Write,
00019 *                         Erase-only and Write-only.
00020 *
00021 *                         $Revision: 1.6 $
00022 *                         $Date: Friday, February 11, 2005 07:16:44 UTC $
00023 ****************************************************************************/
00024 #include "grbl.h"
00025 #ifdef AVRTARGET
00026 #include <avr/io.h>
00027 #include <avr/interrupt.h>
00028 /* These EEPROM bits have different names on different devices. */
00029 #ifndef EEPE
00030         #define EEPE  EEWE  //!< EEPROM program/write enable.
00031         #define EEMPE EEMWE //!< EEPROM master program/write enable.
00032 #endif
00033 
00034 /* These two are unfortunately not defined in the device include files. */
00035 #define EEPM1 5 //!< EEPROM Programming Mode Bit 1.
00036 #define EEPM0 4 //!< EEPROM Programming Mode Bit 0.
00037 
00038 /* Define to reduce code size. */
00039 #define EEPROM_IGNORE_SELFPROG //!< Remove SPM flag polling.
00040 #endif
00041 #ifdef WIN32
00042 #include <stdio.h>
00043 #include <string.h>
00044 #endif
00045 #ifdef STM32F103C8
00046 #include <string.h>
00047 #include "stm32eeprom.h"
00048 #include "settings.h"
00049 #endif
00050 #if defined(WIN32) || defined (STM32F103C8)
00051 unsigned char EE_Buffer[0x400];
00052 #endif
00053 #if defined(WIN32)
00054 #ifndef NOEEPROMSUPPORT
00055 void eeprom_flush()
00056 {
00057     FILE *out = fopen("eeprom.bin", "wb");
00058     fwrite(EE_Buffer, 1, 0x400, out);
00059     fclose(out);
00060 }
00061 #endif
00062 void eeprom_init()
00063 {
00064 #ifndef NOEEPROMSUPPORT
00065     FILE *in = fopen("eeprom.bin", "rb");
00066     if (in != NULL)
00067     {
00068         fread(EE_Buffer, 1, 0x400, in);
00069         fclose(in);
00070     }
00071     else
00072     {
00073         memset(EE_Buffer, 0xff, 0x400);
00074     }
00075 #else
00076     memset(EE_Buffer, 0x0, 0x400);
00077 #endif
00078 }
00079 #endif
00080 
00081 #ifdef STM32F103C8
00082 #ifndef NOEEPROMSUPPORT
00083 void eeprom_flush()
00084 {
00085     uint32_t nAddress = EEPROM_START_ADDRESS;
00086     uint16_t *pBuffer = (uint16_t *)EE_Buffer;
00087     uint16_t nSize = PAGE_SIZE;
00088 
00089     FLASH_Status FlashStatus = FLASH_COMPLETE;
00090 
00091     /* Erase Page0 */
00092     FlashStatus = FLASH_ErasePage(EEPROM_START_ADDRESS);
00093 
00094     /* If erase operation was failed, a Flash error code is returned */
00095     if (FlashStatus != FLASH_COMPLETE)
00096     {
00097         return;
00098     }
00099 
00100     while (nSize > 0)
00101     {
00102         if (*pBuffer != 0xffff)
00103         {
00104             FLASH_ProgramHalfWord(nAddress, *pBuffer++);
00105         }
00106         else
00107         {
00108             pBuffer++;
00109         }
00110         if (*pBuffer != 0xffff)
00111         {
00112             FLASH_ProgramHalfWord(nAddress + 2, *pBuffer++);
00113         }
00114         else
00115         {
00116             pBuffer++;
00117         }
00118         nSize -= 4;
00119         nAddress += 4;
00120     }
00121 }
00122 void eeprom_init()
00123 {
00124     uint16_t VarIdx = 0;
00125     uint8_t *pTmp = EE_Buffer;
00126 
00127     for (VarIdx = 0; VarIdx < PAGE_SIZE; VarIdx++)
00128     {
00129         *pTmp++ = (*(__IO uint8_t*)(EEPROM_START_ADDRESS + VarIdx));
00130     }
00131 
00132     if (EE_Buffer[0] != SETTINGS_VERSION)
00133     {
00134         pTmp = EE_Buffer;
00135 
00136         for (VarIdx = 0; VarIdx < PAGE_SIZE; VarIdx++)
00137         {
00138             *pTmp++ = 0xFF;
00139         }
00140     }
00141 }
00142 #endif
00143 #endif
00144 
00145 /*! \brief  Read byte from EEPROM.
00146  *
00147  *  This function reads one byte from a given EEPROM address.
00148  *
00149  *  \note  The CPU is halted for 4 clock cycles during EEPROM read.
00150  *
00151  *  \param  addr  EEPROM address to read from.
00152  *  \return  The byte read from the EEPROM address.
00153  */
00154 unsigned char eeprom_get_char( unsigned int addr )
00155 {
00156 #ifdef AVRTARGET
00157     do {} while( EECR & (1<<EEPE) ); // Wait for completion of previous write.
00158     EEAR = addr; // Set EEPROM address register.
00159     EECR = (1<<EERE); // Start EEPROM read operation.
00160     return EEDR; // Return the byte read from EEPROM.
00161 #endif
00162 #if defined(WIN32) || defined(STM32F103C8)
00163     return EE_Buffer[addr];
00164 #endif
00165 }
00166 
00167 /*! \brief  Write byte to EEPROM.
00168  *
00169  *  This function writes one byte to a given EEPROM address.
00170  *  The differences between the existing byte and the new value is used
00171  *  to select the most efficient EEPROM programming mode.
00172  *
00173  *  \note  The CPU is halted for 2 clock cycles during EEPROM programming.
00174  *
00175  *  \note  When this function returns, the new EEPROM value is not available
00176  *         until the EEPROM programming time has passed. The EEPE bit in EECR
00177  *         should be polled to check whether the programming is finished.
00178  *
00179  *  \note  The EEPROM_GetChar() function checks the EEPE bit automatically.
00180  *
00181  *  \param  addr  EEPROM address to write to.
00182  *  \param  new_value  New EEPROM value.
00183  */
00184 void eeprom_put_char( unsigned int addr, unsigned char new_value )
00185 {
00186 #ifdef AVRTARGET
00187     char old_value; // Old EEPROM value.
00188     char diff_mask; // Difference mask, i.e. old value XOR new value.
00189 
00190     cli(); // Ensure atomic operation for the write operation.
00191     
00192     do {} while( EECR & (1<<EEPE) ); // Wait for completion of previous write.
00193     #ifndef EEPROM_IGNORE_SELFPROG
00194     do {} while( SPMCSR & (1<<SELFPRGEN) ); // Wait for completion of SPM.
00195     #endif
00196     
00197     EEAR = addr; // Set EEPROM address register.
00198     EECR = (1<<EERE); // Start EEPROM read operation.
00199     old_value = EEDR; // Get old EEPROM value.
00200     diff_mask = old_value ^ new_value; // Get bit differences.
00201     
00202     // Check if any bits are changed to '1' in the new value.
00203     if( diff_mask & new_value ) {
00204         // Now we know that _some_ bits need to be erased to '1'.
00205         
00206         // Check if any bits in the new value are '0'.
00207         if( new_value != 0xff ) {
00208             // Now we know that some bits need to be programmed to '0' also.
00209             
00210             EEDR = new_value; // Set EEPROM data register.
00211             EECR = (1<<EEMPE) | // Set Master Write Enable bit...
00212                    (0<<EEPM1) | (0<<EEPM0); // ...and Erase+Write mode.
00213             EECR |= (1<<EEPE);  // Start Erase+Write operation.
00214         } else {
00215             // Now we know that all bits should be erased.
00216 
00217             EECR = (1<<EEMPE) | // Set Master Write Enable bit...
00218                    (1<<EEPM0);  // ...and Erase-only mode.
00219             EECR |= (1<<EEPE);  // Start Erase-only operation.
00220         }
00221     } else {
00222         // Now we know that _no_ bits need to be erased to '1'.
00223         
00224         // Check if any bits are changed from '1' in the old value.
00225         if( diff_mask ) {
00226             // Now we know that _some_ bits need to the programmed to '0'.
00227             
00228             EEDR = new_value;   // Set EEPROM data register.
00229             EECR = (1<<EEMPE) | // Set Master Write Enable bit...
00230                    (1<<EEPM1);  // ...and Write-only mode.
00231             EECR |= (1<<EEPE);  // Start Write-only operation.
00232         }
00233     }
00234     
00235     sei(); // Restore interrupt flag state.
00236 #endif
00237 #if defined(WIN32) || defined(STM32F103C8)
00238     EE_Buffer[addr] = new_value;
00239 #endif
00240 }
00241 
00242 // Extensions added as part of Grbl 
00243 
00244 
00245 void memcpy_to_eeprom_with_checksum(unsigned int destination, char *source, unsigned int size) {
00246   unsigned char checksum = 0;
00247   for(; size > 0; size--) { 
00248     checksum = (checksum << 1) || (checksum >> 7);
00249     checksum += *source;
00250     eeprom_put_char(destination++, *(source++)); 
00251   }
00252   eeprom_put_char(destination, checksum);
00253 #if defined(WIN32) || defined(STM32F103C8)
00254 #ifndef NOEEPROMSUPPORT
00255   eeprom_flush();
00256 #endif
00257 #endif
00258 }
00259 
00260 int memcpy_from_eeprom_with_checksum(char *destination, unsigned int source, unsigned int size) {
00261   unsigned char data, checksum = 0;
00262   for(; size > 0; size--) { 
00263     data = eeprom_get_char(source++);
00264     checksum = (checksum << 1) || (checksum >> 7);
00265     checksum += data;    
00266     *(destination++) = data; 
00267   }
00268   return(checksum == eeprom_get_char(source));
00269 }
00270 
00271 // end of file