Shop OBEX P1 Docs P2 Docs Learn Events
cogstop and port settings — Parallax Forums

cogstop and port settings

What happens to port settings (DIRA and OUTA) when a cog gets stopped with cogstop? Will they get reset?

I could test this myself, of course, but perhaps somebody has already done this.

I have one cog running doing time critical I/O and another giving it instructions and watching that these get executed in time. If there is a problem talking to the attached device i just kill that cog and restart the task with cognew. Can it happen that the port setting of the stopped cog get stuck where they were at the time it got killed. cognew could select another cog and this would eventually be disturbed because the old cog has some port set to output and high.
If this is the case I will have to take care to start the same cog again.

Comments

  • Cluso99Cluso99 Posts: 18,066
    No. AFAIK the cogstop resets the DIRA and OUTA registers and pins.
  • Yes, DIRA and OUTA (and all the other special registers) get set to zero so a stopped cog has no influence on the actual state of the I/O pins.
  • Clock LoopClock Loop Posts: 2,069
    edited 2017-11-02 21:43
    When I have used one of the cogs to declare dira and outa settings, once I stopped that cog, my i/o that I set in that cog became unusable by other cogs in the same way.

    What Ive learned about the prop is never stop the cog that is doing:

    DIRA, unless you don't care about those pins anymore.

    If you need to work with those pins, don't control the dira with that cog only, do it with both the start cog and the one using it.

    If you control the dira with a nonstop cog, then if you set outa and dira with a different cog , then stop it, that output remains in the static state you last set with the cog you stopped, because the direction output of that pin is still controlled by another cog.

    When I stop cogs that control dira, my prop becomes Z, or an unkown pin out state, . In the microcontroller world, never expect the rest state of a cpu to be reliable in any way.

    ALWAYS set the state of your pins, 24/7, and make sure a repeat looping cog controls the dira also all the time.
    {Cog Management}
    
    
    CON
            _clkmode = xtal1 + pll16x                                               'Standard clock mode * crystal frequency = 80 MHz
            _xinfreq = 5_000_000
    
    
      pin1        =  0
      pin2        =  1
      pin3        =  2
      pin4        =  3
    
    
    
    VAR
      long  cogon[8], cog[8], pile[3000]   ' cog management      
      long  symbol
       
    OBJ
     
      
    PUB Start        'Remember this is the first cog.   1 cog used.
    
    '  PUT YOUR PIN DECLARATIONS HERE
    
    
        outa[pin1] := 0             'set pin state before you turn the output on.
        outa[pin2] := 0
    
        dira[pin1] := 1             'turn the output on. 
        dira[pin2] := 1
    
    
      cogon[0] := (cog[0] := cognew(RunOnce, @pile[100]) > 0)      'this sets pin1 to on and shuts the cog off, pin 1 will remain on because pins 1 dira was set in the Start cog.             1 cog used. 
    
      cogon[1] := (cog[1] := cognew(ZStateOutput, @pile[200]) > 0)     '       1 cog used.   This sets pin 3 to high and as an output.   Then shuts off, Z state, do not do this.
    
    
      cogon[2] := (cog[2] := cognew(KnownOffState, @pile[300]) > 0)          '  1 cog used.    This sets pin 4 to high and as an output.   Then sets pin 4 to an input. Then turns off.  
     
      'cogon[3] := (cog[3] := cognew(, @pile[400]) > 0)          
    
      'cogon[4] := (cog[4] := cognew(, @pile[500]) > 0)
      
      'cogon[5] := (cog[5] := cognew(, @pile[600]) > 0)    
                                     
      'cogon[6] := (cog[6] := cognew(, @pile[700]) > 0)    
    
    
    Repeat                 ' This keeps the main cog running.    
        waitcnt(100_000 + cnt)     'cpu wait   Don't run loops without wait counts of some value, or your prop wastes power, and hammers the ram.
        WatchDog
    
         
    PRI WatchDog
    
      outa[pin1] := 0                 'Blink Led on P0  
      waitcnt(80_000_000 + cnt)    
      outa[pin1] := 1                 'Blink Led on P0 
      waitcnt(80_000_000 + cnt)     
    
    
    PRI RunOnce
      dira[pin2] := 1
      outa[pin2] := 0                 'Blink Led on P0  
      waitcnt(80_000_000 + cnt)    
      outa[pin2] := 1                 'Blink Led on P0 
      waitcnt(80_000_000 + cnt)     
    
    PRI ZStateOutput   'do not do this
    
      outa[pin3] := 1        'set pin state before you turn the output on.
      
      dira[pin3] := 1       'keep this in the main cog that loops in the watchdog.
        
        
    PRI KnownOffState  'do not do this, but better than nothing.
     
      outa[pin4] := 1         'set pin state before you turn the output on.
      
      dira[pin4] := 1              'set as output keep this in the main cog that loops in the watchdog, not here.
      
      dira[pin4] := 0              'set as input keep this in the main cog that loops in the watchdog, not here.
      
        
    
    
    PUB stop
    
    
    '' Unload timer object - frees a cog
    
      if cogon[0]~                                          ' if object running, mark stopped
        cogstop(cog[0])
    
      if cogon[1]~                                          ' if object running, mark stopped
        cogstop(cog[1])
        
      if cogon[2]~                                          ' if object running, mark stopped
        cogstop(cog[2])
    
      if cogon[3]~                                          ' if object running, mark stopped
        cogstop(cog[3])
     
      if cogon[4]~                                          ' if object running, mark stopped
        cogstop(cog[4])
    
      if cogon[5]~                                          ' if object running, mark stopped
        cogstop(cog[5])
    
      if cogon[6]~                                          ' if object running, mark stopped
        cogstop(cog[6])
    
    DAT
    
    
  • Your program doesn't do what your comments describe. For example, WatchDog will blink the LED on pin1 as it's executed in cog 0, but RunOnce won't blink the LED on pin2 because its DIRA is set to zero (in cog 1). Similarly, ZStateOutput will briefly set pin3 to high (in cog 2) before stopping itself and setting pin3 to input. KnownOffState will run in cog3 and briefly set pin4 to high before setting it back to input mode then stopping itself.

    If you leave a cog running in a loop, it does continually use a little bit of power. This is usually an issue only if you're running off batteries and want to conserve as much power as possible. "hammers the ram" ... not really. Static RAM doesn't wear out like EEPROM might. It takes a little bit of power to read a RAM location ... again, only an issue if you're on battery power.

    The I/O pins do behave the way the documentation describes. Each cog has its own copy of DIRA and OUTA and they're wired together in a chain of OR gates. When a cog is stopped for any reason, its control registers are cleared to zero. When a cog starts to execute code, DIRA and OUTA are zero. If one or more cogs set a DIRA bit to 1, that I/O pin becomes an output set to the state of that cog's OUTA bit (zero by default). If one or more cogs that have a DIRA bit set to 1 also have their OUTA bit to 1, that I/O pin gets set high.
  • Mike is correct, of course. The program does exactly what you would expect, which has little in common with the comments.

    I connected each output to a 1K/1K divider. This biased them to 1.6, so you could actually tell when they were not being driven.

    The initial cog drives Pin1 from input to output low and then toggles (just like you would expect). It also drives pin2 low.

    The RunOnce cog doesn't do anything because it never sets any ones into its DIRA.

    The other two cogs produce a short pulse on their respective outputs which then become inputs when the cog stops.
    1202 x 684 - 91K
  • Clock LoopClock Loop Posts: 2,069
    edited 2017-11-02 21:21
    Mike Green wrote: »
    Your program doesn't do what your comments describe. For example, WatchDog will blink the LED on pin1 as it's executed in cog 0, but RunOnce won't blink the LED on pin2 because its DIRA is set to zero (in cog 1).


    There is no code that turns pin2 dira to 0 anywhere in the code at all.
    So your saying the default dira of the cog that runs runonce needs to set the dira to use the io, ALSO? (its set in the start cog)
    Wow, i thought the cog that launched from the start cog, can control any pins if the pins dira is already set in the start cog.

    Mike Green wrote: »
    Similarly, ZStateOutput will briefly set pin3 to high (in cog 2) before stopping itself and setting pin3 to input.

    That is the intent. To show that dropping pin3, and no cog is controlling it, because the dira was set in zstateoutput, not in start.
    Nor was the pin set to an input before exiting, and it probably should be.

    Mike Green wrote: »
    KnownOffState will run in cog3 and briefly set pin4 to high before setting it back to input mode then stopping itself.
    Again, this is the intent. To show that turning an output to an input before turning the cog off is better than nothing.

    Mike Green wrote: »
    If you leave a cog running in a loop, it does continually use a little bit of power. This is usually an issue only if you're running off batteries and want to conserve as much power as possible.
    Not saying it was more/less, just saying it uses power. Never said alot.
    Mike Green wrote: »
    "hammers the ram" ... not really. Static RAM doesn't wear out like EEPROM might.
    I never said anything about it "wearing out".
    What this is talking about, is when loops run as fast as they can, they access the ram locations more often, this introduces delays when other cogs are also accessing those same memory locations,

    why run loops at their max, when the variable you sample isn't expected to change that often? To catch it asap sure, but every thing has a limit to what is really needed.

    from my own experience, i find that putting wait delays helps other programs access those memory locations with less lag or delay.

    I find this when I make programs that use most of the cogs on a design, where the cogs all share the ram in the DAT section.

    Mike Green wrote: »
    It takes a little bit of power to read a RAM location ... again, only an issue if you're on battery power.
    Some designs are similar to battery power in that they can pull power from limited sources.
    It dosen't hurt to design optimally.
    Mike Green wrote: »
    The I/O pins do behave the way the documentation describes. Each cog has its own copy of DIRA and OUTA and they're wired together in a chain of OR gates. When a cog is stopped for any reason, its control registers are cleared to zero. When a cog starts to execute code, DIRA and OUTA are zero. If one or more cogs set a DIRA bit to 1, that I/O pin becomes an output set to the state of that cog's OUTA bit (zero by default). If one or more cogs that have a DIRA bit set to 1 also have their OUTA bit to 1, that I/O pin gets set high.

    Isn't that what my program shows?
    I wasn't saying anyone here was wrong.

    My intent was to show that dir settings should probably be set in the START cog.

    And it seems what I should have put is that dir settings should be in both locations.

    The start cog and the cog you want to work with.

  • Clock LoopClock Loop Posts: 2,069
    edited 2017-11-02 21:53
    The program does exactly what you would expect, which has little in common with the comments.


    If I had known it was gonna get a visual rendering, I would have added wait counts, the scale on that scope is in seconds and the only output you can see on it is the watchdog loop, the other cogs run too fast for you to see.


    And it seems what I should have said, and coded, initially, is dir settings should be in both locations.

    The start cog and the cog you want to work with.

    I will add it to the intitial code, making this the only change.
    This was added to the RunOnce cog
    dira[pin2] := 1
    

    The point being that the direction and output state of all pins used should really be controlled at all times in code (in the start cog) so you don't forget about the state of a pin.


    Uhh, a bit harsh on saying it has little to do with the ops comment, its all about dir registers, launching cogs, stopping them, and I actually am the only brave soul here to post some code, risking public hanging, so i would like to take the time for saying your welcome for making the effort and time to produce some example code. (pats self on back)
    Even if i did get it wrong. (a single line) Gosh, i think i would simply post the corrected code that someone was trying to do, instead of saying they offered no help, push it higher not lower?
    Ive been hung so many times i like the noose, yours is kinda soft. ;)
  • Except in a few contrived situations, it's not necessary to initialize OUTA and DIRA bits in any cog that's not explicitly using those I/O pins ... and it may misrepresent what's actually happening. Remember that it takes about 100us to start up a cog and the cog executing the COGINIT will regain control in roughly 1us (depends on the relative hub positions of the two cogs). How does the initializing cog know when to release the I/O pins without either waiting the longest initialization time or explicitly synchronizing with spawned cogs. If the intention is to do away with pull-up or pull-down resistors by having the initialization cog control output lines until other cogs can finish their initialization, what happens between the power-up reset and the point where the initialization code can set a known state?

    When a cog stops whether due to an explicit COGSTOP or simply running off the end of the method started by a COGINIT (or COGNEW), all control registers are zeroed including OUTA and DIRA. This effectively makes that cog disappear as far as the I/O circuitry is concerned. It is not necessary to explicitly set DIRA to zero.

    One of the nice features of the Propeller and Spin is the use of objects to encapsulate functions and their behavior. It's usually not necessary for a program making use of a UART object to know whether the object makes use of a cog to perform its functions. The main program's initialization routine has to know which method to call to initialize the object and let the object know which I/O pin(s) to use. The main program normally would not explicitly affect the associated DIRA or OUTA bits and would leave them as zeroes.
  • Clock Loop wrote:
    What this is talking about, is when loops run as fast as they can, they access the ram locations more often, this introduces delays when other cogs are also accessing those same memory locations, ...
    Accesses to hub RAM from a cog are not slowed by other cogs accessing the same -- or any other -- memory locations in the hub. Hub access is done strictly on rotating basis and is not altered by demand.

    -Phil
  • I would invite anyone to engineer a better example since i failed so badly.
  • Clock LoopClock Loop Posts: 2,069
    edited 2017-11-02 22:15
    Clock Loop wrote:
    What this is talking about, is when loops run as fast as they can, they access the ram locations more often, this introduces delays when other cogs are also accessing those same memory locations, ...
    Accesses to hub RAM from a cog are not slowed by other cogs accessing the same -- or any other -- memory locations in the hub. Hub access is done strictly on rotating basis and is not altered by demand.

    -Phil

    I am working with long sized variables, not sure if that changes the situation. Then I don't know why i see different behavior when I run a repeat loop with no delay versus a delay, the loop just checks a variable for a change.
    I guess the reason behind it is different, but the problem was fixed by not letting a repeat loop run unlimited while checking a long sized variable for any change.

  • @ClockLoop,

    stating that one should set up IO in the start Cog is completely WRONG. Get this thought out of your brain.

    Each COG needs to set up its DIRA and OUTA completely independent of a start COG or any other COG.

    In the OPPOSITE you should AVOID setting the same pins in different COGs, except for some rare cases for sharing pins by say multiple COG video-driver.

    Each COG has its OWN dira and outa, no other COG can change them.

    From the software side each COG has his own pins and can set them to input or output and if output hi or low.

    From the HW side all dira and outa are ORed together to finally drive the pin.

    That means that if ONE or MORE COGS set a pin to output the physical pin is output for those COGS, but still input for all others. They will read the actual value, but are not able to change it.

    Same goes for outa. If one (or more) COGS have set a pin to output, they can change the physical state, all other COGs can NOT change the physical state, just read it.

    And if ONE (or more) COG having the pin as output, is setting it HIGH, then it is HIGH, else it stays low.

    Usually you just use a pin by one COG so it does not matter, but if you use a pin as output from multiple COGS then it will be HIGH if one COG says so, else low.

    Enjoy!

    Mike
  • Mike GreenMike Green Posts: 23,101
    edited 2017-11-02 22:53
    Can't tell why you're observing different behavior with and without delays. You'd need to provide source code and specific described examples. Most of this timing stuff won't be present in Spin code because the interpreter overhead tends to swamp any real effects even though the interpreter is very efficient. You can see it in some assembly code. For example, one high resolution VGA driver in the Object Exchange uses 3 cogs to take turns building and outputting scan lines along with a 4th handling a cursor. The 3 cogs have to be initialized to the same time point (system clock value) then maintained in lock-step. They share the VGA I/O pins taking turns controlling them including turning over control to each cog's video generator. The main program doesn't touch that portion of its DIRA or OUTA registers nor its video generator. It simply tells the object which group of I/O pins to use and where in hub memory to find various buffers and variables.
  • Clock Loop wrote: »
    I would invite anyone to engineer a better example since i failed so badly.

    I got the idea that you were suggesting that terminated cogs somehow interfere with IO pins controlled by live cogs. Here is the first line of your first comment on this thread:

    When I have used one of the cogs to declare dira and outa settings, once I stopped that cog, my i/o that I set in that cog became unusable by other cogs in the same way.

    If I misunderstood your position, I apologize. Perhaps you could state your point differently.
    I would be happy to fiddle your program to demonstrate that the Prop behaves exactly as described.
  • Here is a zoomed in version of my original screen capture. I think it is pretty clear that your program works exactly as one would expect.
    1202 x 684 - 88K
  • I would be happy to fiddle your program

    I don't think hijackin this thread is so great, i return the ball with the direction that someone might make a program to demonstrate some dir behavior, forget about my program if you like make a new.

Sign In or Register to comment.