Shop OBEX P1 Docs P2 Docs Learn Events
Secondary Cog will not start — Parallax Forums

Secondary Cog will not start

CountMurphyCountMurphy Posts: 19
edited 2013-08-12 16:57 in Propeller 1
I'm not sure what I'm doing wrong here. My main function looks like this:
      SC.Clear  'clears OLED Screen
      SC.ShowVideoCog 'supposed to launch new cog to animate screen
      gps.init  'turns on GPS
      gps.ProcessLocalDateTime(DST)  'parses GPS data
      waitcnt(clkfreq+cnt)
      SC.FadeOut  'turn screen off
      gps.kill   'turns off GPS

The cog code in question looks like this:
var
  long stack[20]

pub Init
  serial.init(5,4,9600)

pub ShowVideo
  MediaInit
  serial.tx($FF)
  serial.tx($BB)
  serial.tx($00)
  serial.tx($00)
  serial.tx($00)
  serial.tx($00)
  WaitForComplete

pub ShowVideoCog
  coginit(7,newCogSetup,@stack)

pub MediaInit
  serial.tx($FF)
  serial.tx($B1)
  WaitForComplete

pri newCogSetup
  ShowVideo

When ShowVideoCog is called from main, nothing happens on the screen, and the gps turns on. Nothing else happens after this. If I comment out gps.ProcessLocalDateTime(DST), the code should play the animation on the screen, turn the gps on, wait, turn the screen off and kill the GPS. What actually happens is the GPS turns on. Thats it. I tried running my video code without starting a new cog and it works just fine. I even tried to simply turn an LED off and on with the new cog and I get the same results. The entire program seems to stall and the led never blinks. I have tried both coginit and cog new with the same results.What am I doing wrong? I am compeltly out of ideas

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-08-12 13:15
    A stack size of 20 may be too small. Try a bigger stack.

    -Phil
  • CountMurphyCountMurphy Posts: 19
    edited 2013-08-12 13:16
    I tried upping it to 200, no change
  • Mike GreenMike Green Posts: 23,101
    edited 2013-08-12 13:33
    The other thing is that it's bad form to use COGINIT unless you know exactly how each specific cog is being used since COGINIT uses a specific cog for the new program while COGNEW looks for an unused cog and uses that (and reports back which one it used). Cog 7 may have been used for something else.

    Another thing is that each cog has its own set of I/O registers. One cog may have initialized DIRA so that a pin is an output, but another cog may have left it as the default (input). Even though the 2nd cog is sending data to OUTA, it doesn't make it out to the I/O pins.

    I don't understand why your program is so convoluted, but I'd suggest you simplify the use of multiple cogs first. Let library objects first be the only ones to start up new cogs, then think carefully about why you'd want or need to move a section of code into another cog. When you do that, you can first think about all the ramifications in terms of I/O usage, shared memory access, etc.
  • CountMurphyCountMurphy Posts: 19
    edited 2013-08-12 13:55
    Mike Green wrote: »
    The other thing is that it's bad form to use COGINIT unless you know exactly how each specific cog is being used since COGINIT uses a specific cog for the new program while COGNEW looks for an unused cog and uses that (and reports back which one it used). Cog 7 may have been used for something else.

    Another thing is that each cog has its own set of I/O registers. One cog may have initialized DIRA so that a pin is an output, but another cog may have left it as the default (input). Even though the 2nd cog is sending data to OUTA, it doesn't make it out to the I/O pins.

    I don't understand why your program is so convoluted, but I'd suggest you simplify the use of multiple cogs first. Let library objects first be the only ones to start up new cogs, then think carefully about why you'd want or need to move a section of code into another cog. When you do that, you can first think about all the ramifications in terms of I/O usage, shared memory access, etc.

    Originally, I was using cognew. When that didn't work I tried coginit. When that didnt work I posted here. Currently my program only uses 2 cogs (The main, one for the gps library and hopefully 3 if I can get this one working. I doubt cog 7 was being used).

    I did also try to reinialize the pins using the serial.init in the new cog (tried it before posting the original post). Again, nothing really happened.

    pri newCogSetup
      Init   
      ShowVideo
    
    How is the program convoluted? The way its setup now when I make any call to the screen functions, I need to wait for the complete signal from the OLED before I can continue. since my animation is about 10 seconds,there would be 10 seconds without the prop doing any acutal work with the GPS while the code waited on the OLED. I do of know a way around that, but why not just spin up an extra cog to play the animation while the other cogs do the real work? Or did I misunderstand your quote? Either way I will need to figure out how to start cogs properly for another task I have down the road.

    What would you do to make my code unconvoluted?
  • Mike GreenMike Green Posts: 23,101
    edited 2013-08-12 14:44
    First of all, you can't call from one cog to another. If you start up a 2nd cog and that cog calls a routine in some library object, it's the 2nd cog that's executing the library object routine. That can be a problem if that library object is using any of the cog's special registers or some common buffer. This is true for the serial routines you're using. If you call the serial routines from two separate cogs, the buffer pointers may get messed up unless you use a lock (semaphore) to guarantee that only one cog is accessing something at a time (LOCKxxx).

    You've only posted part of your program, so it's hard to figure out for sure which parts are being executed by one cog and which parts are being executed by the other cog. It may be that the animation needs to be done by a 2nd cog and that's the cog that needs to "own" the serial I/O routines. Alternatively, the serial.tx and serial.rx routines may need to be modified so they can be called by either of the two cogs without getting confused. It depends partly on what WaitForComplete does.
  • CountMurphyCountMurphy Posts: 19
    edited 2013-08-12 15:03
    Mike Green wrote: »
    First of all, you can't call from one cog to another. If you start up a 2nd cog and that cog calls a routine in some library object, it's the 2nd cog that's executing the library object routine. That can be a problem if that library object is using any of the cog's special registers or some common buffer. This is true for the serial routines you're using. If you call the serial routines from two separate cogs, the buffer pointers may get messed up unless you use a lock (semaphore) to guarantee that only one cog is accessing something at a time (LOCKxxx).

    You've only posted part of your program, so it's hard to figure out for sure which parts are being executed by one cog and which parts are being executed by the other cog. It may be that the animation needs to be done by a 2nd cog and that's the cog that needs to "own" the serial I/O routines. Alternatively, the serial.tx and serial.rx routines may need to be modified so they can be called by either of the two cogs without getting confused. It depends partly on what WaitForComplete does.

    That makes perfect sense, thank you. I am going to need to rethink this. Does spin have built in semaphore support, or is that something I will have to code by hand / get from a library?
  • Mike GreenMike Green Posts: 23,101
    edited 2013-08-12 16:22
    Look at the description of the LOCKxxx statements in the Propeller Manual. They let you check out and return a hardware semaphore, then use it to lock or release a resource. Remember to initialize the semaphore during your program's initialization. When you check one out, its initial state is not defined.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-08-12 16:25
    The main things you need to worry about (at least it's I what I mainly worry about) when using multiple cogs are the I/O pins.

    As Mike Green suggests, I think your serial object is causing the problem. Call "Init" from the same cog as the cog which will use the serial object. If it's something like SimpleSerial, you can't use if from multiple cogs. Many of the other serial driver can be used from multiple cogs but it's still a bad idea to do so.

    I generally try to have one cog take care of all the serial tasks. If more than one cog can use the serial driver they end up stepping on each other's output. If you do want to use if from multiple cogs, I know I have an example of using locks to keep the cogs from using the driver at the same time. If you'd like, I'll try to find an example.

    What objects are you using for you GPS stuff. When I started a GPS project about a year ago I was dismayed by the way serial objects were used within the GPS code I had found in the OBEX. Hopefully you found a better start place than I had.
  • msrobotsmsrobots Posts: 3,709
    edited 2013-08-12 16:28
    In the code at the top post you do not call SC.Init

    Enjoy!

    Mike
  • CountMurphyCountMurphy Posts: 19
    edited 2013-08-12 16:57
    @Duane Degn, yup, I was using simple serial. I think I'm going to have to rethink my process on the secondary cog anyhow. I can get away with using one cog for the wait animation if I tweak a few things. There is only one other instance I know I will need an extra cog for, but it doesn't use any serial library so I "should" be ok.

    I too wasn't thrilled with most of the gps objects I found. I Ended up using gps_io_mini and it works really well. The only link I could find for it was here: https://code.google.com/p/robot-chopper/source/browse/trunk/Analysis/Communications/RF+DAQ/Propeller+Program/GPS_IO_mini.spin?r=218

    If you have that example on locking I would love to read it.

    @Mike Green
    I will definetly read up on LOCKxxx. Thanks for your help!

    @msrobots, SC.Init is one of the first lines I call, though I didn't post any code that high up. Thanks anyway though :)
Sign In or Register to comment.