|
View:
New views
11 Messages
—
Rating Filter:
Alert me
|
|
|
eeprom redundant-values routinesGood day to all.
I'm getting started on a project that requires a few bytes of eeprom. The target is a 12F675. I recall recent discussion (and past discussions) about the problem of multiple writes causing eventual read failures of static eeprom values (static as in they don't change often or at all). Bob Axtell mentions that he gets around the problem by storing 5 redundant values and checking them upon reading. This sounds like it might be a good idea. With that in mind, I started writing code. Its somewhat more complicated than I first thought. I'd like to post my routines for any thoughts or criticisms. In particular, I'd like to find shorter or faster methods of doing the same thing. In a nutshell, this is a pair of subroutines. The main code calls ReadEEredundant with the starting address in W. The routine returns with the Z=1 and the value read from eeprom in W if everything was OK. It returns Z=0 if it can't find 3 identical bytes in the 5 locations (fatal error). ReadEEredundant makes use of another subroutine as part of its operation. The whole thing uses 2 levels of stack. If ReadEEredundant finds one or more bad bytes out of the 5 but does find at least 3 values the same, it re-writes all 5 bytes. Before I post the code, I should mention the conventions that I use when writing my code. RB1(value) is a macro that writes that value to ram page 1 BB1(_value) is another macro that sets or clears individual bits on ram page 1 The above macros are mostly to ensure that I get adequate warning if I mess up writing to the wrong ram page. Individual bits are defined with a leading underscore. SUBTMP1 through SUBTMP3 are temporary values used in subroutines and are on ram page 0 SUBTMP1_0 through SUBTMP1_3 are the same but on ram page 1 I realize that user ram on the 12F675 is the same on both ram page 0 & ram page 1 but I tend to write my code for the other PICs that I use. rampg0 is a macro that sets the ram page select bits to ram page 0 rampg1 is a macro that sets the ram page select bits to ram page 1 tstw is a 1 line macro that sets or clears the Z flag based on the value contained in W (xorlw 0) Finally, I need to mention that this is a first pass on the code. While it assembles cleanly, I haven't yet fully tested it. There may be some stupid errors in there. All that said: here's the code. Again, these are subroutines that are intended to be called by the main loop. ReadEEredundant ;read EE value stored in 5 redundant locations ;enters with start address in W ;returns with EE value in W, Z=0 if OK, z=1 if fail ;read redundant eeprom value, re-write value if corrupted rampg1 ;this whole routine uses ram pg 1 movwf SUBTMP1_0 ;save start location movwf RB1(EEADR) movlw .4 ;# bytes to compare to movwf SUBTMP1_1 ;loop counter movfw SUBTMP1_0 ;start with 1st byte call ReadRedund ;returns: 0x00=perfect, 0x01=1st OK, 0xFF=bad tstw bz NoReadErrors ;all 5 values identical ;one or more read errors have occurred ;2 choices here: 1st byte is OK **or** 1st byte doesn't match at least 2 others xorlw 0x01 bz ReadEErewrite ;fewer than 3 errors: rewrite array ;1st byte doesn't match 2 other bytes: try starting with 2nd byte movlw .3 ;# bytes to compare to movwf SUBTMP1_1 ;loop counter incf SUBTMP1_0,W ;start with 2nd byte call ReadRedund ;returns: 0x01=1st OK, 0xFF=bad ;2 choices: 2nd byte is OK **or** 2nd byte doesn't match at least 2 others xorlw 0x01 bz ReadEErewrite ;fewer than 3 errors: rewrite array ;2nd byte doesn't match 2 other bytes: try last (3rd) byte movlw .2 ;# bytes to compare to movwf SUBTMP1_1 ;loop counter movlw .2 ;start with 3rd byte addwf SUBTMP1_0,W call ReadRedund ;returns: 0x01=1st OK, 0xFF=bad ;2 choices: 3rd byte is OK **or** 3rd byte doesn't match at least 2 others xorlw 0x01 bz ReadEErewrite ;fewer than 3 errors: rewrite array ;fatal error: no 3 bytes identical rampg0 clrz retlw 0xFF ;Bad data. Returns z=0 NoReadErrors movfw SUBTMP1_3 ; rampg0 setz return ;returns with known-good value in W, z=1 ReadEErewrite ;re-write entire block of 5 bytes with known-good data ;still in ram pg 1 movfw SUBTMP1_3 ;retrieve known-good data movwf RB1(EEDATA) movfw SUBTMP1_0 ;starting address movwf RB1(EEADR) movlw .5 ;write all 5 bytes movwf SUBTMP1_1 ReadEErewriteLoop rampg0 movlw INT_EEWRITE ;clr all bits except PEIE movwf INTCON bcf _EEIF rampg1 movlw PIE1_EEWRITE ;clr all bits except EEIE movwf RB1(PIE1) bsf BB1(_WREN) ;EE write enable movlw 0x55 ;EE un-lock sequence movwf RB1(EECON2) movlw 0xAA movwf RB1(EECON2) bsf BB1(_WR) ;initiate write bcf BB1(_WREN) ;clear EE write enable sleep ;GIE=0, all others =0 except PEIE & EEIE incf RB1(EEADR),F ;next address decfsz SUBTMP1_1,F goto ReadEErewriteLoop movlw PIE1_INIT movwf RB1(PIE1) ;restore PIE1 movfw SUBTMP1_3 ;known-good value rampg0 movwf SUBTMP1 ;save value from rampg1 to rampg0 movlw INT_INIT movwf INTCON ;restore INTCON movfw SUBTMP1 setz return ;done! Returns with value in W, Z=1 if OK ReadRedund ;enters with comparison byte address in W ;returns: 0x00=perfect, 0x01= 1st byte OK, 0xFF= bad ;still in ram pg 1 movwf RB1(EEADR) bsf BB1(_RD) movfw RB1(EEDATA) ;W contains comparison byte movwf SUBTMP1_3 ;save for exit clrf SUBTMP1_2 ;bytes-the-same-value register (bit mapped) ReadRedundLoop clrc incf RB1(EEADR),F ;point to next address bsf BB1(_RD) xorwf RB1(EEDATA),W ;same as 1st address? skpnz setc xorwf RB1(EEDATA),W ;restore W rlf SUBTMP1_2,F decfsz SUBTMP1_1,F goto ReadRedundLoop ;fall into GetEE_Error GetEE_Error ;"1" bits means match with 1st (comparison) byte movfw SUBTMP1_2 addwf PCL,W skpnc incf PCLATH,F movwf PCL ;need to match at least 2 bytes (3 total) retlw 0xFF ;b'xxxx0000' retlw 0xFF ;b'xxxx0001' retlw 0xFF ;b'xxxx0010' retlw 0x01 ;b'xxxx0011' retlw 0xFF ;b'xxxx0100' retlw 0x01 ;b'xxxx0101' retlw 0x01 ;b'xxxx0110' retlw 0x01 ;b'xxxx0111' retlw 0xFF ;b'xxxx1000' retlw 0x01 ;b'xxxx1001' retlw 0x01 ;b'xxxx1010' retlw 0x01 ;b'xxxx1011' retlw 0x01 ;b'xxxx1100' retlw 0x01 ;b'xxxx1101' retlw 0x01 ;b'xxxx1110' retlw 0x00 ;b'xxxx1111' No errors As I mentioned, I'd be interested in other (easier) ways of doing the same thing. Many thanks! dwayne -- Dwayne Reid <dwayner@...> Trinity Electronics Systems Ltd Edmonton, AB, CANADA (780) 489-3199 voice (780) 487-6397 fax www.trinity-electronics.com Custom Electronics Design and Manufacturing -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist |
|
|
Re: eeprom redundant-values routinesOn Wed, Oct 28, 2009 at 10:46 PM, Dwayne Reid <dwayner@...> wrote:
> I recall recent discussion (and past discussions) about the problem > of multiple writes causing eventual read failures of static eeprom > values (static as in they don't change often or at all). If the data doesn't change, don't initiate an EEPROM write. Only write it on change. This should eliminate this concern. However, in high reliability scenarios, five copies is perhaps overkill, and the way you are doing the write may be prone to problems related to power off conditions (ie, since all five bytes are being written you may run into issues regarding the validity of data if the write is in process when the unit loses power). You must seperate your writes in both time and space - they should not be immediately adjacent, and the writes should not occur at the same time. Further, you would be better off adopting a CRC and a counter for each redundant value (or redundant datablock). This gives you confidence the value is correct (error checking), and that it's the latest value stored (coherence). For example: In one high reliability, safety critical industry the most critical information is kept in three locations, everything else is stored in only two locations. Each time the value is changed the counter is incremented, the CRC calculated over both the value and the counter, and the first redundant copy is written. If anything fails during this write, the second copy still has the older value, and the CRC ensures that this one won't be used. Once the first copy is finished writing, a routine verifies it. Then the counter is incremented, the CRC recalculated, and the second copy is written and verified. Again, if anything fails during this write then the first copy is known good, and the counter verifies that it's the latest. If a third copy is made, then the same process happens all over again. On boot up both (or all three) values are checked to see if the CRC is ok. For those items where the CRC is ok, the counters are checked to see which one is the latest, and that value is used. During normal operation, another periodic routine goes over all the eeprom checking CRCs and comparing values in redundant copies. It simply sets a flag if something goes wrong, and the module may report the error for user replacement before the other locations go bad. Depending on the project requirements it may either 1) not attempt to to 'fix' anything or re-write anything, it merely reports on inconsistencies it finds, or 2) if a CRC is bad, or values don't match, it takes the latest good value and attempts a re-write of the bad copy. Options 2 is harder than option one, because you then have to store more informaiton in EEPROM to limit the number of times you attempt to re-write the data. Further, if the EEPROM is going bad it's often better to baby it and avoid writes, so fixing it may actually exacerbate the problem. This removes most problems with power down, bad eeprom cells, etc. It doesn't really perform EEPROM wear leveling, which is something you must consider if you believe you're going to be doing more than 1k writes to any given cell in the EEPROM over the life of the unit. Even though the EEPROM is rated to 10k, 100k, or more, that's an MTBF - statistically calculated, and any one cell can easily fail well before then and still be withing the statistical curve of their rating. Wear leveling has to have a bit more thought put into it in regards to infrequently changing values vs frequently changing values, and whether redundant copies are actually spaced apart in EEPROM. Simply copying the values 5 times and checking for correlation is a very poor method for error and coherence checking. CRC for error checking, and counters for coherence are a _significantly_ better option. But if you need to stick with the 5 bytes for whatever reason (perhaps this is overkill for your situation), make sure the writes are done in seperate operations, and space them out throughout the EEPROM if possible. In the PIC you mention it doesn't matter, but on other devices if there are multiple EEPROM 'blocks' then put seperate copies into different blocks of the EEPROM. Also, you'll need to have a hard-coded fallback value if all the copies fail their CRC checks, and your device is required to continue operation (either full or partial) given complete EEPROM failure. You may need to do this in your scenario if three or four cells have failed (and only 2 or no values match). I hope this is useful. -Adam -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist |
|
|
Re: eeprom redundant-values routinesHi Adam,
On Thu, Oct 29, 2009 at 8:56 AM, M. Adam Davis <stienman@...> wrote: > On Wed, Oct 28, 2009 at 10:46 PM, Dwayne Reid <dwayner@...> wrote: >> I recall recent discussion (and past discussions) about the problem >> of multiple writes causing eventual read failures of static eeprom >> values (static as in they don't change often or at all). > > If the data doesn't change, don't initiate an EEPROM write. Only > write it on change. This should eliminate this concern. > Hmmm. The datasheets for many of the affected parts suggest that rarely-changing data SHOULD be "refreshed" or re-written. Do you think that the datasheet is mixed up here? Sean -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist |
|
|
Re: eeprom redundant-values routinesAt 06:56 AM 10/29/2009, M. Adam Davis wrote:
>On Wed, Oct 28, 2009 at 10:46 PM, Dwayne Reid <dwayner@...> wrote: > > I recall recent discussion (and past discussions) about the problem > > of multiple writes causing eventual read failures of static eeprom > > values (static as in they don't change often or at all). > >If the data doesn't change, don't initiate an EEPROM write. Only >write it on change. This should eliminate this concern. That used to be my standard approach. However, Microchip is quite adamant that frequent writes to the eeprom array will damage static data in other locations. In other words, data that has not been changed or refreshed can be damaged by writes to other locations within the eeprom array. This is new behavior and something that I've not had to deal with previously. You will notice that I am treating my re-writes as a refresh. Thus, if any of the 5 values is different from the others, I refresh all 5 bytes. I also do NOT re-write the data if all 5 values are the same. Power-down during writes is definite concern. I didn't mention it but I think that I have it covered: this particular project is required to allow operation only while the incoming line voltage is within a specified window. I have a slow filter on the incoming AC line voltage measurement routine for that purpose - and a much faster filter that is used to disallow writes if the AC should fail. There is sufficient power supply reserve to allow all 5 writes to complete should the AC fail while the writes are occurring. Good points, though. I appreciate it. dwayne -- Dwayne Reid <dwayner@...> Trinity Electronics Systems Ltd Edmonton, AB, CANADA (780) 489-3199 voice (780) 487-6397 fax www.trinity-electronics.com Custom Electronics Design and Manufacturing -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist |
|
|
Re: eeprom redundant-values routinesI've got a 16F886 in a device where I store a number of user settable
paramaters in eeprom and I don't have any more space either in eeprom or program memory to store multiple redundant values. There have been a number of threads now on eeprom loss of data problems and this has got me concerned about PIC reliability. Is this common in all eeproms in all PICs or are microchip's devices just crappy? Over the life of my divice I will read the eeprom less than 700 times. Is this something that will cause problems? Can someone point me to a document were the problem is described and specs given? Thanks, Gordon Williams -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist |
|
|
Re: eeprom redundant-values routinesGordon Williams escreveu:
> I've got a 16F886 in a device where I store a number of user settable > paramaters in eeprom and I don't have any more space either in eeprom or > program memory to store multiple redundant values. > > There have been a number of threads now on eeprom loss of data problems and > this has got me concerned about PIC reliability. Is this common in all > eeproms in all PICs or are microchip's devices just crappy? > > Over the life of my divice I will read the eeprom less than 700 times. Is > this something that will cause problems? Can someone point me to a document > were the problem is described and specs given? Why are you worried about the number of reads the EEPROM will be subjected? AFAIK the number of reads are unlimited, the writes are what affect the EEPROM reliability. __________________________________________________ Faça ligações para outros computadores com o novo Yahoo! Messenger http://br.beta.messenger.yahoo.com/ -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist |
|
|
Re: eeprom redundant-values routinesAt 11:41 AM 10/29/2009, Gordon Williams wrote:
>There have been a number of threads now on eeprom loss of data problems and >this has got me concerned about PIC reliability. Is this common in all >eeproms in all PICs or are microchip's devices just crappy? > >Over the life of my divice I will read the eeprom less than 700 times. Is >this something that will cause problems? Can someone point me to a document >were the problem is described and specs given? This problem appeared to surface with Microchip's later chips (nanowatt series?). Early chips such as the venerable F84 or the early 16F628 don't have the problem, the (a) versions of the 16F628 (16F628A) apparently do have the problem. So, apparently, does the 12F675. So far as I know, reading the eeprom does NOT cause the problems, Instead, the problem is caused by many writes to one part of the eeprom array. Those bytes that are frequently written are NOT the problem. What does get affected is eeprom addresses that DON'T get written. I know that I've seen Microchip describe this in at least one data sheet but I'll be darned if I can find just WHICH data sheet that was (I spent 5 minutes looking just now). I'll post the URL for the appropriate data sheet when I run across it again. dwayne -- Dwayne Reid <dwayner@...> Trinity Electronics Systems Ltd Edmonton, AB, CANADA (780) 489-3199 voice (780) 487-6397 fax www.trinity-electronics.com Custom Electronics Design and Manufacturing -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist |
|
|
Re: eeprom redundant-values routinesOn Thu, Oct 29, 2009 at 1:55 PM, Dwayne Reid <dwayner@...> wrote:
> > So far as I know, reading the eeprom does NOT cause the > problems, Instead, the problem is caused by many writes to one part > of the eeprom array. Those bytes that are frequently written are NOT > the problem. What does get affected is eeprom addresses that DON'T > get written. > Dwayne, This seems to be in dispute. In the recent discussion on this (about 1 month ago), several people claimed that reads DO degrade the EEPROM cell contents in these certain affected PICs. This is not mentioned in the datasheets but people seem to claim that the information in the datasheets is at best incomplete. I would be very happy to hear additional information about this since we have some products out in the field which would be severely affected by this. They use nanowatt series parts, continually read the EEPROM, do not store redundant values, and write much more frequently to some parts of the array than to others. We designed them to be compatible with products originally made by another manufacturer so we do not have total flexibility in the way the EEPROM is used (i.e., too much of it is used to make duplicate copies of each value). Sean -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist |
|
|
Re: eeprom redundant-values routines> So far as I know, reading the eeprom does NOT cause the > problems, Instead, the problem is caused by many writes to one part > of the eeprom array. Thanks for the clarification. By "many writes" are you talking about hundreds, tens of thousand. The eeprom endurance is spec'ed at 1M writes. Gordon Williams -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist |
|
|
Re: eeprom redundant-values routinesMaybe some clarification.
Section 10.3.1 in the 16F88x data sheet says: 10.3.1 USING THE DATA EEPROM The data EEPROM is a high-endurance, byte addressable array that has been optimized for the storage of frequently changing information (e.g., program variables or other data that are updated often). When variables in one section change frequently, while variables in another section do not change, it is possible to exceed the total number of write cycles to the EEPROM (specification D124) without exceeding the total number of write cycles to a single byte (specifications D120 and D120A). If this is the case, then a refresh of the array must be performed. For this reason, variables that change infrequently (such as constants, IDs, calibration, etc.) should be stored in Flash program memory. with 17.5 saying (sorry about the format): Data EEPROM Memory D120 ED Byte Endurance 100K 1M - E/W -40°C ? TA ? +85°C D120A ED Byte Endurance 10K 100K - E/W +85°C ? TA ? +125°C D121 VDRW VDD for Read/Write VMIN - 5.5 V Using EECON1 to read/write VMIN = Minimum operating voltage D122 TDEW Erase/Write Cycle Time - 5 6 ms D123 TRETD Characteristic Retention 40 - - Year Provided no other specifications are violated D124 TREF Number of Total Erase/Write Cycles before Refresh(4) 1M 10M - E/W -40°C ? TA ? +85° The way that I read this was that each byte in EEPROM would last typically 1M writes (D120) and that the eeprom could have typically 10M writes (D124) before the whole thing would need to be refreshed. Have I got it right? Gordon Williams ----- Original Message ----- From: "Gordon Williams" <gwilliams@...> To: "Microcontroller discussion list - Public." <piclist@...> Sent: Thursday, October 29, 2009 3:07 PM Subject: Re: [PIC] eeprom redundant-values routines > > > So far as I know, reading the eeprom does NOT cause the > > problems, Instead, the problem is caused by many writes to one part > > of the eeprom array. > > Thanks for the clarification. By "many writes" are you talking about > hundreds, tens of thousand. The eeprom endurance is spec'ed at 1M writes. > > Gordon Williams > > -- > http://www.piclist.com PIC/SX FAQ & list archive > View/change your membership options at > http://mailman.mit.edu/mailman/listinfo/piclist -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist |
|
|
|
| Free embeddable forum powered by Nabble | Forum Help |