Shop OBEX P1 Docs P2 Docs Learn Events
EEPROM write/read issues — Parallax Forums

EEPROM write/read issues

Martin HebelMartin Hebel Posts: 1,239
edited 2007-10-22 23:53 in Propeller 1
Hi all,
I'm making some additions to BS2_Functions, including write/read for EEPROM, both in code space and upper 32K. In theory I've seen on the board if you write to a variables EEPROM address,
on reboot it will hold that value. In testing, I use F11 to save the code without the write, use F10 to save with the write, then reload. In the code below neither X (reading the address from EEPROM) nor t1, the variable, holds my data (though the write then read does when F10ing)

VAR
    Long stack1[noparse][[/noparse]50]          ' Stack for 2nd BS2 Cog

    long t1,  x
OBJ

BS2 : "BS2_Functions"    ' Create BS2 Object


PUB Start 
    BS2.start (31,30)        ' Initialize BS2 Object timing, Rx and Tx pins for DEBUG
    BS2.Pause(2000)
    bs2.debug_str(string("Writing....",13))
'    BS2.write_CodeMem(@t1, 456_789, 4)
    BS2.Pause(1000)
    bs2.debug_str(string("Reading....",13)) 
    x := BS2.Read_CodeMem(@t1, 4)
    BS2.Debug_Dec(t1)
    BS2.DEBUG_CR
    BS2.Debug_Dec(x)
    BS2.DEBUG_CR    
    repeat




Here is the actual methods, thanks for any help understanding or with code issues.

Pub Write_CodeMem(address, value, size)

    write_Code(address,value, size, 1)

Pri Write_Code(address, value, size, inc) | SDA, SCL, ack, i

{
Thanks to:
Paul B. Voss
Assistant Professor
Picker Engineering Program
Smtih College  
}
    SCL := 28
    SDA := 29

    size--
    
    repeat i from 0 to size 
      outa[noparse][[/noparse]SCL]~~
      dira[noparse][[/noparse]SCL]~~
      dira[noparse][[/noparse]SDA]~
      outa[noparse][[/noparse]SDA]~
      dira[noparse][[/noparse]SDA]~~
      shiftout(SDA, SCL, %10100000, MSBFIRST, 8)
      dira[noparse][[/noparse]SDA]~
      ack := shiftin(SDA, SCL, LSBPRE, 1)
      shiftout(SDA, SCL, address >> 8, MSBFIRST, 8)
      dira[noparse][[/noparse]SDA]~
      ack := shiftin(SDA, SCL, LSBPRE, 1)
      shiftout(SDA, SCL, address, MSBFIRST, 8)
      dira[noparse][[/noparse]SDA]~
      ack := shiftin(SDA, SCL, LSBPRE, 1)
      shiftout(SDA, SCL, value >> (i*8), MSBFIRST, 8)
      dira[noparse][[/noparse]SDA]~
      ack := shiftin(SDA, SCL, LSBPRE, 1)
      outa[noparse][[/noparse]SDA]~
      dira[noparse][[/noparse]SDA]~~
      outa[noparse][[/noparse]SCL]~~
      dira[noparse][[/noparse]SDA]~
      address += inc
      waitcnt(clkfreq/200 + cnt)

Pub Read_CodeMem(address, size)

    return read_Code(address, size,1)
    
Pri Read_Code(address, size, inc) : value | SDA, SCL, ack, i, temp
{
 Thanks to:
 Paul B. Voss
 Assistant Professor
 Picker Engineering Program
 Smtih College
}
   
    SCL := 28
    SDA := 29
    size--
    value~
    
    repeat i from 0 to size
      dira[noparse][[/noparse]SCL]~~
      outa[noparse][[/noparse]SCL]~~
      dira[noparse][[/noparse]SDA]~
      outa[noparse][[/noparse]SDA]~
      dira[noparse][[/noparse]SDA]~~
      shiftout(SDA, SCL, %10100000, MSBFIRST, 8)
      dira[noparse][[/noparse]SDA]~
      ack := shiftin(SDA, SCL, LSBPRE, 1)
      shiftout(SDA, SCL, address >> 8, MSBFIRST, 8)
      dira[noparse][[/noparse]SDA]~
      ack := shiftin(SDA, SCL, LSBPRE, 1)
      shiftout(SDA, SCL, address, MSBFIRST, 8)
      dira[noparse][[/noparse]SDA]~
      ack := shiftin(SDA, SCL, LSBPRE, 1)
      dira[noparse][[/noparse]SCL]~~
      outa[noparse][[/noparse]SCL]~~
      dira[noparse][[/noparse]SDA]~
      outa[noparse][[/noparse]SDA]~
      dira[noparse][[/noparse]SDA]~~
       shiftout(SDA, SCL, %10100001, MSBFIRST, 8)
      dira[noparse][[/noparse]SDA]~
      ack := shiftin(SDA, SCL, LSBPRE, 1)
      dira[noparse][[/noparse]SDA]~
      temp := shiftin(SDA, SCL, MSBPRE, 8)
      value := value + (temp << (i*8))
      ack := shiftin(SDA, SCL, LSBPRE, 1)
      outa[noparse][[/noparse]SDA]~
      dira[noparse][[/noparse]SDA]~~
      outa[noparse][[/noparse]SCL]~~
      dira[noparse][[/noparse]SDA]~
      debug_ihex(address,4)
      debug_CR
      address += inc


▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
StampPlot - GUI and Plotting Software
Southern Illinois University Carbondale, Electronic Systems Technologies

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2007-10-22 16:50
    Martin,
    I would strongly suggest you incorporate an existing EEPROM package like the "Basic I2C Driver", either by including it as an object and exporting its useful public methods in some kind of "wrapper" or by incorporating its code directly. It's already debugged and documented and may be a little more efficient than the routines you posted since the code is specific to I2C and EEPROM access. For example, you re-address the EEPROM for every byte transferred while the "Basic I2C Driver" just sends an initial address, then uses the EEPROM's internal address counter for successive bytes. I'll have a more detailed look at this code and let you know what I see.
    Mike
  • hippyhippy Posts: 1,981
    edited 2007-10-22 17:12
    @ Martin : I had problems when writing my own I2C driver ( wanted to automatically handle page-boundary crossing on array writing ).

    The best approach is to start with a proven and debugged I2C object as Mike suggests and get your code working with a single byte variable.

    Then create your own I2C object, write your I2C Byte Write routine and get it debugged using the known working object ( any errors will be in your write routines ). Next add your own I2C Byte Read routine and get that working ( any errors will be in your read routine ).

    Do it a step at a time and you will end up with a complete I2C object of your own. You can always fall back on using the proven object to verify as you go along.
  • Beau SchwabeBeau Schwabe Posts: 6,559
    edited 2007-10-22 17:12
    Martin,

    I would take a closer look at your START/STOP conditions for the READ and WRITE functions.

    First, the START conditions that you have for both READ and WRITE are different from one another.

    Assuming that the SCL is driven, and the SDA uses a pull up (except through the shiftout) you should make sure that the lines after the SHIFTOUT's that read...

    dira[noparse][[/noparse]SDA]~

    ... So that it reads...

    dira[noparse][[/noparse]SDA]~
    Outa[noparse][[/noparse]SDA]~

    ...This defaults them to a LOW when they are driven or made outputs, just in case the SHIFTOUT routine leaves them in an unpredictable state.

    Edit
    Outa[noparse][[/noparse]SDA]~··· ... Should also be initialized somewhere at the beginning of the I2C routines (within the START perhaps) as to pre define the I/O to be LOW when it is made an OUTPUT.





    For a STOP condition, the i2c bus is basically looking for the SCL to make a
    transition from LOW to HIGH followed by the SDA making a transition from LOW to HIGH.

    I would change the STOP condition in both cases that currently reads...

    outa[noparse][[/noparse]SDA]~
    dira[noparse][[/noparse]SDA]~~
    outa[noparse][[/noparse]SCL]~~
    dira[noparse][[/noparse]SDA]~

    ...So that they read...

    Edit ... Since the SDA line isn't Driven HIGH (uses a pullup resistor) the START code needed to change slightly.

    'Note: The order is important here...
    '····· We want the SCL to go LOW before the SDA otherwise we would generate a potential START condition when we want to generate a STOP.

    outa[noparse][[/noparse]SCL]~······················· 'Make SCL LOW (driven)
    dira[noparse][[/noparse]SDA]~~····················· 'Make SDA LOW (driven)

    '····· Here is where we want the·STOP condition (after BOTH SDA and SCL are LOW)

    outa[noparse][[/noparse]SCL]~~··················· 'Make SCL HIGH (driven)
    dira[noparse][[/noparse]SDA]~······················ 'Make SDA HIGH (through pullup)





    Similarly I would do the same for the START condition.

    For a START condition, the i2c bus is basically looking for the SDA to make a
    transition from HIGH to LOW followed by the SCL making a transition from HIGH to LOW.

    I would change the START condition in both cases so that it reads...

    Edit ... Since the SDA line isn't Driven HIGH (uses a pullup resistor) the STOP code needed to change slightly.

    'Note: The order is important here...
    ····· We want the SDA to go HIGH before the SCL otherwise we would generate a potential STOP condition when we want to generate a START.
    ·
    dira[noparse][[/noparse]SDA]~····················· 'Make SDA HIGH (through pullup)
    outa[noparse][[/noparse]SCL]~~···················· 'Make SCL HIGH (driven)

    '····· Here is where we want the·START condition (after BOTH SDA and SCL are HIGH)
    dira[noparse][[/noparse]SDA]~~···················· 'Make SDA LOW (driven)
    outa[noparse][[/noparse]SCL]~····················· 'Make SCL LOW (driven)







    Good I2C reference...
    http://www.esacademy.com/faq/i2c/index.htm

    I2C Start/Stop Conditions...
    http://www.esacademy.com/faq/i2c/busevents/i2cstast.htm







    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.

    Post Edited (Beau Schwabe (Parallax)) : 10/22/2007 7:56:21 PM GMT
  • Fred HawkinsFred Hawkins Posts: 997
    edited 2007-10-22 18:22
    Nice link, Beau.
  • Martin HebelMartin Hebel Posts: 1,239
    edited 2007-10-22 18:55
    Thanks Mike and Beau,
    Trying to keep the code all in one object, and working with someone else on this. It seemed to be all working fine except the variable write/read.

    Beau, on the part below, could you look that over once, it's the same as the STOP, and I want to be sure it wasn't a copy/paste mishap.

    Mike, understand it would be faster to stream the data once connected, but in one circumstance it has to write backwards in memory.

    Thanks,
    Martin
    Beau Schwabe (Parallax) said...
    Martin,
    Similarly I would do the same for the START condition.

    For a START condition, the i2c bus is basically looking for the SDA to make a
    transition from HIGH to LOW followed by the SCL making a transition from HIGH to LOW.

    I would change the STOP condition in both cases so that it reads...

    outa |= 1<<SDA|1<<SCL 'Simultaneously make SDA and SCL HIGH
    dira[noparse][[/noparse]SDA]~~ 'Make SDA LOW (driven)
    outa[noparse][[/noparse]SCL]~ 'Make SCL LOW (driven)
  • Martin HebelMartin Hebel Posts: 1,239
    edited 2007-10-22 19:02
    Thanks also Hippy, sorry, yeah, might start using Mike's to piece it together. I've got today to see if I can get this going, then I'll have to put it on hte back burner for a while.

    -Martin
  • Martin HebelMartin Hebel Posts: 1,239
    edited 2007-10-22 19:16
    OK, got it working here, (though can still use Beau's response on that one post), the code worked as it was though I'll try to integrate the changes.

    The issues was the version on EEPROM to read the address was a little different than the one to write to it with f10, thus my address was changing. I watched the address being used for hours and didn't notice it.

    Changing the test routing helped!!

    One of those "oh Smile!" moments....

    Martin
  • Beau SchwabeBeau Schwabe Posts: 6,559
    edited 2007-10-22 19:17
    Martin Hebel,

    See my edit for the STOP, and why the Edit was necessary.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • Martin HebelMartin Hebel Posts: 1,239
    edited 2007-10-22 19:23
    Thanks Beau,

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    StampPlot - GUI and Plotting Software
    Southern Illinois University Carbondale, Electronic Systems Technologies
  • Mike GreenMike Green Posts: 23,101
    edited 2007-10-22 19:29
    Martin,
    The timing for reading bits from the I2C device is not right in your code. The SHIFTIN routine reads the input pin, then puts out a clock pulse which is correct for SPI, but I2C requires the input pin to be sampled while the clock pulse is high. It may work with some devices to sample first, then clock the device, but it's not the way I read the I2C specs and examples in various datasheets and may not work in some circumstances.
  • Martin HebelMartin Hebel Posts: 1,239
    edited 2007-10-22 20:20
    Thank Mike,
    Still integrating Beau's suggestions, but modified the code to stream on write/read (took care of the backwards issue by backing off by size) and adjusted the SHIFIN, though my clock times could be cleaner probably.

    Also, on the repeat, tyring to figure out what should be in the repeat loop, seems to work as is, but having the stop in there makes me think it shouldn't be. I'll dig through the data sheets shortly.


    Pri Read_Code(address, size) : value | SDA, SCL, ack, i, temp
    {
     Thanks to:
     Paul B. Voss
     Assistant Professor
     Picker Engineering Program
     Smith College
    }
       
        SCL := 28
        SDA := 29
        size--
        value~
        
       
          dira[noparse][[/noparse]SCL]~~
          outa[noparse][[/noparse]SCL]~~
          dira[noparse][[/noparse]SDA]~
          outa[noparse][[/noparse]SDA]~
          dira[noparse][[/noparse]SDA]~~
          shiftout(SDA, SCL, %10100000, MSBFIRST, 8)
          dira[noparse][[/noparse]SDA]~
          ack := shiftin_I2C(SDA, SCL, 1)
          shiftout(SDA, SCL, address >> 8, MSBFIRST, 8)
          dira[noparse][[/noparse]SDA]~
          ack := shiftin_I2C(SDA, SCL, 1)
          shiftout(SDA, SCL, address, MSBFIRST, 8)
          dira[noparse][[/noparse]SDA]~
          ack := shiftin_I2C(SDA, SCL, 1)
    
          dira[noparse][[/noparse]SCL]~~
          outa[noparse][[/noparse]SCL]~~
          dira[noparse][[/noparse]SDA]~
          outa[noparse][[/noparse]SDA]~
          dira[noparse][[/noparse]SDA]~~
          repeat i from 0 to size
            shiftout(SDA, SCL, %10100001, MSBFIRST, 8)
            dira[noparse][[/noparse]SDA]~
            ack := shiftin_I2C(SDA, SCL, 1)
            dira[noparse][[/noparse]SDA]~
            temp := shiftin_I2C(SDA, SCL, 8)
            value := value + (temp << (i*8))
            ack := shiftin_I2C(SDA, SCL, 1)
            outa[noparse][[/noparse]SDA]~
            dira[noparse][[/noparse]SDA]~~
            outa[noparse][[/noparse]SCL]~~
            dira[noparse][[/noparse]SDA]~
    
    
    PRI SHIFTIN_I2C (Dpin, Cpin, Bits) : Value | InBit
    
        dira[noparse][[/noparse]Dpin]~                                            ' Set data pin to input
        outa[noparse][[/noparse]Cpin]:=0                                          ' Set clock low 
        dira[noparse][[/noparse]Cpin]~~                                           ' Set clock pin to output 
                                                    
           Value:=0
           REPEAT Bits                                        
              !outa[noparse][[/noparse]Cpin]                                    
              waitcnt(500 + cnt)
              InBit:= ina[noparse][[/noparse]Dpin]                              
              Value := (Value << 1) + InBit                    ' Add to  value shifted by position
              !outa[noparse][[/noparse]Cpin]
              waitcnt(500 + cnt)
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    StampPlot - GUI and Plotting Software
    Southern Illinois University Carbondale, Electronic Systems Technologies
  • edited 2007-10-22 22:01
    Martin,

    Why not just use the Propeller Eeprom object?

    http://forums.parallax.com/showthread.php?p=678271

    Andy

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Andy Lindsay

    Education Department
    Parallax, Inc.
  • edited 2007-10-22 22:11
    BTW, attached is a small object with methods that behave like the BASIC Stamp 2's WRITE and READ commands.· And, yes,·the Propeller Eeprom object·already does page writes and sequential reads.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Andy Lindsay

    Education Department
    Parallax, Inc.
  • Martin HebelMartin Hebel Posts: 1,239
    edited 2007-10-22 23:53
    Hi Andy,
    Thanks, Paul Voss had sent the code wondering if I'd like to incorporate it in the BS2_Functions, sounded like a good idea (and is to round out the library a little with some WRITE/READ functions), and except for my one big goof in extending and testing, it seemed good to go.

    -Martin

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    StampPlot - GUI and Plotting Software
    Southern Illinois University Carbondale, Electronic Systems Technologies
Sign In or Register to comment.