Shop OBEX P1 Docs P2 Docs Learn Events
coginit question — Parallax Forums

coginit question

n.borreron.borrero Posts: 16
edited 2008-08-07 00:36 in Propeller 1
for some reason, when i try to use coginit, if the function that coginit is calling has a repeat loop in it, then the main code won't continue until the loop in the other cog finishes. this seems to defeat the purpose so i'm obviously doing something wrong. any ideas?

as you can see i've tried both cognew and coginit



CON

  _clkmode = xtal1
  _xinfreq = 5_000_000

OBJ

  PWM: "PWM_beta_0_1"                                   'Object which controls PWM output
  PWMb: "PWM_beta_0_1_alt"

VAR

  long StackPWMa[noparse][[/noparse]100]                                   'Stack space for outputting PWM
  long StackPWMb[noparse][[/noparse]100]
  long StackPWMc[noparse][[/noparse]100]
  byte CogPWM                                        'Holds ID of cog running PWM
  long power
  
PUB Main

  dira[noparse][[/noparse]16..23]~~

  power := 20
  repeat
     repeat until ina

''   CogPWM := cognew(PWMb[noparse][[/noparse]0].Start(18, 50000, 50), @StackPWMb)
''   CogPWM := cognew(PWMb.Start(20, 500, 90), @StackPWMc)
''   CogPWM[noparse][[/noparse]0] := cognew(PWM.Start(16, 500, power), @StackPWMa)

     coginit(7, PWMb[noparse][[/noparse]0].Start(18, 50000, 50), @StackPWMb)
     coginit(6, PWMb.Start(20, 50000, 90), @StackPWMc)
     coginit(5, PWM.Start(16, 500, power), @StackPWMa)


Comments

  • AleAle Posts: 2,363
    edited 2008-08-06 08:45
    If you are trying to relaunch for every loop iteration... well that may have some problems... the could in the COGS 5, 6 and 7 will be reloaded and reloaded and so on. It seems confusing.. you know your are not just running some subroutine you are launching a new process in another processor.... and probably not letting execute far enough (it take something like 8192 clocks to launch a new cog)

    What do you want to achieve again ?....
  • n.borreron.borrero Posts: 16
    edited 2008-08-06 09:07
    after that code there's another part that stops the cog when you press a button. basically, each cog is just flashing an LED. i want each cog to control a different LED. PWM.Start(16, 500, power) means that it's gonna control the LED connected to port 16. i'll try adding pauses in between each coginit n see if that helps.
  • AleAle Posts: 2,363
    edited 2008-08-06 09:30
    Well, that may explain something... If you have push buttons connected to an input. push button (and any key for that matter) bounce so you may have to add some debounce software, for example you sample the key status periodically, let's say every 10 or 20 ms to see when it stays put for 2 or 3 cycles. When that happened you launch a new cog depending on which key was pressed. Debouncing keys... is nice smile.gif have a look at this code:

    c7_wait_key   
                  mov       k7_keys,INA
                  and       k7_keys,k7_cnt_keys
                  cmp       k7_keys,k7_cnt_keys   wz ' waits for a key
            if_z  jmp       #c7_wait_key5
                  mov       k7_tkeys,k7_keys
                  test      k7_kcnt,k7_kcnt   wz    ' is zero ?
            if_z  mov       k7_kcnt,#5
                  sub       k7_kcnt,#1   wz
            if_z  jmp       #c7_proc_key
    
    c7_wait_key5  
                  mov       k7_wait,CNT
                  add       k7_wait,k7_cnt_20ms
                  waitcnt   k7_wait,#0
                  jmp       #c7_wait_key
    
    
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-08-06 15:33
    As a general rule, if you're using coginit at all, you need to rethink your code. Although the command is available, it's use is almost universallly discouraged. If you need to launch a new process, use cognew. If what you need instead is a subroutine, define one as a public or private method and call it. But, please, just say "no" to coginit. It really doesn't have a legitimate purpose in Spin, and you're only courting trouble if you attempt to use it.

    -Phil

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    'Still some PropSTICK Kit bare PCBs left!
  • Paul BakerPaul Baker Posts: 6,351
    edited 2008-08-06 16:37
    Hi Phil, I know this is something that we have fostered (discouraging use of coginit). Do you feel this advice is generally followed? Have you come across any instances where coginit is truely needed? The reason I ask is we are working out the mechanics of certain aspects of the next chip, and one of those is coginit/cognew with the expanded memory pointers for code and data. Enabling the use of coginit requires 4 bits (8 cogs for coginit, + 1 bit to specify cognew/coginit), if there is no true need for coginit, those bits could be a possible candidate for repurposing.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Paul Baker
    Propeller Applications Engineer

    Parallax, Inc.

    Post Edited (Paul Baker (Parallax)) : 8/6/2008 4:49:44 PM GMT
  • Mike GreenMike Green Posts: 23,101
    edited 2008-08-06 16:52
    I've not found a use for COGINIT that a COGSTOP followed by a COGNEW wouldn't work just as well.
  • jazzedjazzed Posts: 11,803
    edited 2008-08-06 16:58
    PASM coginit use seems legitimate in at least one piece of code I've seen.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-08-06 17:00
    Paul,

    "Have you come across any instances where coginit is truely needed?"

    No, I really haven't. coginit requires knowledge of which cogs are in use and which are available. Since the Propeller contains such a great mechanism (cognew) that obviates the need for such knowledge, coginit is virtually deprecated out of the gate. Those times I've seen it used in forum queries, it's almost universally substituted for method calls, which is an inappropriate application.

    In general, it's better to think of cog IDs simply as non-numerical receipts that you get from cognew and that you can "turn in" for use with cogstop or designate as a source of FM audio for broadband video. Crossing the line into managing cogs by their actual number is a sure symptom that one's program needs to be refactored.

    I'm not saying that coginit should be deleted from Spin. It's too late for that, after all. But it might be helpful if the manual contained a warning block discouraging its use. I think it would save countless headaches and misapprehensions about what cogs are for and how they should be managed.

    -Phil

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    'Still some PropSTICK Kit bare PCBs left!

    Post Edited (Phil Pilgrim (PhiPi)) : 8/6/2008 5:51:36 PM GMT
  • BradCBradC Posts: 2,601
    edited 2008-08-06 20:39
    n.borrero said...
    for some reason, when i try to use coginit, if the function that coginit is calling has a repeat loop in it, then the main code won't continue until the loop in the other cog finishes. this seems to defeat the purpose so i'm obviously doing something wrong. any ideas?

    as you can see i've tried both cognew and coginit


    
         coginit(7, PWMb[noparse][[/noparse]0].Start(18, 50000, 50), @StackPWMb)
         coginit(6, PWMb.Start(20, 50000, 90), @StackPWMc)
         coginit(5, PWM.Start(16, 500, power), @StackPWMa)
    
    
    


    I always thought the method being started had to reside in the same object. You are trying to start methods in other objects. From memory this can do "funky things" and rarely what you intended.

    Experts, am I wrong?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pull my finger!
  • BradCBradC Posts: 2,601
    edited 2008-08-06 20:56
    To reply to myself.. it ain't ever gonna work like that.

    After checking the generated code, when an object is referenced in the cognew/coginit. Instead of generating a proper call stack the compiler calls the subroutine!
    Now this is pretty funky as if someone was clever they can use this to subvert the way cognew works.
    A working call from the same method
      Cognew(Fred(1,2),@CogStack)
    Method 1 Length 10 Address 0020 Stack 0008
    0:1 : 0020 : Constant 2 $00000001                          <-- Parm 1
    0:1 : 0021 : Constant Mask X=2 Y=0 00000002        <-- Parm 2
    0:1 : 0023 : Constant 2 Bytes - 02 02                      <-- Parameters (2) | Pub Method to call (2)
    0:1 : 0026 : Memory Op Long VBASE + ADDRESS Address = 0030 <-- Stack Pointer
    0:1 : 0028 : Run
    0:1 : 0029 : CogInit(Id, Addr, Ptr)
    
    A call that will fail from another object
      Cognew(test.Fred(1,2,3),@CogStack)
    0:1 : 0020 : Constant 0 $FFFFFFFF <-- Parm 1
    0:1 : 0021 : Drop Anchor Push                              <-- Setup to call
    0:1 : 0022 : Constant 2 $00000001                        <-- Parm 1
    0:1 : 0023 : Constant Mask X=2 Y=0 00000002      <-- Parm 2
    0:1 : 0025 : Constant Mask X=2 Y=33 00000003    <-- Parm 3
    0:1 : 0027 : Call Obj.Sub 3 1                                <-- Subroutine call into other object which will leave a value on the stack
    0:1 : 002A : Memory Op Long VBASE + ADDRESS Address = 0030 <-- Stack Pointer.
    0:1 : 002C : CogInit(Id, Addr, Ptr)
    
    
    



    Now this allows you to use a method in another object to select which method in the current object to call.
    You'd have to set up the methods with one parameter (which will always be passed $FFFFFFFF), but as long as you returned
    01XX from the object call, you could use XX to select which PUB method to call in the current object.

    All completely theoretical of course..


    Scratch that, I did not spot the missing "run" which builds the call stack and starts things up..
    No wonder it gets funky!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pull my finger!

    Post Edited (BradC) : 8/6/2008 9:03:26 PM GMT
  • BradCBradC Posts: 2,601
    edited 2008-08-06 21:06
    n.borrero said...
    for some reason, when i try to use coginit, if the function that coginit is calling has a repeat loop in it, then the main code won't continue until the loop in the other cog finishes.
    
         coginit(7, PWMb[noparse][[/noparse]0].Start(18, 50000, 50), @StackPWMb)
         coginit(6, PWMb.Start(20, 50000, 90), @StackPWMc)
         coginit(5, PWM.Start(16, 500, power), @StackPWMa)
    
    
    


    One last reply after looking at the code even closer.
    This will run the three lines in sequence while starting cogs 7,6&5 with garbage from whatever is roughly in the memory location returned by the PWM(x).Start routines..
    so you will see precisely the effect you are seeing..

    Try perhaps using helpers in the object you are calling from.. something like
    Pub Start7
    PWMb[noparse][[/noparse]0].Start(18, 50000,50)

    and launching it with
    coginit(7, Start7, @StackPWMb)

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pull my finger!
  • n.borreron.borrero Posts: 16
    edited 2008-08-06 21:29
    @BradC

    hey that worked! thanks a lot. i don't completely understand why it's different though. are you saying that is was retrieving commands from the wrong section of the memory er somethin?

    thanks.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-08-06 21:39
    Brad,

    I hate to sound like a broken record here, but writing a method in a separate object that uses coginit only compounds the issues with it that I noted above. At least if you use coginit in a top object, you might have some clue whether the cogs you're starting are even available. In a remote object, the chances of that are zilch — especially if you forget that the coginits are there and try to reuse the object later or, worse, distribute it to others.

    Again, just don't use coginit, period.

    -Phil

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    'Still some PropSTICK Kit bare PCBs left!
  • hippyhippy Posts: 1,981
    edited 2008-08-06 21:51
    Paul Baker (Parallax) said...
    Have you come across any instances where coginit is truely needed?

    Re-starting Cog 0 Spin interpreter having altered Hub memory ( eg, post-bootload fixups or to run
    a RAM Spin Interpreter ). That's only necessary though if the user's code does specify Cogs of their
    own assuming code will start in Cog 0. Of course there's no way to tell so Cog 0 has to be used.

    As long as it can be predicted when Cog 0 is about to be selected by a CogNew, even that's not a
    necessity, the re-launcher can issue CogNew and CogStop on dummy code until it gets access to
    Cog 0 it wants to use. Providing a user's program works the sane whether from vanilla boot or
    after post-fixup and re-launch it doesn't matter how it works, as long as it does.
  • BradCBradC Posts: 2,601
    edited 2008-08-06 22:29
    Phil Pilgrim (PhiPi) said...
    Brad,

    I hate to sound like a broken record here, but writing a method in a separate object that uses coginit only compounds the issues with it that I noted above. At least if you use coginit in a top object, you might have some clue whether the cogs you're starting are even available. In a remote object, the chances of that are zilch — especially if you forget that the coginits are there and try to reuse the object later or, worse, distribute it to others.

    Again, just don't use coginit, period.

    -Phil

    Don't disagree with you at all, but I'm not here to preach. I was simply pointing out why his original code would not work and what he could do to make it work.
    Personally I don't use coginit, but if someone else wants to use it I'm not going to beat them about the head with it.

    The reality of the problem the original poster was seeing has zero to do with coginit/cognew differences and everything to do with the compiler doing funky stuff when you pass it an object instead of a local method.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pull my finger!
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-08-06 22:30
    Hippy,

    Yup, come to think of it, I've used it for that myself. But, you're right: it's not strictly necessary. I've got a program that uses a coginit(0, @bootloader, 0) in Spin to lauch a bootloader on reset, and the bootloader issues a coginit interpreter. Both can be accomplished with a cognew (the second followed by a cogstop). Moreover, since the original Spin program vacates cog 0, that's probably where the interpreter will go when it's launched. But, frankly, that should never matter, as all code should be cog number agnostic.

    -Phil

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    'Still some PropSTICK Kit bare PCBs left!
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-08-06 23:21
    BradC said...
    Don't disagree with you at all, but I'm not here to preach.
    LOL! I guess you must think that's my job! smile.gif

    Seriously, I understand where you're coming from and didn't mean to criticize your answer — only to underscore some issues with the coginit approach, which has become a subtext of this thread.

    -Phil

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    'Still some PropSTICK Kit bare PCBs left!
  • n.borreron.borrero Posts: 16
    edited 2008-08-07 00:00
    i changed it back to cognew. the only reason i was even using coginit was because i couldn't get cognew to work.
  • hippyhippy Posts: 1,981
    edited 2008-08-07 00:21
    @ n.borrero : As your post got a little hijacked and side-tracked, in case you missed it ...
    BradC said...
    The reality of the problem the original poster was seeing has zero to do with
    coginit/cognew differences and everything to do with the compiler doing funky stuff when you
    pass it an object instead of a local method.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-08-07 00:36
    BradC, Hippy,

    Good point, and thanks for the refocusing. My critique centered as much on style as it did on substance. But the real meat of the matter, wich you correctly point out, is that there's something fishy going on in the compiler.

    n.borrero,

    Nonetheless, I'm glad you switched to cognew! smile.gif

    -Phil

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    'Still some PropSTICK Kit bare PCBs left!
Sign In or Register to comment.