Shop OBEX P1 Docs P2 Docs Learn Events
PASM Question: best practice for cog-to-cog data sharing — Parallax Forums

PASM Question: best practice for cog-to-cog data sharing

WossnameWossname Posts: 174
edited 2011-08-04 09:39 in Propeller 1
I'm beginning to learn assembly language programming for the Propeller chip.

My aim is to have one Cog periodically reading a set of 8 switches and writing those 8 bits to a byte in Cog ram. Then another Cog will periodically read this byte and act upon it accordingly (initially it will just display these bits on 8 LEDs, but later on it will do something more useful).

How do I decide what hub ram address would be appropriate for storing the data? I'm not sure what the syntax should be for declaring the address value and what that numerical value ought to be.

Comments

  • Heater.Heater. Posts: 21,230
    edited 2011-07-31 03:32
    You don't need to specify an address for that shared data. Just define it as a byte in a DAT or VAR section as appropriate and then pass the address of that byte to any other cogs that want to use it. Use the @ operator to get the hub address of the byte. Use PAR to get that address into your cog.
  • kuronekokuroneko Posts: 3,623
    edited 2011-07-31 04:08
    This [thread=132830]thread[/thread] may be of interest (including quirks and pitfalls).
  • StefanL38StefanL38 Posts: 2,292
    edited 2011-07-31 04:09
    COG-RAM is exclusive to each COG. Every Cog can't access another cog-ram.

    The usual way is to use HUB-RAM with the commands WRLONG and RDLONG
    There are some more methods to interchange data between cogs but they are more sophisticated.

    Therefore both cogs have to know which HUB-RAM-adress.
    Here is the actual end of my knowledge. @the PASM-experts How do you tell a cog started from another cog running PASM a HUB-RAM-adress?
    My first idea is to use a fixed and - through a hardcoded value adressable HUB-RAM-long at the upper end of the HUB-RAM.

    keep the questions coming
    best regards

    Stefan
  • kuronekokuroneko Posts: 3,623
    edited 2011-07-31 04:14
    StefanL38 wrote: »
    @the PASM-experts How do you tell a cog started from another cog running PASM a HUB-RAM-adress?
    By specifying par as usual. The coginit parameter (dst) is layed out as follows: dst[31..18]: par/4n, dst[17..4] code address/4n, dst[3]: new/init, dst[2..0]: cogid. See PM page 284.
  • StefanL38StefanL38 Posts: 2,292
    edited 2011-07-31 05:40
    Hi kuroneko,

    thank you very much for direct answering me this - even if - me myself - sometimes emphasise on others "info can be found at ...." or just writing guiding questions.

    best regards

    Stefan
  • WossnameWossname Posts: 174
    edited 2011-08-01 10:56
    Hi guys, thanks for the help.

    I'm still having a bit of trouble making this work though.

    This will be difficult to explain but I'd be grateful if someone could glance over my code and see if they can spot some obvious mistakes I've made...
    CON 
      _clkmode = RCFAST
    
    
    VAR
      byte HUBRAM_DIPSWITCH_VALUE_ADDRESS
    
    PUB Main 
    
      coginit(1, @ShiftIn, @HUBRAM_DIPSWITCH_VALUE_ADDRESS)       'begin polling inputs and updating the hub ram byte
      coginit(0, @ShiftOut, @HUBRAM_DIPSWITCH_VALUE_ADDRESS)      'do cog 0 last otherwise the other cogs won't get assigned 
      
    
    DAT
           
     
                  org       0
                                                         
    ShiftOut  ''''''''''''''''''''''''''''''''''''''''''''''''''''''
                  mov       shiftDataOUT, par                            
                  mov       dira, #0
                  or        dira, SCLR_Pin 
                  or        dira, SCK_Pin 
                  or        dira, G_Pin   
                  or        dira, SI_Pin  
                  or        dira, RCK_Pin
                  mov       outa, #0 
                                  
                  mov       timeOUT, cnt       
                  add       timeOUT, #15
    
    :mainloop     waitcnt   timeOUT, delayOUT
    
                  rdbyte    valueOUT, shiftDataOUT
    
                  mov       bitcount, #8
                  or        outa, G_Pin             'set high - disables outputs on shift register (all leds off)
                  andn      outa, SCLR_Pin          'set low - clears shift register
                  or        outa, SCLR_Pin          'set high again to allow data to be shifted in
    
    :bitloop      rcr       valueOUT, #1 WC         'put the bit we want to shift out into the C flag
                  muxc      outa,  SI_Pin           'put the C flag onto the SI_Pin        
                  or        outa, SCK_Pin           'clock the bit into the shift register
                  andn      outa, SCK_Pin           'reset the clock ready for the next bit
                  djnz      bitcount, #:bitloop
    
                  or        outa, RCK_Pin           'set high - move shifted in bits to the storage register
                  andn      outa, RCK_Pin           'set low - reset the storage register pin
    
                  andn      outa, G_Pin             'set low - enables outputs on shift register (leds should display the binary bits)
    
                  waitcnt   timeOUT, delayOUT
                  xor       outa, G_Pin
                  
                  jmp       #:mainloop
                                       
    
    delayOUT      long      3_000_000
    SCLR_Pin      long      |< 0
    SCK_Pin       long      |< 1
    G_Pin         long      |< 2
    SI_Pin        long      |< 3
    RCK_Pin       long      |< 4                                  
    timeOUT       res       1
    valueOUT      res       1    
    bitcount      res       1
    shiftDataOUT  res       1
    
    
                  FIT
    
    
    
    
                  
    
                                   
    
                  org       0
                  
    ShiftIn  ''''''''''''''''''''''''''''''''''''''''''''''''''''''
                  mov       shiftDataIN, par
                  mov       valueIN, #0
                  mov       timeIN, cnt       
                  add       timeIN, #15
                  
    :mainloop     waitcnt   timeIN, delayIN
                  add       valueIN, #1                     '<---- something wrong here, the LEDs just flash 1 all the time, it never changes 
                  wrbyte    valueIN, shiftDataIN
                         
                  jmp       #:mainloop                       ' looks like valueIN gets reset to zero somehow?!?!
    
    
    shiftDataIN   res       1  
    delayIN       long      3_000_000
    timeIN        res       1
    valueIN       res       1
    
                  FIT
                  
    



    The shift register control code works well, I'm happy that it's showing the values it should be. However the wdbyte and rdbyte usage is probably broken and I'm not sure how.

    Also the loop in the ShiftIn routine doesn't do what I expect. I'd expect it to continually increment valueIN... 0, 1, 2, 3, 4, etc etc, but the LEDs on my shift register just flash 1 all the time, and it never changes from 1.

    I'm unsure about the usage of "@" in all this business.

    Any ideas guys?
  • AribaAriba Posts: 2,690
    edited 2011-08-01 12:36
    [B]shiftDataIN   res       1[/B]  
    delayIN       long      3_000_000
    timeIN        res       1
    valueIN       res       1
    

    The res must stay after the delayIN long. As you have it now, the shiftDataIN gets the value 3_000_000 and not the delayIN register.

    Andy
  • StefanL38StefanL38 Posts: 2,292
    edited 2011-08-01 13:32
    I wanted to use the PASDebugger to see what is happening and learned something new

    After loading the code into PASD. PASD right away mentioned the bug in the status line
    at the bottom of the PASD-window and even marking the buggy line pink

    keep the questions coming
    best regards

    Stefan
    669 x 788 - 18K
  • WossnameWossname Posts: 174
    edited 2011-08-02 09:54
    @Ariba, thank you for spotting that! Now it works just fine. Now I can see how to expand my app to use all COGs at once!

    @Stefan, I've had a look at the PASD software you mentioned and it has confused me a bit. It's complaining that the "timeOUT" declaration should be at the bottom. But surely if I put it at the bottom then it won't be loaded into COG 0 (if the code was a lot longer for example). Or am I wrong about that? (I'm still getting to grips with this language so let me know if I'm talking rubbish :)).

    Looks like a good tool though, it came up with my code almost without my noticing it had loaded it. Then I realised that it had scanned for the Propeller Tool's open file. Pretty cool stuff.

    Thank you to everyone who posted, I've learned some interesting things in this thread.

    Parallax's forums are great, friendly folks all around.

    Thanks again everyone.
  • StefanL38StefanL38 Posts: 2,292
    edited 2011-08-02 11:28
    Hi Woss,

    the message "res section must be at end to correspond with assembler alignement" is meant exactly how ariba showed it

    all PASM-commands and longs have to be before any res.

    the order of the res do't play a role. You can order them as you like the names of each res gets calculated by the compiler but the calculation is only correct if the res start behind
    commands and behind longs

    Though I don't know what happends if you have code for more than one cog in a DAT-section and put the res-(erved) longs at the end.
    The code must fit into the COGs RAM which means there is room for 496 longs. If your code extends that only the first 496 longs get loaded
    and I guess if res)erved longs are behind that they are just not there making the code not working.

    Maybe the PASM-experts can chime in.
    Would I create a separate DAT-section for each cogs code?
    Would I use separate spin-file for each PASM-code?

    keep the questions coming
    best regards

    Stefan
  • kuronekokuroneko Posts: 3,623
    edited 2011-08-02 17:01
    StefanL38 wrote: »
    Would I create a separate DAT-section for each cogs code?
    Would I use separate spin-file for each PASM-code?
    Separate DAT sections are not quite enough, they have to be prefixed by an org 0, just the org is fine as is a separate file (but maybe overkill). Make sure that the whole program (code/variables) stays together, e.g. between orgs. Also, you can't place a res after $1F0, i.e. it tracks the org counter and complains.
  • WossnameWossname Posts: 174
    edited 2011-08-03 12:22
    My code is finished, and I've made this into a brief pseudo-tutorial on my blog...
    http://wardyprojects.blogspot.com/2011/08/propeller-plus-input-and-output-shift.html
  • StefanL38StefanL38 Posts: 2,292
    edited 2011-08-03 14:19
    Hi Woss,

    You are using coginit. One of the rare situations where coginit should be used is if you want to restart a certain cog for executing PASM-code that is actually executing SPIN-code.

    As long as you do not run out of cogs use cognew. If you use cognew the propeller-chip takes care which cog will be used. If you start using coginit you the user are responsible for
    starting and stopping the right cogs.

    A short time ago there was a thread about this restart a certain SPIN-cog with PASM-thread.

    keep the questions coming
    best regards

    Stefan
  • WossnameWossname Posts: 174
    edited 2011-08-03 23:53
    Hi Stefan, yeah I want to keep tight control on which cogs are running at any given time, so I chose to use coginit(). This is a safety feature actually, this code will eventually be part of control firmware for a pen plotter, when the stepper motors hit the end of their movement range I want to be able to kill the cog that controls it instantly, regardless of what it's doing at the time.

    Otherwise it may rise up and overthrow it's puny human masters etc. etc.etc...
  • kuronekokuroneko Posts: 3,623
    edited 2011-08-04 00:16
    Wossname wrote: »
    ... I want to be able to kill the cog that controls it instantly, regardless of what it's doing at the time.
    And you can't do that by recording the cogid returned by cognew (provided it doesn't fail)?
  • StefanL38StefanL38 Posts: 2,292
    edited 2011-08-04 00:28
    I don't think so. If you use cognew all the time the propeller makes 100% sure to start a free cog as long as there are cogs available.
    If all eight cogs are in use you get e feedback about this.

    If you use coginit you force the cog to start or to restart. Now imagine you want to start cog 4 thinking it is free but it isn't. With coginit you force the already running cog to terminate its actual task
    and start it with your new task. When using coginit the propeller hands over the full responsibility which cog to start, stop or restart to you. And I guess in most cases this is a source of bugs that could be avoided through using cognew consequently.

    For stopping code-actions I used to make the execution of critcical parts conditionally to a central variable.
    pseudo-code if MyAbortVar = zero ....

    Whenever something strange happens regardless of what it is (in your example pen hits end of his moving range) MyAbortVar is st to a non-zero value indicationg an error.
    if really all critical things are condiational to if MyAbortVar = zero .... everything stops as soon as possible. For using this across cogs it has to be a shared HUB-RAM-long.

    I used this while programming in delphi for PC_based industrial controls.

    Anyway something like pen hitting the border of his range or real emergency things I would hardwire in a serial of normally closed switches. Operates only as long as all switches are closed.
    Whenever one switch opens or a wire gets cutted the thing stops without the need of the MCU checking it.

    keep the questions coming
    best regards

    Stefan
  • WossnameWossname Posts: 174
    edited 2011-08-04 09:39
    My plotter's extent switches will be software-polled because I want to use them in the calibration phase at bootup. But I'll be testing them after each pulse I send to the stepper motors, so it's still as close to passive as I can get without losing functionality.
Sign In or Register to comment.