00001 /**********************************************************************************************************************\ 00002 00003 C++ library for Atmel AVR microcontrollers 00004 Copyright (C) 2007 Lauri Kirikal, Mikk Leini, MT� TT� Robotiklubi 00005 00006 This program is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU General Public License 00008 as published by the Free Software Foundation; either version 2 00009 of the License, or (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 00020 See http://creativecommons.org/licenses/GPL/2.0/ 00021 00022 MT� TT� Robotiklubi http://www.robotiklubi.ee robotiklubi@gmail.com 00023 Lauri Kirikal laurikirikal@gmail.com 00024 Mikk Leini mikk.leini@gmail.com 00025 00026 \**********************************************************************************************************************/ 00027 00028 #include "EEPROM.h" 00029 #include "Interrupt.h" 00030 00031 00032 namespace AVRCpp 00033 { 00034 namespace EEPROM 00035 { 00036 00037 // Waits while CPU is programming Flash. Only needed if boot loader is present. 00038 static inline bool IsWritingFlash() { return IsBitsSet<__SPMCSR__>(__SPMEN__); } 00039 static inline void WaitWhileWritingFlash() { while (IsWritingFlash() ); } 00040 00041 static void WriteOperation() 00042 { 00043 // Save SREG_I bit. 00044 uint8_t savedSREG = SREG; 00045 00046 // __EEPE__ must be set immediately after setting __EEMPE__ 00047 GlobalInterrupts::Disable(); 00048 00049 SetBits<_EECR>(__EEMPE__); 00050 SetBits<_EECR>(__EEPE__); 00051 00052 // Restore the interrupt bit in Status Register 00053 SREG = savedSREG; 00054 00055 } // WriteOperation 00056 00057 00058 bool MoveNext() 00059 { 00060 if (EEAR < EEPROM_SIZE - 1) 00061 { 00062 WaitWhileWriting(); 00063 EEAR++; 00064 00065 return true; 00066 } 00067 00068 return false; 00069 00070 } // MoveNext 00071 00072 00073 void Write(uint8_t data) 00074 { 00075 WaitWhileWriting(); 00076 00077 WaitWhileWritingFlash(); 00078 00079 EEDR = data; 00080 00081 WriteOperation(); 00082 00083 } // Write 1 00084 00085 00086 void Write(uint16_t address, uint8_t data) 00087 { 00088 WaitWhileWriting(); 00089 00090 WaitWhileWritingFlash(); 00091 00092 SetAddressUnsafe(address); 00093 00094 EEDR = data; 00095 00096 WriteOperation(); 00097 00098 } // Write 2 00099 00100 00101 namespace Internal 00102 { 00103 00104 bool SavingProcess(uint16_t lastByteAddr, uint8_t *uint8Data) 00105 { 00106 // Enough space ? 00107 if (lastByteAddr >= EEPROM_SIZE) 00108 return false; 00109 00110 // Write byte by byte 00111 while (true) 00112 { 00113 Write(*uint8Data); 00114 00115 uint8Data++; 00116 00117 // Done ? 00118 if (EEAR == lastByteAddr) 00119 break; 00120 00121 WaitWhileWriting(); 00122 EEAR++; 00123 } 00124 00125 MoveNext(); 00126 00127 return true; 00128 00129 } // SavingProcess 00130 00131 00132 bool LoadingProcess(uint16_t lastByteAddr, uint8_t *uint8Data) 00133 { 00134 // Enough space ? 00135 if (lastByteAddr >= EEPROM_SIZE) 00136 return false; 00137 00138 // Read byte by byte 00139 while (true) 00140 { 00141 *uint8Data = Read(); 00142 00143 uint8Data++; 00144 00145 // Done ? 00146 if (EEAR == lastByteAddr) 00147 break; 00148 00149 WaitWhileWriting(); 00150 EEAR++; 00151 } 00152 00153 MoveNext(); 00154 00155 return true; 00156 00157 } // LoadingProcess 00158 00159 } // namespace Internal 00160 00161 #if __EEPROM_PROPERTIES__ & __EEPROM_ERASEBLE__ 00162 00163 static inline bool ErasingProcess(uint16_t lastByteAddr) 00164 { 00165 // Enough space ? 00166 if (lastByteAddr >= EEPROM_SIZE) 00167 return false; 00168 00169 // Erase byte by byte 00170 while (true) 00171 { 00172 00173 WaitWhileWriting(); 00174 00175 WaitWhileWritingFlash(); 00176 00177 WriteOperation(); 00178 00179 // Done ? 00180 if (EEAR == lastByteAddr) 00181 break; 00182 00183 WaitWhileWriting(); 00184 00185 EEAR++; 00186 } 00187 00188 MoveNext(); 00189 00190 return true; 00191 00192 } // ErasingProcess 00193 00194 00195 static inline bool EraseOperation(uint16_t numberOfBytes) 00196 { 00197 // Is there anything to read or write ? 00198 if (numberOfBytes == 0) 00199 return true; 00200 00201 { 00202 uint16_t lastByteAddr = EEAR + numberOfBytes - 1; 00203 00204 return ErasingProcess(lastByteAddr); 00205 } 00206 00207 } // EraseOperation 00208 00209 00210 bool Erase(uint16_t numberOfBytes) 00211 { 00212 uint8_t savedEECR = EECR; 00213 00214 SetMode(EraseOnly); 00215 00216 { 00217 bool result = EraseOperation(numberOfBytes); 00218 00219 ChangeBits<_EECR>(_EEPM1 | _EEPM0, savedEECR); 00220 00221 return result; 00222 } 00223 00224 } // Erase 00225 00226 #endif // if __EEPROM_PROPERTIES__ & __EEPROM_ERASEBLE__ 00227 00228 } // namespace EEPROM 00229 00230 } // namespace AVRCpp
MTÜ TTÜ Robotiklubi |