00001 /****************************************************************************************/ 00002 /* */ 00003 /* LPC2k_ee.C: basic LPC213x EEPROM routines (rev 1.1, Jan 27th, 2006.) */ 00004 /* */ 00005 /* Functions provided here: */ 00006 /* */ 00007 /* ee_erase(command_ee, result_ee[]): erases all EEPROM */ 00008 /* ee_write(command_ee, result_ee[]): writes record of ee_data (defined in LPC2k_ee.h)*/ 00009 /* ee_read(command_ee, result_ee[]) : reads the last record added into EEPROM */ 00010 /* ee_readn(command_ee, result_ee[]): reads the n-th record in EEPROM */ 00011 /* ee_count(command_ee, result_ee[]): counts records of ee_data type in EEPROM */ 00012 /* */ 00013 /****************************************************************************************/ 00014 00015 #include "LPC214x.h" 00016 #define _EEPROM_ 00017 #include "LPC2k_ee.h" /* LPC2000 EEPROM definitions */ 00018 #undef _EEPROM_ 00019 #define IAP_LOCATION 0x7ffffff1 00020 00021 //const unsigned char eeprom[EE_SIZE] _at_ EE_ADDR_L; 00022 void ee_erase(unsigned int ,unsigned int[]); //function erases EEPROM 00023 void ee_write(unsigned int ,unsigned int[]); //function adds a record in EEPROM 00024 void ee_read (unsigned int ,unsigned int[]); //function reads the latest valid record in EEPROM 00025 void ee_count(unsigned int ,unsigned int[]); //function counts records in EEPROM 00026 void ee_readn(unsigned int ,unsigned int[]); //function reads n-th record in EEPROM 00027 int ee_locate(void); //function locates the next available location 00028 00029 typedef void (*IAP)(unsigned int [],unsigned int[]); 00030 IAP iap_entry; 00031 00032 /************************************************************************/ 00033 /* */ 00034 /* function: */ 00035 /* void ee_erase(unsigned int command_ee,unsigned int result_ee[]) */ 00036 /* */ 00037 /* type: void */ 00038 /* */ 00039 /* parameters: */ 00040 /* command_ee - Not used. */ 00041 /* result_ee[0] - Returns a response to the last IAP command used. */ 00042 /* 0 - EEPROM successfully erased. */ 00043 /* For all other response values, see microcontroller */ 00044 /* User Manual, IAP Commands and Status Codes Summary. */ 00045 /* result_ee[1] - Not used. */ 00046 /* */ 00047 /* version: 1.1 (01/27/2006) */ 00048 /* */ 00049 /* constants defined in LPC2k_ee.h used in this function: */ 00050 /* EE_SEC_L - microcontroller's Flash sector where EEPROM begins */ 00051 /* EE_SEC_H - microcontroller's Flash sector where EEPROM ends */ 00052 /* EE_CCLK - microcontroller's system clock (cclk) */ 00053 /* */ 00054 /* description: */ 00055 /* This function erases LPC2000 on-chip Flash sectors selected to act */ 00056 /* as an EEPROM. All Flash sectors between EE_SEC_L abd EE_SEC_H */ 00057 /* (including these sectors) will be erased using the In Application */ 00058 /* Programming (IAP) routines (see User Manual for more details). */ 00059 /* Also, this function disables all interrupts while erasing the */ 00060 /* EEPROM. If this is not needed, three lines of the ee_erase */ 00061 /* subroutine can simply be commented-out without affecting the */ 00062 /* routine performance at all. */ 00063 /* */ 00064 /* revision history: */ 00065 /* - Rev. 1.1 adds interrupt disable feature. */ 00066 /* */ 00067 /************************************************************************/ 00068 void ee_erase(unsigned int command_ee,unsigned int result_ee[]){ 00069 unsigned int command_iap[5]; 00070 unsigned int result_iap[3]; 00071 unsigned long int enabled_interrupts; 00072 00073 enabled_interrupts = VICIntEnable; //disable all interrupts 00074 VICIntEnClr = enabled_interrupts; 00075 00076 command_iap[0]=50; //prepare sectors from EE_SEC_L to EE_SEC_H for erase 00077 command_iap[1]=EE_SEC_L; 00078 command_iap[2]=EE_SEC_H; 00079 iap_entry=(IAP) IAP_LOCATION; 00080 iap_entry(command_iap,result_iap); 00081 00082 command_iap[0]=52; //erase sectors from EE_SEC_L to EE_SEC_H 00083 command_iap[1]=EE_SEC_L; 00084 command_iap[2]=EE_SEC_H; 00085 command_iap[3]=EE_CCLK; 00086 iap_entry=(IAP) IAP_LOCATION; 00087 iap_entry(command_iap,result_iap); 00088 00089 command_iap[0]=53; //blankcheck sectors from EE_SEC_L to EE_SEC_H 00090 command_iap[1]=EE_SEC_L; 00091 command_iap[2]=EE_SEC_H; 00092 iap_entry=(IAP) IAP_LOCATION; 00093 iap_entry(command_iap,result_iap); 00094 00095 VICIntEnable = enabled_interrupts; //restore interrupt enable register 00096 00097 result_ee[0]=result_iap[0]; 00098 return; 00099 } 00100 00101 /************************************************************************/ 00102 /* */ 00103 /* function: */ 00104 /* void ee_write(unsigned int command_ee,unsigned int result_ee[]) */ 00105 /* */ 00106 /* type: void */ 00107 /* */ 00108 /* parameters: */ 00109 /* command_ee - An address of a content of ee_data type that has */ 00110 /* to be programmed into EEPROM. */ 00111 /* result_ee[0] - Returns a response to the last IAP command used. */ 00112 /* 0 - data successfully programmed in EEPROM. */ 00113 /* 501 - no space in EEPROM to program data. */ 00114 /* For all other response values, see microcontroller */ 00115 /* User Manual, IAP Commands and Status Codes Summary. */ 00116 /* result_ee[1] - Not used. */ 00117 /* */ 00118 /* version: 1.1 (01/27/2006) */ 00119 /* */ 00120 /* constants defined in LPC2k_ee.h used in this function: */ 00121 /* EE_BUFFER_SIZE - IAP buffer size; must be 256 or 512 */ 00122 /* NO_SPACE_IN_EEPROM - EEPROM is full and no data can be programmed */ 00123 /* EE_BUFFER_MASK - parameter used for interfacing with IAP */ 00124 /* EE_REC_SIZE - ee_data structure size in bytes */ 00125 /* EE_SEC_L - micro's Flash sector where EEPROM begins */ 00126 /* EE_SEC_H - micro's Flash sector where EEPROM ends */ 00127 /* EE_CCLK - micro's system clock (cclk) */ 00128 /* */ 00129 /* description: */ 00130 /* This function writes a single structure of ee_data type into the */ 00131 /* EEPROM using an In Application Programming (IAP) routines (see */ 00132 /* User Manual for more details). command_ee contains an address of */ 00133 /* this structure. EEPROM is scanned for the last (if any) record */ 00134 /* identifier (EE_REC_ID), and a new record is added next to it. */ 00135 /* Also, this function disables all interrupts while erasing the */ 00136 /* EEPROM. If this is not needed, three lines of the ee_write */ 00137 /* subroutine can simply be commented-out without affecting the */ 00138 /* routine performance at all. */ 00139 /* */ 00140 /* revision history: */ 00141 /* - Rev. 1.1 fixes a bug related to verifying a content written into */ 00142 /* the EEPROM. 1.0 was reporting missmatch even when there were no */ 00143 /* problems at all. */ 00144 /* Rev. 1.1 adds interrupt disable feature. */ 00145 /* */ 00146 /************************************************************************/ 00147 void ee_write(unsigned int command_ee,unsigned int result_ee[]){ 00148 int location; 00149 unsigned int *source, *destination, i; 00150 unsigned char ee_buffer[EE_BUFFER_SIZE]; 00151 unsigned int command_iap[5], result_iap[3]; 00152 unsigned long int enabled_interrupts; 00153 00154 location = ee_locate(); 00155 if (location == -1){ 00156 result_ee[0]=NO_SPACE_IN_EEPROM; 00157 } 00158 else{ 00159 for (i=0;i<EE_BUFFER_SIZE;i++) ee_buffer[i]=0xFF; 00160 00161 destination = (unsigned int *) ((&ee_buffer[0])+((unsigned int)location & EE_BUFFER_MASK)); 00162 source = (unsigned int *) command_ee; 00163 for(i=0;i!=EE_REC_SIZE/4;i++) *(destination+i) = *(source+i); 00164 00165 enabled_interrupts = VICIntEnable; //disable all interrupts 00166 VICIntEnClr = enabled_interrupts; 00167 00168 command_iap[0]=50; //prepare sectors from EE_SEC_L to EE_SEC_H for erase 00169 command_iap[1]=EE_SEC_L; 00170 command_iap[2]=EE_SEC_H; 00171 iap_entry=(IAP) IAP_LOCATION; 00172 iap_entry(command_iap,result_iap); 00173 00174 command_iap[0]=51; //copy RAM to flash/eeprom 00175 command_iap[1]=(unsigned int) (location & EE_START_MASK); 00176 command_iap[2]=(unsigned int) (&ee_buffer[0]); 00177 command_iap[3]=EE_BUFFER_SIZE; 00178 command_iap[4]=EE_CCLK; 00179 iap_entry=(IAP) IAP_LOCATION; 00180 iap_entry(command_iap,result_iap); 00181 00182 command_iap[0]=56; //compare RAM and flash/eeprom 00183 command_iap[1]=(unsigned int) source; 00184 command_iap[2]=(unsigned int) location; 00185 command_iap[3]=EE_REC_SIZE; 00186 iap_entry=(IAP) IAP_LOCATION; 00187 iap_entry(command_iap,result_iap); 00188 00189 VICIntEnable = enabled_interrupts; //restore interrupt enable register 00190 00191 result_ee[0]=result_iap[0]; 00192 } 00193 return; 00194 } 00195 00196 /************************************************************************/ 00197 /* */ 00198 /* function: */ 00199 /* void ee_read(unsigned int command_ee,unsigned int result_ee[]) */ 00200 /* */ 00201 /* type: void */ 00202 /* */ 00203 /* parameters: */ 00204 /* command_ee - Not used. */ 00205 /* result_ee[0] - Returns a response. */ 00206 /* 0 - data successfully found in EEPROM. */ 00207 /* 500 - no data/records available in EEPROM. */ 00208 /* result_ee[1] - an address of the last record of ee_data type */ 00209 /* in EEPROM. */ 00210 /* */ 00211 /* version: 1.1 (01/27/2006) */ 00212 /* */ 00213 /* constants defined in LPC2k_ee.h used in this function: */ 00214 /* NO_RECORDS_AVAILABLE - EEPROM is empty/no records identifiable */ 00215 /* with a record identifier (EE_REC_ID) found */ 00216 /* EE_ADR_L - micro's Flash address from where EEPROM begins */ 00217 /* EE_REC_SIZE - size (in bytes) of a ee_data structure */ 00218 /* */ 00219 /* description: */ 00220 /* This function scans an EEPROM content looking for the last record */ 00221 /* that can be identified with a record identifier (EE_REC_ID). When */ 00222 /* such data is found, its address is passed as result_ee[1]. */ 00223 /* */ 00224 /* revision history: */ 00225 /* - Rev. 1.0 had problems with accessing the last record in a fully */ 00226 /* occupied EEPROM. Rev. 1.1 fixes this. */ 00227 /* */ 00228 /************************************************************************/ 00229 void ee_read(unsigned int command_ee,unsigned int result_ee[]){ 00230 int location; 00231 00232 location = ee_locate(); 00233 if (location == EE_ADDR_L){ 00234 result_ee[0]=NO_RECORDS_AVAILABLE; 00235 } 00236 else{ 00237 result_ee[0]=0; 00238 if (location == -1) 00239 result_ee[1]=(unsigned int)(EE_ADDR_H+1 - EE_REC_SIZE); 00240 else 00241 result_ee[1]=(unsigned int)(location - EE_REC_SIZE); 00242 } 00243 return; 00244 } 00245 00246 /************************************************************************/ 00247 /* */ 00248 /* function: */ 00249 /* void ee_readn(unsigned int command_ee,unsigned int result_ee[]) */ 00250 /* */ 00251 /* type: void */ 00252 /* */ 00253 /* parameters: */ 00254 /* command_ee - An index of a record in EEPROM that should be read. */ 00255 /* result_ee[0] - Returns a response. */ 00256 /* 0 - data successfully found in EEPROM. */ 00257 /* 502 - requested index of record in EEPROM is out of */ 00258 /* EEPROM's memory. */ 00259 /* result_ee[1] - an address of the specified record of ee_data type */ 00260 /* in EEPROM. */ 00261 /* */ 00262 /* version: 1.0 (initial release 05/13/2005) */ 00263 /* */ 00264 /* constants defined in LPC2k_ee.h used in this function: */ 00265 /* INDEX_OUT_OF_RANGE - index of a record in EEPROM specified by */ 00266 /* command_ee is out of EEPROM's range */ 00267 /* EE_ADR_L - micro's Flash address from where EEPROM begins */ 00268 /* EE_ADR_H - micro's Flash address where EEPROM ends */ 00269 /* EE_REC_SIZE - size (in bytes) of a ee_data structure */ 00270 /* */ 00271 /* description: */ 00272 /* This function returns in result_ee[1] an address of an EEPROM */ 00273 /* record index specified in command_ee. Index can not be less than 0. */ 00274 /* */ 00275 /************************************************************************/ 00276 void ee_readn(unsigned int command_ee,unsigned int result_ee[]){ 00277 if(command_ee>((EE_ADDR_H+1-EE_ADDR_L)/EE_REC_SIZE)){ 00278 result_ee[0]=INDEX_OUT_OF_RANGE;} 00279 else{ 00280 result_ee[0]=0; 00281 result_ee[1]=(unsigned int)(EE_ADDR_L+EE_REC_SIZE*command_ee); 00282 } 00283 return; 00284 } 00285 00286 /************************************************************************/ 00287 /* */ 00288 /* function: */ 00289 /* void ee_count(unsigned int command_ee,unsigned int result_ee[]) */ 00290 /* */ 00291 /* type: void */ 00292 /* */ 00293 /* parameters: */ 00294 /* command_ee - Not used. */ 00295 /* result_ee[0] - Returns a response. Always 0. */ 00296 /* result_ee[1] - number of records of ee_data type in EEPROM. */ 00297 /* */ 00298 /* version: 1.1 (01/27/2006) */ 00299 /* */ 00300 /* constants defined in LPC2k_ee.h used in this function: */ 00301 /* EE_ADR_L - micro's Flash address from where EEPROM begins */ 00302 /* EE_REC_SIZE - size (in bytes) of a ee_data structure */ 00303 /* */ 00304 /* description: */ 00305 /* This function returns number of records of ee_data type in EEPROM. */ 00306 /* */ 00307 /* revision history: */ 00308 /* - Initial release (1.0) was not supplying the right feedback in case */ 00309 /* of counting records in a full EEPROM. Rev. 1.1 fixes this. */ 00310 /* */ 00311 /************************************************************************/ 00312 void ee_count(unsigned int command_ee,unsigned int result_ee[]){ 00313 int location; 00314 result_ee[0]=0; 00315 location = ee_locate(); 00316 if (location == -1) location = EE_ADDR_H+1; 00317 result_ee[1]=(unsigned int)((location-EE_ADDR_L)/EE_REC_SIZE); 00318 return; 00319 } 00320 00321 /************************************************************************/ 00322 /* */ 00323 /* function: */ 00324 /* void ee_locate() */ 00325 /* */ 00326 /* type: int */ 00327 /* */ 00328 /* parameters: none */ 00329 /* */ 00330 /* version: 1.1 (01/27/2006) */ 00331 /* */ 00332 /* constants defined in LPC2k_ee.h used in this function: */ 00333 /* EE_ADR_L - micro's Flash address from where EEPROM begins */ 00334 /* EE_ADR_H - micro's Flash address where EEPROM ends */ 00335 /* EE_REC_ID - a record indicator used to identify valid data */ 00336 /* EE_REC_SIZE - size (in bytes) of a ee_data structure */ 00337 /* */ 00338 /* description: */ 00339 /* This function returns an address as of which new record can be */ 00340 /* added into Flash/EEPROM. In case of EEPROM being full, function */ 00341 /* returns -1. Searching is based on divide by two method that */ 00342 /* provides the fastest processing time. */ 00343 /* */ 00344 /* revision history: */ 00345 /* - Rev. 1.1 fixes a bug related to identifying an unused byte of */ 00346 /* EEPROM in an EEPROM with size not equal to EE_REC_SIZE * 2^k (k>=0)*/ 00347 /* */ 00348 /************************************************************************/ 00349 int ee_locate(void){ 00350 unsigned int addr_l, addr_m, addr_r, size, slice_limit; 00351 addr_l = EE_ADDR_L; 00352 if ((*((unsigned char *)addr_l))==0xFF) return(addr_l); 00353 addr_r = EE_ADDR_H+1; 00354 if ((*((unsigned char *)(addr_r-EE_REC_SIZE)))==EE_REC_ID) return(-1); 00355 size = addr_r - addr_l; 00356 slice_limit = EE_REC_SIZE - 1; 00357 while(size != EE_REC_SIZE){ 00358 addr_m = (addr_r+addr_l)/2; 00359 if ((addr_m & slice_limit)!=0x00000000){ 00360 if ((*((unsigned char *)(addr_r - EE_REC_SIZE)))==0xFF) 00361 addr_r = addr_r - EE_REC_SIZE; 00362 else 00363 addr_l = addr_l + EE_REC_SIZE; 00364 addr_m = (addr_r+addr_l)/2; 00365 size = size - EE_REC_SIZE; 00366 } 00367 if ((*((unsigned char *)addr_m))==0xFF) 00368 addr_r = addr_m; 00369 else 00370 addr_l = addr_m; 00371 size = size/2; 00372 } 00373 return(addr_r); 00374 }