Shop OBEX P1 Docs P2 Docs Learn Events
flexspin compiler for P2: Assembly, Spin, BASIC, and C in one compiler - Page 131 — Parallax Forums

flexspin compiler for P2: Assembly, Spin, BASIC, and C in one compiler

1125126127128129131»

Comments

  • __deets____deets__ Posts: 216
    edited 2026-02-08 19:21

    Ok so I found the culprit. I've written a program (years ago) that opens the serial port and just prints out what it reads. I call it stail for serial tail. And this detects when the propeller is being programmed, and shuts down the serial port so the loadp2 can do it's work, waits a second and tries to re-open the port.

    And it appears that has changed its behavior, possibly my new underlying Linux or something. After fiddling with it, I don't seem to suffer from this stray reset. And guess what, the not-working.spin2 happens to work.

    DIEZ 2026-02-01: sx1268_init:0
    sx1268-send-test: 0
    Lora1: sx1268: start send test.
    
    Lora1: sx1268: chip is busy.
    
    Lora1: sx1268: set standby failed.
    
    Lora1: sx1268: chip is busy.
    
    sx1268-send-test:failed
    
    

    So more investigation needed.

  • I just tried this:

    VAR
      long  position
      long  timeStamp
    
    PUB GetPosition (): pos | p, t, ct, dt, v, h
      p:= @position
      ORG
            setq    #1              ' atomic read of p+t
            rdlong  p,p
      END
      ct:= getct ()
    ...
    

    position and timeStamp are written by another cog. I assumed that p and t are consecutive registers which are later used in another assembler inline section. I think Chip used tricks like this in P1 Spin a lot which relied on the order of stack parameters and local variable in memory. But in P1 Spin those were in hub RAM, not cog RAM. The problem is that FlexSpin assigns registers in the order the variables appear in the code of the function, not in the list of local variables in the header. So _var01 is allocated to p and _var02 to ct instead of t.

    I know this is not a bug. It was never promised to work, just my optimistic assumption. o:) But is there a way to make it work? If I do

    PUB GetPosition (): pos | p, t, ct, dt, v, h
      p:= position
      t:= timeStamp
    ...
    

    instead my code works but, of course, the access to p and t is not atomic. SETQ + RDLONG is a nice way to avoid locks and delays.

  • @ManAtWork said:
    But is there a way to make it work?

    Easiest would be to add {++opt(!fast-inline-asm)} between PUB/PRI and the function name. That'll force it to do the whole interpreter-style variable copy (slow and nasty) for ORG/END sections.

    But I think if the variable you read into is a quad, array or structure, it will always place that in consecutive registers, so try that first.

  • evanhevanh Posts: 17,122
    edited 2026-03-04 23:11

    If those locals are exclusively Pasm used then move them into a group of labelled RES's at end of ORG section.

    VAR
      long  position
      long  timeStamp
    
    PUB GetPosition (): pos | ct, dt, v, h
      ct:= @position
      ORG
            setq    #1              ' atomic read of p+t
            rdlong  p,ct
            ...
            ret
    
    p       res 1
    t       res 1
      END
      ct:= getct ()
    
  • evanhevanh Posts: 17,122
    edited 2026-03-05 07:46

    Eric,
    Looks like a regression in the includes at some point. The newer _sdmm_open() base function, used by _vfs_open_sdcardx(), for starting up Flexspin's built-in SD driver is not declared anywhere now. I've previously been directly using this function due to its compatibility with the external driver plug-in mechanism. To get it in scope now, I place the following line in my top source file:

    vfs_file_t *_sdmm_open(int pclk, int pss, int pdi, int pdo) _IMPL("filesys/block/sdmm_vfs.c");
    
  • @Wuerfel_21 said:
    But I think if the variable you read into is a quad, array or structure, it will always place that in consecutive registers, so try that first.

    I didn't know that I can declare local array variables, so far. But I tried and it seems to work. :)

    PUB GetPosition (): pos | p[2], t, ct, dt, v, h
      p:= @position
      ORG
            setq    #1              ' atomic read of p+t
            rdlong  p,p
      END
      t:= p[1]
      ct:= getct ()
    

    @evanh Your idea is also good but unfortunatelly doesn't work in my case. I have a second inline assembler section after some calculations in Spin2 and I couldn't acess the p and t res 1 variables from the second section. Ok, it would work with some additional copy instructions but is way more complicated than the solution above. But thanks, anyway.

  • evanhevanh Posts: 17,122
    edited 2026-03-05 11:01

    I'd never have two Pasm sections split. That's double dipping on the Fcache overheads. I sure hope there's a damn good reason not to just merge them.

  • @evanh said:
    I'd never have two Pasm sections split. That's double dipping on the Fcache overheads. I sure hope there's a damn good reason not to just merge them.

    Yeah, you're absolutely right. I could translate the Spin code between the two assembler sections to assembler, too. I kept it because it was easier to debug and also for historical reasons. This was a P1 program, once. I've ported it to the P2 and added the 64 bit arithmetic later.

    PUB GetPosition (): pos | p[2], t, ct, dt, v, h
      p:= @position
      ORG
            setq    #1              ' atomic read of p+t
            rdlong  p,p
      END
      t:= p[1]
      ct:= getct ()
      dt:= ct - lastTime
      if p <> lastPos       ' position changed?
        last2Pos:= lastPos
        last2Time:= lastTime
        lastPos:= p
        lastTime:= t
      elseif dt > maxPeriod ' < min. speed
        last2Pos:= p                ' force v=0
        lastTime:= ct - maxPeriod
        last2Time:= lastTime - maxPeriod    ' avoid timer overflow
      else
        lastTime:= t ' update in the case dithering changed t
      ' v:= (lastPos - last2Pos) * cycleTime / (lastTime - last2Time)
      ' pos:= lastPos + v*dt / cycleTime
      p:= lastPos - last2pos
      t:= lastTime - last2Time
      ct:= cycleTime
      ORG ' use 64 bit arithmetic because v*dt or p*cycleTime could be >2^31
            abs     p wc
            qmul    p,ct ' (lastPos - last2Pos) * cycleTime
            getqx   p
            getqy   h
            setq    h
            qdiv    p,t             ' / (lastTime - last2Time)
            getqx   v
            qmul    v,dt            ' * dt
            getqx   v
            getqy   h
            setq    h
            qdiv    v,ct   ' / cycleTime
            getqx   p
            negc    p
      END
      pos:= lastPos + p
    
  • ersmithersmith Posts: 6,270

    @evanh said:
    Eric,
    Looks like a regression in the includes at some point. The newer _sdmm_open() base function, used by _vfs_open_sdcardx(), for starting up Flexspin's built-in SD driver is not declared anywhere now. I've previously been directly using this function due to its compatibility with the external driver plug-in mechanism. To get it in scope now, I place the following line in my top source file:

    vfs_file_t *_sdmm_open(int pclk, int pss, int pdi, int pdo) _IMPL("filesys/block/sdmm_vfs.c");
    

    I don't think that function was ever declared in header files, it was probably getting dragged in as a side effect of something else. Anyway, I've added an explicit declaration now. Thanks for catching this.

  • ersmithersmith Posts: 6,270

    @ManAtWork said:

    @Wuerfel_21 said:
    But I think if the variable you read into is a quad, array or structure, it will always place that in consecutive registers, so try that first.

    I didn't know that I can declare local array variables, so far. But I tried and it seems to work. :)

    Yes, that should work. So should structures, but if you're directly manipulating elements in assembly language using an array might be clearer.

  • @ersmith said:
    I don't think that function was ever declared in header files, it was probably getting dragged in as a side effect of something else. Anyway, I've added an explicit declaration now. Thanks for catching this.

    Remember, I separated out some of the SDMM stuff because it was getting compiled in and bloating binaries even when using an external block driver (SDSD). I think dead code elimination doesn't work well for functions that are referred to by function pointers somewhere.

  • ersmithersmith Posts: 6,270

    @Wuerfel_21 said:

    @ersmith said:
    I don't think that function was ever declared in header files, it was probably getting dragged in as a side effect of something else. Anyway, I've added an explicit declaration now. Thanks for catching this.

    Remember, I separated out some of the SDMM stuff because it was getting compiled in and bloating binaries even when using an external block driver (SDSD). I think dead code elimination doesn't work well for functions that are referred to by function pointers somewhere.

    Right, but I don't think just declaring the function should cause any issues. I looked at your patch that did the re-arrangement, and I don't think sdmm_open was declared before that either (unless I missed something).

  • evanhevanh Posts: 17,122
    .../include/filesys/block/sdmm_vfs.c:60: warning: Redefining function or subroutine _sdmm_open with an incompatible type
    

    I don't think struct vfs was a good choice. :)

  • ersmithersmith Posts: 6,270

    @evanh said:

    .../include/filesys/block/sdmm_vfs.c:60: warning: Redefining function or subroutine _sdmm_open with an incompatible type
    

    I don't think struct vfs was a good choice. :)

    Oops yes, thanks. I've pushed an update.

Sign In or Register to comment.