Good 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 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