Shop OBEX P1 Docs P2 Docs Learn Events
Stumped - Basic_I2C_Driver — Parallax Forums

Stumped - Basic_I2C_Driver

TomSTomS Posts: 128
edited 2007-07-27 23:45 in Propeller 1
I can't seem to get Basic_I2C_Driver to work from another cog. My program hierarchy is as follows:

Main
--Basic_I2C_Driver
--Reconciler
----Basic_I2C_Driver

I can read from a seperate EEPROM just fine from Main but can't write from Reconciler. I see no evidence of any clock activity when Reconciler calls WritePage.

Here's my code.

{{Reconciler.spin}}
VAR
  Long  stack[noparse][[/noparse]32]
  Byte  cog, isChanged  
'##################################################################################################
OBJ
  i2c       : "Basic_I2C_Driver"
  PE4302    : "PE4302"
'##################################################################################################
PUB Start(nvPtr,ovPtr,pe4302le,i2cSCL,devAddr): Success
  Stop
  i2c.Initialize(i2cSCL)
  Success := (cog := cognew(Reconcile(nvPtr,ovPtr,pe4302le,devAddr), @stack) + 1)
'--------------------------------------------------------------------------------------------------    
PUB stop
  if cog
    cogstop(cog~ - 1)
'--------------------------------------------------------------------------------------------------    
PUB Active : YesNo
  YesNo := cog > 0
'--------------------------------------------------------------------------------------------------    
PUB Reconcile(nvPtr,ovPtr,pe4302le,addr24LC256) | temp, x
  repeat
    isChanged := False
    if (LONG[noparse][[/noparse]ovPtr][noparse][[/noparse]0] <> LONG[noparse][[/noparse]nvPtr][noparse][[/noparse]0])       ' Compare values
        LONG[noparse][[/noparse]ovPtr][noparse][[/noparse]0] := LONG[noparse][[/noparse]nvPtr][noparse][[/noparse]0]        ' Make equal if different
        isChanged := True                       ' Set flag
   
    if (LONG[noparse][[/noparse]ovPtr] <> LONG[noparse][[/noparse]nvPtr])       ' Compare values
        temp := LONG[noparse][[/noparse]nvPtr]                  ' Assign to temp so calculations can be done
        x := (temp/1000)*2 #> 0 <# 62           ' limit x to 0 - 62
        if  temp//1000                          ' if any remainder, add 1
          x += 1
        LONG[noparse][[/noparse]nvPtr] := x * 500               ' Mult by 500 to get value x 1000
        LONG[noparse][[/noparse]ovPtr] := LONG[noparse][[/noparse]nvPtr]        ' Make equal
        isChanged := True                       ' Set flag
        PE4302.SetAtten(pe4302le,x)             ' Set attenuation to new value
        
    if isChanged                                        ' Check if any variable has changed
      i2c.WritePage(0, addr24LC256, 0, nvPtr, 64)       ' Write page 0 if yes
      x := cnt                                          ' Store clock count in x
      repeat while i2c.WriteWait(0, addr24LC256, 0)     ' Repeat while busy or timeout
        if cnt - x > clkfreq/200                        ' 
          quit



I must be doing something wrong.

Tom

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2007-07-27 21:53
    You're running into several problems:
    1) In Reconciler, you're setting up I2C in one cog (the one running Start), but using I2C in the cog started in Reconciler.· There's a separate copy of the I/O registers for each cog and that may be part of what's going on.· Move the Initialize call into the beginning of Reconciler.

    2) You didn't include your Main program which presumably also calls I2C.· It may be that the two copies interfere with each other (try to access the same I2C bus and device at the same time).· Again, without the whole program, it's difficult to tell.

    3) This is one of those cases where you may need the semaphores (LOCKxxx) so that only one cog accesses the I2C bus at a time.· You may be able to solve this also by having only one cog do the actual I2C accesses in response to requests from the other cogs.· Usually, the I2C routines leave the I/O pins in input state when they're through with a transaction (as long as both SCL and SDA have pullup resistors).· That makes it easier for several cogs to share the bus.
    ·
  • deSilvadeSilva Posts: 2,967
    edited 2007-07-27 22:23
    Most likely (1) is the cause of the problem, but (2) is a possibilty. As BASIC_I2C does not use any static variables a fourth source of confusion (multiple instances) does not apply. So Mike's analysis is very complete.

    Note that sync issues Mike discusses under (3) do not have their root in having two instances of BASIC_I2C but in (possibly) using BASIC_I2C from two parallel running COGs.

    This is a fine example that you always have to distinguish and consider:
    - which instance of an object you are calling (different object data)
    - from which COG this does happen (different I/O register context)
  • TomSTomS Posts: 128
    edited 2007-07-27 22:26
    The Main program reads the EEPROM at startup and isn't used again. I've checked the state of SCL and SDA after the initial read and both are high (the last command before the retun value is set is STOP, which sets both pins to inputs).
    I've tried moving the Initialize call to inside Reconciler and it didn't help.
    There is only one device on the bus, that is the EEPROM, so bus contention shouldn't be an issue.
    I've attached my main program if it helps.

    Tom
  • TomSTomS Posts: 128
    edited 2007-07-27 22:33
    I just moved the Initialize call back into Reconciler. Now it works. I swear I've tried this at least three times (4th times the charm?)

    Tom
  • deSilvadeSilva Posts: 2,967
    edited 2007-07-27 23:45
    You are probably an "F10/F11 victim"; some reset re-activated the old version from the EEPROM
Sign In or Register to comment.