Shop OBEX P1 Docs P2 Docs Learn Events
Problem writing to 64k EEPROM — Parallax Forums

Problem writing to 64k EEPROM

MJHanaganMJHanagan Posts: 189
edited 2012-06-20 08:09 in Propeller 1
I am tring to write some LONG variables to the upper end of the 64k byte EEPROM on my Gadget Gangster Propeller USB board and have problems writing to address $FFF8. I can write to and read a LONG variable starting at $FFFC and one at $FFF4 without any problems but the middle one at $FFF8 always returns a -1 value. Any ideas on what I am doing wrong here?

Here is the basic code:
CON
  _clkmode = xtal1 + pll16x
  _xinfreq = 5_000_000

'  MemoryLocation = $7FE0        'Location in memory to store ID.  $7FE0 will place at end of eeprom
' EEPROM memory locations for storing last known axis positions and last established origin and status byte.

' For 64k EEPROM:
  Xabs = $FFFC
  Yabs = $FFF8
  Zabs = $FFF4
  Xorg = $FFF0
  Yorg = $FFEC
  Zorg = $FFE8
  StatusByte = $FFE4

OBJ
  i2c : "Basic_I2C_Driver"
  pst : "Parallax Serial Terminal"

VAR
  byte NewValue
  long EPSB, AbsPos[3], OrgPos[3], Wally
  
      
PUB initialize | x, pstCog, OK, ackbit

    pstCog := pst.Start( 115200 )                       
    pst.Clear
    pst.Beep
    pst.str(String(pst#NL, "Serial terminal running in: " ) )
    pst.dec( pstCog )

' Read EEPROM status byte
  EPSB := i2c.ReadByte(i2c#BootPin, i2c#EEPROM, StatusByte ) 
  pst.str(string(pst#nl, pst#nl, "EEPROM status byte is: %"))
  pst.bin( EPSB, 8 )

'  IF EPSB == 0
'    pst.str(string( pst#NL, "EEPROM status byte is not valid."))
'  ELSE
    pst.str(string( pst#NL, "Axis positions from EEPROM: X="))
    AbsPos[0] := i2c.ReadLong(i2c#BootPin, i2c#EEPROM, XAbs )  
    pst.dec( AbsPos[0] )
     
    AbsPos[1] := i2c.ReadLong(i2c#BootPin, i2c#EEPROM, YAbs )  
    pst.str(string("  Y="))
    pst.dec( AbsPos[1] )
            
    AbsPos[2] := i2c.ReadLong(i2c#BootPin, i2c#EEPROM, ZAbs )  
    pst.str(string("  Z="))
    pst.dec( AbsPos[2] ) 

    pst.str(string( pst#NL, "Axis origin positions from EEPROM: X="))
    OrgPos[0] := i2c.ReadLong(i2c#BootPin, i2c#EEPROM, XOrg )  
    pst.dec( OrgPos[0] )
     
    OrgPos[1] := i2c.ReadLong(i2c#BootPin, i2c#EEPROM, YOrg )  
    pst.str(string("  Y="))
    pst.dec( OrgPos[1] )
            
    OrgPos[2] := i2c.ReadLong(i2c#BootPin, i2c#EEPROM, ZOrg )  
    pst.str(string("  Z="))
    pst.dec( OrgPos[2] ) 


' Write final position locations to EEPROM.
  AbsPos[0] := 12345
  i2c.WriteLong(i2c#BootPin, i2c#EEPROM, XAbs, AbsPos[0] )
  i2c.WriteWait(i2c#BootPin, i2c#EEPROM, XAbs )
  
  AbsPos[1] := 678
  Wally :=1357
  i2c.WriteLong(i2c#BootPin, i2c#EEPROM, YAbs, AbsPos[1] )  
  i2c.WriteWait(i2c#BootPin, i2c#EEPROM, YAbs )
  pst.str(string(pst#nl, "  New Y="))
  pst.dec( AbsPos[1] )
  
  AbsPos[2] := 91011
  i2c.WriteLong(i2c#BootPin, i2c#EEPROM, ZAbs, AbsPos[2] )
  i2c.WriteWait(i2c#BootPin, i2c#EEPROM, ZAbs )

' Write final position locations to EEPROM.

  i2c.WriteLong(i2c#BootPin, i2c#EEPROM, XOrg, OrgPos[0] )
  i2c.WriteWait(i2c#BootPin, i2c#EEPROM, XOrg )

  i2c.WriteLong(i2c#BootPin, i2c#EEPROM, YOrg, OrgPos[1] )  
  i2c.WriteWait(i2c#BootPin, i2c#EEPROM, YOrg )

  i2c.WriteLong(i2c#BootPin, i2c#EEPROM, ZOrg, OrgPos[2] )
  i2c.WriteWait(i2c#BootPin, i2c#EEPROM, ZOrg )

  EPSB := %10101010
  i2c.WriteLong(i2c#BootPin, i2c#EEPROM, StatusByte, EPSB )
  i2c.WriteWait(i2c#BootPin, i2c#EEPROM, StatusByte )

  pst.str(string(pst#nl, "AbsPos values written to EEPROM"))   
' Write final position locations to SC card
      
    pst.str(String(pst#NL, pst#NL, "All done." ) )


Here is the result displayed on the serial terminal screen:

[IMG][/img]
EEPROM Problem.jpg

[\IMG]
561 x 396 - 76K

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2012-06-19 21:31
    Your code looks ok. The only thing I could think of that would behave the way you describe would that the bytes from $FFF8 to $FFFB won't program for some reason. The erased state of the EEPROM is all one bits, so they would be read as -1. One easy way to tell would be to change all your addresses from $FFEx and $FFFx to $FFCx and $FFDx, then see what happens.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-06-19 21:35
    This method of having to specify a fixed address for a variable in EEPROM is redundant as Spin variables are embedded within the image that is loaded from EEPROM on boot, all you need to do is to modify that variable at it's location in EEPROM and automatically it is loaded on boot. Where's that location? Not a mystery. Use i2c.WriteLong(@myvariable,myvariable) to change the default variable and it will automatically be restored at boot.
  • msrobotsmsrobots Posts: 3,709
    edited 2012-06-19 21:41
    Hi Peter,

    you got me there - this is brilliant simple. Never thought of it. I really like it.

    Thank you

    Mike
  • MJHanaganMJHanagan Posts: 189
    edited 2012-06-20 04:00
    I fiddled with the code and it turns out I was using the "i2c.WaitWrite" routine incorrectly. I assumed it returned one the current write operation was complete but this is not the case. It immediately returns a value of 1 (if the EEPROM is busy - like still writing) or a 0 when the write operation is completed. Once I put in the
    REPEAT UNTIL i2c.WriteWait(i2c#BootPin, i2c#EEPROM, Addr ) == 0
    
    line it now waits for the write operation to complete before the read occurs so now it works fine. It seems the write operation takes a whopping 5 msec to complete (much, much slower than I expected).
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
    OBJ
      i2c : "Basic_I2C_Driver"
      pst : "Parallax Serial Terminal"
          
    PUB initialize | EEPROM, Addr, StepAddr
    
        pst.Start( 115200 )                       
        pst.Clear
        pst.Beep
    
        StepAddr := 4
        Addr := $FFFF - 3  
         
        REPEAT 20
         
          pst.str(string( pst#nl, "Addr: $"))
          pst.hex( Addr, 4 )
           
          EEPROM := i2c.ReadLong(i2c#BootPin, i2c#EEPROM, Addr )
          pst.str(string( "  Initial read: $"))
          pst.hex( EEPROM, 4 )
           
          pst.str(string( "  Writing: "))
          pst.hex( Addr, 4 )
           
          i2c.WriteLong(i2c#BootPin, i2c#EEPROM, Addr, Addr )
          ' used to be: i2c.WriteWait(i2c#BootPin, i2c#EEPROM, Addr )
          REPEAT UNTIL i2c.WriteWait(i2c#BootPin, i2c#EEPROM, Addr ) == 0
           
          EEPROM := i2c.ReadLong(i2c#BootPin, i2c#EEPROM, Addr )
          pst.str(string( "  After write: "))
          pst.hex( EEPROM, 4 )
         
          Addr -=StepAddr
           
    
          
      pst.str(String(pst#NL, pst#NL, "All done." ) )
    
    

    to this:
    
    
    and now everything is working as expected.

    If the write operation is busy this routine returns a value of 1. When the write operation is done it returns a value of 0.
  • MJHanaganMJHanagan Posts: 189
    edited 2012-06-20 04:06
    I need to store a few values in EEPROM so they doen't get over written when Spin load new code into the EEPROM. Since the lower 32k are for Spin I am using location in the upper 32k range. So I assume the i2c.WriteLong(@myvariable,myvariable) won't work here since no variable could have an address greater than $7FFF. Is that correct?
  • Mike GreenMike Green Posts: 23,101
    edited 2012-06-20 05:18
    The "trick" that Peter mentioned won't work when the Propeller Tool downloads new code into the EEPROM. You'll have to use EEPROM past 32K for that as you're doing.
  • MJHanaganMJHanagan Posts: 189
    edited 2012-06-20 08:09
    Thanks for the help with this little problem!
Sign In or Register to comment.