Shop OBEX P1 Docs P2 Docs Learn Events
Differences with Inline PASM and starting PASM in a separate cog. — Parallax Forums

Differences with Inline PASM and starting PASM in a separate cog.

So I prototyped some code using in-line PASM. Everything works perfectly. I want to offload this into a separate, dedicated cog. I have used all available local variables for in-line PASM. Moving it into a dedicated cog is the only path forward. So I dutifully duplicated the code, using different reserved variable names. I hand off 3 longs from hubram using setq and rdlong to fill the reserved variables. Everything else, such as pins, pinfields, and fixed variables are constants.

Unfortunately, I am seeing some bazar behavior when the cog is launched. It does not work correctly and fills the rubram buffer with the same variable value ($78). I am having some trouble determining what is going on. I thought converting inline to standard PASM would be easy. Two weeks of complete and utter failure have me really down in the dumps. I thought I would be into code optimization by now.

What differences should I expect when changing code from inline PASM to regular PASM? Would anything be different about constants, pin operations, etc?

Comments

  • evanhevanh Posts: 16,039
    edited 2022-02-23 05:54

    It'll likely be something minor. When getting confused about these things the tried and true way out is test each question mark.

    Here's a slightly modified previous example that now, using DEBUG() feature, prints the value of PTRA from within the Pasm cog.

    CON
        _xtlfreq = 20_000_000
        _clkfreq = 10_000_000
        DOWNLOAD_BAUD = 230_400
        DEBUG_BAUD = DOWNLOAD_BAUD
    
    
    PUB startfastrx(ptr1) : e131cog
      e131cog := coginit(COGEXEC_NEW, @cogx, $87654321)  + 1
      return
    
    DAT
    
        org   0
    
    cogx
        drvl    #56
        drvh    #57
        debug   (uhex(ptra))
    
    .loop
        waitx   ##clkfreq_
        outnot  #56
        outnot  #57
        jmp #.loop
    

    That prints $87654321 in the terminal. Proving that it is PTRA that receives the passed parameter.

    Cog0  INIT $0000_0000 $0000_0000 load
    Cog0  INIT $0000_0404 $0000_0000 load
    Cog1  INIT $0000_06EC $8765_4321 load
    Cog1  ptra = $8765_4321
    
  • As Evan points out, it's probably a small "gotcha" -- I have done exactly what you're wanting to do several times.

  • Past my bedtime tonight, but you can easily debug in PASM?!?!?!?!?! Ok, I'm on it tomorrow night. I can work with this! Thank you guys!

  • evanhevanh Posts: 16,039

    Gotta be one of best parts of debug(). :)

  • ke4pjwke4pjw Posts: 1,169
    edited 2022-02-24 03:15

    OK, real progress tonight. That debug is so dadgum nice!

    I have found that after sending data to the databus and performing a FLTL on those pins, I can read the correct information with inline PASM, but when executed in its own cog, the last data sent out is all that is read.

    This works and returns the expected $0000 (right side of picture)

    'Set BS
      DRVl  ##A0 'ADDR bit 0
      DRVh  ##A1 'ADDR bit 1
    
      altsb datapin, #outa
      setbyte BS
      debug(uhex(BS))  
    
      DRVL  ##WRn
      waitx #50
      DRVH  ##WRn
    
      DRVh  ##A0 'ADDR bit 0
      DRVh  ##A1 'ADDR bit 1
      FLTL #DATA
    
    ' Read i number of bytes.
    
    rxloop DRVL ##RDn ' Enable Chip Read
          waitx #50 ' Wait cuz this is slow
          altgb datapin,#ina ' Where you gonna get that data?
          getbyte tmpdata ' Get that data and put it in tmpdata
          debug(uhex(tmpdata))
          WFBYTE tmpdata  ' Write that data to the read buffer in HUBRAM.
          add RB, #1 ' Increment the read buffer by 1 byte
          DRVH ##RDn ' Disable Chip read
          waitx #50  ' Wait cuz this is slow
    
          add r,tmpdata  ' Populate return value
          shl r,#8
    
    ' R U Dun? (Compare i, which is where we stop where it is equal to the current read buffer value)
          CMP i,RB wz
    if_nz jmp #rxloop
          shr r,#8
    ' Disable Chip Select
          DRVH  ##CSn
          ret
    
    

    This does not work and returns the last data I sent out the bus. (Left side of picture)

    'Set lBS
          DRVl  ##A0 'ADDR bit 0
          DRVh  ##A1 'ADDR bit 1
    
          altsb ldatapin, #outa
          setbyte lBS
          debug(uhex(lBS))
    
          DRVL  ##WRn
          waitx #50
          DRVH  ##WRn
    
          DRVh  ##A0 'ADDR bit 0
          DRVh  ##A1 'ADDR bit 1
          FLTL #DATA
    
    ' Read i number of bytes.
    
    lrxloop DRVL ##RDn ' Enable Chip Read
          waitx #50 ' Wait cuz this is slow
          altgb ldatapin,#ina ' Where you gonna get that data?
          getbyte ltmpdata ' Get that data and put it in ltmpdata
          debug(uhex(ltmpdata))
          WFBYTE ltmpdata ' Write that data to the read buffer in HUBRAM.
          add lRB, #1 ' Increment the read buffer by 1 byte
          DRVH ##RDn ' Disable Chip read
          waitx #50  ' Wait cuz this is slow
    
          add lr,ltmpdata  ' Populate return value
          shl lr,#8
    
    ' R U Dun? (Compare i, which is where we stop where it is equal to the current read buffer value)
          CMP li,lRB wz
    if_nz jmp #lrxloop
          shr lr,#8
    ' Disable Chip Select
          DRVH  ##CSn
          ret
    
    

    I changed the BS value and indeed, the new value was reflected in the two byte reads of the return value. RB values are expected to be different.

    I am sure that it is the FLTL. What is the proper way to set the pins back to be able to read? Why would it be different if ran in a cog? (I don't think any other cogs are doing anything with those pins.)

    PS: There is a WRFAST #0,RB and WRFAST #0,lRB at the top of the routine that sets the hub address to write into.

  • evanhevanh Posts: 16,039

    I'm guessing ldatapin is not in the range of 0 to 3.

  • ke4pjwke4pjw Posts: 1,169
    edited 2022-02-24 04:48

    ldatapin is $3

    #DATA is $1D8 which I think is the expected result of 24 ADDPINS 7

    It's just so weird! I am losing my mind over this, LOL! It must be something to do with cog0.

    544 x 527 - 21K
  • I have definitively ruled out interference from other code. Booted the chip straight to starting this cog without doing anything else and the result was the same.

  • evanhevanh Posts: 16,039
    edited 2022-02-24 05:12

    Nothing particularly wrong that I can see. Seems like another cog is driving the pins with that value when Cog3 is reading the pins.

  • @evanh said:
    Nothing particularly wrong that I can see. Seems like another cog is driving the pins with that value when Cog3 is reading the pins.

    I have shutdown all of the other cogs, commented out any code other than starting this cog, and the result was the same.

    Is there a way I can determine the state of the pins?

  • evanhevanh Posts: 16,039

    You can read the values in OUTA and DIRA. Not many others can be read back like that.

  • OK, looks like databus is fine, however the address lines and chip control lines are pretty far from OK. maybe the "echo" is due to the W6100 chip being in an inconsistent state.

    Working reports $FF_0000
    Broken reports $6E_0000

    I will dig into it further this evening. One thing of note, for the control lines, I didn't expect to have to use ## for those constants, but it was the only way for them to work with inline PASM. Maybe this is the problem? Just thinking out loud.

  • pik33pik33 Posts: 2,388

    I had this kind of problem (code worked in cog #0 and not worked in another cog) because I started the pin using Spin code in cog 0 and then I tried to use it and restart it in another cog. Removing initialization from cog #0 and moving it to the same cog which was supposed to use the pin helped.

  • Yes, pik33 has a point. Each cog has its own pin direction registers, so setup in one cog and use in another may not work. I had this problem with my I2C object. The problem was solved by moving the I2C initialization to the cog that needed I2C transactions.

  • @ke4pjw said:
    One thing of note, for the control lines, I didn't expect to have to use ## for those constants, but it was the only way for them to work with inline PASM. Maybe this is the problem? Just thinking out loud.

    This is actually a very big clue, I think. How exactly are your constants declared? if they're just in a CON block then there's no reason at all why they should need ## in front of them. Is it possible that you mistakenly declared them as variables, or as labels in the DAT section?

  • @JonnyMac said:
    Yes, pik33 has a point. Each cog has its own pin direction registers, so setup in one cog and use in another may not work. I had this problem with my I2C object. The problem was solved by moving the I2C initialization to the cog that needed I2C transactions.

    I think this is it. There are PINs that are left in output states that will need to be changed by the other cog. I am going to release these pins. I didn't think this all the way through (obviously), because I knew the pins were ORed and each cog has it's own latch.

  • As Dave Jones says.... Forever Joy!!!

    I'm golden! That was it! WoooHooo!

    Thank you all! This is the best forum on the Internet! You guys are always to nice and helpful and I know I abuse the privilege too often. Thank you all so much!!!

  • cgraceycgracey Posts: 14,208

    @ke4pjw said:
    As Dave Jones says.... Forever Joy!!!

    I'm golden! That was it! WoooHooo!

    Thank you all! This is the best forum on the Internet! You guys are always to nice and helpful and I know I abuse the privilege too often. Thank you all so much!!!

    We've all been stumped by this circumstance of making some pins outputs in one cog, then launching another cog to deal with them, but never making those pins outputs in that new cog. It's really simple, but can easily get overlooked when starting a new cog, as opposed to carrying on in the same cog.

Sign In or Register to comment.