Stumped - Basic_I2C_Driver
TomS
Posts: 128
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.
I must be doing something wrong.
Tom
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
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.
·
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)
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
Tom