Shop OBEX P1 Docs P2 Docs Learn Events
Noob Question - cognew and the independance of cogs — Parallax Forums

Noob Question - cognew and the independance of cogs

coryco2coryco2 Posts: 107
edited 2011-02-12 11:18 in Propeller 1
I went through the Spin programming tutorial in the Propeller help, and got all excited about using cognew to run two of my Spin files simultaneously in separate cogs. I set up a main method like this:

CON

_clkmode = xtal1 + pll16x ' System clock settings
_xinfreq = 5_000_000


OBJ

MyFirstObject: "MyFirstSpinFile"
MySecondObject: "MySecondSpinFile"

VAR

LONG MyFirstObjectStack[2000]
LONG MySecondObjectStack[2000]

PUB Start

cognew (MyFirstObject, @MyFirstObjectStack)
cognew (MySecondObject, @MySecondObjectStack)


Both of the Spin objects are nowhere near 2000 longs; I just wanted to make sure they had PLENTY of stack space. Maddeningly, though, only the first object called in the Start method will run. If I switch around the two cognew lines, then the other object will run (i.e. so it's whichever is called first). Both objects contain repeat loops, but if they are running in separate cogs, they shouldn't have any effect on each other, should they? (They are not addressing any of the same I/O pins, nor using any of the same objects.)

Can anyone tell me what I am missing here?

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2011-01-29 18:05
    Basically you're passing an object to cognew when it should be a method. Before we go any further, I'm surprised that the code above compiles at all. I replaced the included objects with dummy objects and the compiler complains about the first cognew. So it would be useful if you could attach your complete source.
  • coryco2coryco2 Posts: 107
    edited 2011-02-05 14:59
    Oops, sorry. Actually, I do realize that you pass methods, not objects. My example should have read something like this:

    cognew (MyFirstObject.Init, @MyFirstStack)
    cognew (MySecondObject.Init, @MySecondStack)

    Both the actual objects compile separately just fine, they just don't seem to work when called simultaneously in separate cogs. Is there any way one cog can even interfere with another?
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-02-05 15:09
    You can't cognew a method in another object either. The way to do what you want is to have the init method in each one cognew a separate, internal method.

    -Phil
  • StefanL38StefanL38 Posts: 2,292
    edited 2011-02-05 15:20
    this will not work either.

    you can't use a construction like cognew(objectname.methodname,@Stack)

    it has to be cognew(methodname)

    or if you want to have the method in separate *.spin-files (=objects)

    the cognew-command has to be INSIDE of MyFirstObject.spin and MySecondobject.spin

    the standard for doing this is to have a method called "Start" inside every object-file

    then you start the new cog through

    MyFirstObject.Start

    MySecondobject.Start

    There is a special reason why the compiler allows online this way

    each cog has it's own pin-direction and output-register

    so if you would setup the IO-direction register in cog A
    and then try to set IO-pins high-low with cog B this will not work

    from the mainmenu inside the propeller-tool you can access the
    Propeller Education Kit Labs Fundamentals V1.1

    read chapter 6 "Objects that Launch Processes into Cogs" to get more information about how it is done

    Again this is a case of "the computer does ALWAYS exactly what you have coded"

    Only sometimes you haven't understand in detail yet what you have coded

    best regards

    Stefan

    P.S: a stack of 200 longs will do in most cases. The stack is NOT for storing your whole code. You just need place for the parameters of the called methods.
    The stackspace can increase if you do a lot of nested calls. As each parameter needs a long this isn't that much.
  • coryco2coryco2 Posts: 107
    edited 2011-02-05 15:51
    Ahhh...I see now. Thanks much for the help!
  • kuronekokuroneko Posts: 3,623
    edited 2011-02-05 16:33
    StefanL38 wrote: »
    you can't use a construction like cognew(objectname.methodname,@Stack)
    To be fair, you can use it provided you know what it does (i.e. starting a PASM cog).
  • coryco2coryco2 Posts: 107
    edited 2011-02-12 10:27
    Okay, you were all so helpful before, so let me ask a related question:

    Say I have processes running in three cogs, and I want each of them to be able to be able to arbitrarily modify or read the same set of variables. What is the most efficient way of coding this?
  • Mike GreenMike Green Posts: 23,101
    edited 2011-02-12 10:38
    Assuming that you're writing the routine in Spin, it's easiest to manage all three cogs in the same object. That way, the same variables are directly available to all three cogs. You'd have a variable area and start routine like this:
    VAR long stack1[30], stack2[30], stack3[30]
       long common1, common2[10]
    
    PUB start
       COGNEW(cog1Routine,@stack1)
       ' ...
       COGNEW(cog2Routine,@stack2)
       ' ...
       COGNEW(cog3Routine,@stack3)
       ' ...
    
    PUB cog1Routine
       if common1 > 2
       ' do something
    
    PUB cog2Routine
       repeat common1 from 1 to 10
          common2[common1] := common1 * common1
          ' do something else
    
    PUB cog3Routine
       if common1 == 5
       ' do something else too
    
    Remember that all 3 routines can access the variables at the same time.
  • coryco2coryco2 Posts: 107
    edited 2011-02-12 11:18
    Thanks, Mike. That is interesting. But what if the cogs are in different objects? Say I would like to be able to access/modify the value of the mouse button state variable in the Mouse.spin object from an object running in another cog? Would I set up a PUB method with a local variable in Mouse.spin that would receive the change as a call from the other cog and then modify the button state variable from within Mouse? (If that makes any sense.) Or is there a better approach?

    I also had a few questions about your example approach (i.e. all three cogs managed in the same object):
    Is it more efficient to combine my multi-cog objects into a single "super-object", or to keep them separated? I am guessing all the code starts out in the global RAM anyway, so it's six of one or half dozen of the other? And the cogs can't actually access any given variable at exactly the same time can they (i.e. two of them won't be trying to modify the same variable at once)? They would take turns via the hub?

    Finally (and I maybe should start a new thread--heh), is there a way to store a set of variables in the EEPROM that the cogs can modify, and will then retain those values through the next power cycle?

    Thanks again! :-)
Sign In or Register to comment.