Shop OBEX P1 Docs P2 Docs Learn Events
need help with asm effect flags and shared variables — Parallax Forums

need help with asm effect flags and shared variables

laser-vectorlaser-vector Posts: 118
edited 2014-04-19 20:39 in Propeller 1
Hi

i have two asm blocks that share a variable and a spin routine that can set that variable to some value for control.

when the variable is 0 both asm loops are supposed to do nothing.
when it is set to 2 the "watchForHome" loop waits until there is some value in the PHSA register and then sets the variable to 1.
when the variable is 1 the "asmPID" loop should set "encoderPosition" equal to 0 and then set the shared variable back to 0.

what i am seeing though is the variable "homeFlagReset" starts equal to 0, when i type the command 'h' i see it change to 2.
when i rotate the shaft to the home flag i see it change to 0 then 1 and back again regardless if im still blocking the home flag or not and its just stuck in an endless loop. (eg output: 0,1,1,1,0,1,1,1,0,1,1,1,0......).

if i dont launch the "watchForHome" cog and just set "homeFlagReset" equal to 1 instead of 2 the "encoderPosition" variable is set to 0 and the "homeFlagReset" variable is reset to 0 successfully and all returns to normal.

im pretty new to assembly, i was hoping someone might be able to help me figure out what im doing wrong??

thanks!!
VAR
long speedTarget, homeFlagReset 'do not rearange

PUB main
cognew(@watchForHome, @homeFlagReset)
cogNumber := cognew(@initialization[0], @speedTarget[0])

...
repeat
  if ser.RxCheck
    inByte := ser.rx
    if inByte == 13 'carriage return
      case commandBuffer[0]
        "h" :
          homeFlagReset := 2
          posTarget := -1000               
        other :                      
          ser.str(string("?") )             
      ser.tx(13)
...
     
DAT
'Watch counter for home/limit signal
        org     0
watchForHome  
        mov     ctra,           ctraval
        mov     frqa,           #1
        
:loop   mov     addr,           par      'homeFlagReset
        rdlong  tmp,            addr
        mov     resetPhs,       tmp
                                           
        cmp     resetPhs,       #2    wz 'command 2 waits for reset
if_z    cmp     numOne,         phsa  wc 'if phsa is greater than 1
if_c    mov     phsa,           #0          'reset phsa
if_c    mov     setHome,        #1       'command 1 sets the reset
if_c    wrlong  setHome,        addr   'write the value to the shared variable

        jmp     #:loop                   'loop for next cycle 
          
ctraval       LONG      %01100 << 26 + 19
resetPhs      LONG      0
myPhs         LONG      0         
numBuff       LONG      0
numOne        long      1
tmp           res       
addr          res

dat
initialization

blah blah...
...
...

        org     0
asmPID   
        mov     addrPID,          par  'get the shared variable's address
        add     addrPID,          #4    'we want the second long (eg. "homeFlagReset" )
        rdlong  tmpPID,           addrPID  'get its value
        cmp     tmpPID,           #1 wz      'if it equals 1 then reset position             
if_z    mov     encoderPosition,  #0     'resetting position
if_z    wrlong  encoderPosition,  addrPID  'writing value

        jmp     #asmPID 

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2014-04-19 17:38
    This part worries me:
    tmp           res       
    addr          res
    
    dat
    initialization
    
    blah blah...
    ...
    ...
    

    If the initialization consists of long/word/byte data required by the PASM code above it, it must not come after the res section. Rather, the res has to come last, just before the next org.

    -Phil
  • laser-vectorlaser-vector Posts: 118
    edited 2014-04-19 20:03
    thanks Phil,

    i went ahead and changed those to longs.

    what really made a difference was changing the way the conditionals evaluated the flags and clearing phsa whenever the homing command isnt equal to 2.
                   cmp     resetPhs,       #2    wz 'command 2 waits for reset
    if_nz          mov     phsa,           #0 
    if_z           mov     numBuff,        phsa
    if_z           cmp     numBuff,        #1    wc
    if_z_and_nc    mov     setHome,        #1       'command 1 sets the reset
    if_z_and_nc    wrlong  setHome,        addr
    
    
    
    now its working but i still have much to learn
  • ElectrodudeElectrodude Posts: 1,658
    edited 2014-04-19 20:39
    Note that you don't have to obey PhiPi's advice about the res if the code after the res will get run in another cog. Also, there's nothing wrong with using res - just be sure to put it at the very end of its cog's code. It actually saves you a little bit of hub ram.

    Why is asmPid recalculating the pointer to homeFlagReset every time through the loop? You could at least store the calculated pointer somewhere, it'll save you two instructions (and, probably more importantly, two longs of cogram!). I try to avoid par - it's nothing but a headacheful of pointers and a waste of unnecessary code that only gets run once. Instead try:
    VAR
    
      long  x
    
    PUB main
    
      xptr := @x
      cognew(@entry, 0)
      repeat
        x:= 1
        repeat while x
        waitcnt(clkfreq + cnt)
    
    DAT
                            org     0
    entry                   rdlong  t1,    xptr     wz
                            tjz     t1,    #entry
                            'do stuff
                            wrlong  zero,  xptr             'tell the spin cog we're done
                            jmp     #entry
    
    xptr                    long    0-0
    zero                    long    0
    t1                      res     0
    

    Notice that xptr gets written before the cog gets loaded, so the correct pointer to x gets loaded into the cog along with the rest of the code. You would have homeResetFlagPtr instead. And yes, it is more efficient to pre-load every single hub pointer into what will be cogram after the cognew, no matter how many variables there are, because it will always take more than 1 long to calculate the address but it only takes 1 long to store it. Obviously, you should still calculate the pointer for array offsets and such.

    Is there any reason to use par over this method? I've never seen any, even in cases when I've started multiple cogs from the same pasm (just put a little delay after the cognew or don't start a new cog for a while or wait on a flag that gets cleared by the newly started cog before starting the next cog or something).

    electrodude
Sign In or Register to comment.