Shop OBEX P1 Docs P2 Docs Learn Events
PNut/Spin2 Latest Version (v47 - Cooperative multitasking added to Spin2, up to 32 tasks) - Page 14 — Parallax Forums

PNut/Spin2 Latest Version (v47 - Cooperative multitasking added to Spin2, up to 32 tasks)

1111214161770

Comments

  • cgraceycgracey Posts: 14,206
    Mike Green wrote: »
    Chip, With PNutVr I'm getting an error with a call to AKPIN (Expression terms must return a single result). Your documentation of this call doesn't seem to imply that there is more than one result.

    AKPIN returns nothing, right? It sounds like you are using it as a term which is expected to return a value. AKPIN needs to be used in isolation as an instruction.
  • Yes, I was using it as a term. I'll fix that. Thanks.
  • Cluso99Cluso99 Posts: 18,069
    edited 2020-04-19 05:20
    In spin1 we only had to define...
    _XINFREQ = 5_000_000 + 0000
    _CLKMODE = XTAL1 + PLL16X
    once, where clkfreq was calculated, and all lower levels inherited this value. eg in FullDuplexSerial we could calculate the baud for the inherited clkfreq thus...
    PUB start(rxpin, txpin, mode, baudrate) : okay
    bit_ticks := clkfreq / baudrate

    Do we have similar capability in spin2?
  • cgraceycgracey Posts: 14,206
    edited 2020-04-19 07:01
    Cluso99 wrote: »
    In spin1 we only had to define...
    _XINFREQ = 5_000_000 + 0000
    _CLKMODE = XTAL1 + PLL16X
    once, where clkfreq was calculated, and all lower levels inherited this value. eg in FullDuplexSerial we could calculate the baud for the inherited clkfreq thus...
    PUB start(rxpin, txpin, mode, baudrate) : okay
    bit_ticks := clkfreq / baudrate

    Do we have similar capability in spin2?

    You can always access the runtime variables at any level, like you are talking about. However, you can't access the hard-coded values from the top level file that were compiled.
  • Cluso99Cluso99 Posts: 18,069
    By tricking spin2 to setup the serial ROM and call the monitor, I can finally locate where spin2 (pnut v34R) places my code in hub, and get to look at what it compiled.

    My serial/monitor/debugger (and SD) p2asm code originally compiled for the P2 ROM (pnut v32i) used this format...
                       DAT
    fca78                              orgh
                                       .....                   
    fca88     fdbfffec _Start_Monitor  call    #@_reset_booter                 ' reset the booters interrupts and autobaud
    

    Now when this compiles with spin2 and pnut v34R we get this (derived from the monitor hex dump)
                       DAT
    fca78                              orgh
    01000                              byte    $3D[$A78]
                                       .....                   
    01a88     fdbffbf4 _Start_Monitor  call    #@_reset_booter                 ' reset the booters interrupts and autobaud
    
    Note: There is no realistic/useful listing in pnut. In fact, the code doesn't even reside where the listing (dump) says it is :(

    Now we can finally examine the code to see what is wrong. So here is the snippet just to examine the problem...
    fca78                              orgh
                       
                       ''-----------------------------------------------------------------------------------------------
                       ''      RESET BOOTER SERIAL INTERRUPTS & AUTOBAUD - KEEP SMART UART RUNNING
                       ''-----------------------------------------------------------------------------------------------
    fca78     fd640025 _reset_booter   setint1 #0                              ' disable int1
    fca7c     f527f403                 andn    dira,#3                         ' reset smart pins on P0 & P1
    fca80     fc0c0001                 wrpin   #0,#rx_ths                      ' clear P1 rx_ths mode
    fca84     0c0c0000         _RET_   wrpin   #0,#rx_tne                      ' clear P0 rx_tne mode
                       ''===============================================================================================
                       
                       
                       ''-------[ Start Monitor ]----------------------------------------------------- <--- start monitor --->
    fca88     fdbfffec _Start_Monitor  call    #@_reset_booter                 ' reset the booters interrupts and autobaud
    

    So the ROM code at does a call to a preceeding
    01a88     fdbffbf4 _Start_Monitor  call    #@_reset_booter                 ' reset the booters interrupts and autobaud
    fca78     fd640025 _reset_booter   setint1 #0                              ' disable int1
    
    Here we can see that both pieces of code
    _Start_Monitor call #@_reset_booter

    The _reset_booter label is located 5 longs backwards. The original pnut calculated this correctly as -20 bytes $FFFEC but pnut v34R calculates this to be $FFBF4. So Pnut is incorrectly calculating the relative branch offset.

    BTW I've wasted many days on this since I was flying blind and wondering why things didn't work! :(

    I accept that there can always be bugs. What gets me so upset is the fact that all of the test basics that we have in the ROM is useless, it's a nightmare toconvert P1PASM, and Spin2 is so different it shouldn't even be called spin2. Everything has been thrown out the window with total disregard to what came before.
  • cgraceycgracey Posts: 14,206
    Cluso99 wrote: »
    By tricking spin2 to setup the serial ROM and call the monitor, I can finally locate where spin2 (pnut v34R) places my code in hub, and get to look at what it compiled.

    My serial/monitor/debugger (and SD) p2asm code originally compiled for the P2 ROM (pnut v32i) used this format...
                       DAT
    fca78                              orgh
                                       .....                   
    fca88     fdbfffec _Start_Monitor  call    #@_reset_booter                 ' reset the booters interrupts and autobaud
    

    Now when this compiles with spin2 and pnut v34R we get this (derived from the monitor hex dump)
                       DAT
    fca78                              orgh
    01000                              byte    $3D[$A78]
                                       .....                   
    01a88     fdbffbf4 _Start_Monitor  call    #@_reset_booter                 ' reset the booters interrupts and autobaud
    
    Note: There is no realistic/useful listing in pnut. In fact, the code doesn't even reside where the listing (dump) says it is :(

    Now we can finally examine the code to see what is wrong. So here is the snippet just to examine the problem...
    fca78                              orgh
                       
                       ''-----------------------------------------------------------------------------------------------
                       ''      RESET BOOTER SERIAL INTERRUPTS & AUTOBAUD - KEEP SMART UART RUNNING
                       ''-----------------------------------------------------------------------------------------------
    fca78     fd640025 _reset_booter   setint1 #0                              ' disable int1
    fca7c     f527f403                 andn    dira,#3                         ' reset smart pins on P0 & P1
    fca80     fc0c0001                 wrpin   #0,#rx_ths                      ' clear P1 rx_ths mode
    fca84     0c0c0000         _RET_   wrpin   #0,#rx_tne                      ' clear P0 rx_tne mode
                       ''===============================================================================================
                       
                       
                       ''-------[ Start Monitor ]----------------------------------------------------- <--- start monitor --->
    fca88     fdbfffec _Start_Monitor  call    #@_reset_booter                 ' reset the booters interrupts and autobaud
    

    So the ROM code at does a call to a preceeding
    01a88     fdbffbf4 _Start_Monitor  call    #@_reset_booter                 ' reset the booters interrupts and autobaud
    fca78     fd640025 _reset_booter   setint1 #0                              ' disable int1
    
    Here we can see that both pieces of code
    _Start_Monitor call #@_reset_booter

    The _reset_booter label is located 5 longs backwards. The original pnut calculated this correctly as -20 bytes $FFFEC but pnut v34R calculates this to be $FFBF4. So Pnut is incorrectly calculating the relative branch offset.

    BTW I've wasted many days on this since I was flying blind and wondering why things didn't work! :(

    I accept that there can always be bugs. What gets me so upset is the fact that all of the test basics that we have in the ROM is useless, it's a nightmare toconvert P1PASM, and Spin2 is so different it shouldn't even be called spin2. Everything has been thrown out the window with total disregard to what came before.

    Cluso, in your second CALL, try getting rid of the @, since it is returning the offset within the object, not the ORGH address.
  • Cluso99Cluso99 Posts: 18,069
    Thanks Chip. That worked.

    Having said this, the documents are going to need to spell out where and how to use the “@“, “/“ and nothing. There was discussion a long time ago. We need to be able to specifically dictate in pasm precisely whether relative or absolute addressing is used. Getting something that has some weird base is not acceptable IMHO.
  • Cluso99 wrote: »
    Thanks Chip. That worked.

    Having said this, the documents are going to need to spell out where and how to use the “@“, “/“ and nothing. There was discussion a long time ago. We need to be able to specifically dictate in pasm precisely whether relative or absolute addressing is used. Getting something that has some weird base is not acceptable IMHO.

    I feel like anything I say might set you off, but you're being very pushy towards a particular programming style.

    When Chip has offered to work thru some examples regarding how to convert code, your tone has gotten angrier. Please be willing to accept that what may have taken one instruction on P1 might take 2 or 3 on P2 in certain instances.
  • evanhevanh Posts: 16,032
    Cluso99 wrote: »
    ... There was discussion a long time ago. We need to be able to specifically dictate in pasm precisely whether relative or absolute addressing is used.
    That was only true while the assembler LOC bug persisted. All assemblers are fixed now, Pnut was the last to be sorted.

  • ersmithersmith Posts: 6,068
    edited 2020-04-20 20:29
    "\" is the way you specify absolute rather than relative. If the operand starts with "\" then the absolute version of the instruction is always generated. Otherwise the relative version is generated, if that's possible.

    "@" has nothing to do with absolute/relative; it's the sign that the HUB address of a label is desired. If the label is already after an ORGH then putting "@" does nothing, really. (And if you're mixing Spin and PASM then "@" in PASM may only give you an offset rather than the final hub address, depending on the compiler you use.)
  • Cluso99Cluso99 Posts: 18,069
    ersmith wrote: »
    "\" is the way you specify absolute rather than relative. If the operand starts with "\" then the absolute version of the instruction is always generated. Otherwise the relative version is generated, if that's possible.

    "@" has nothing to do with absolute/relative; it's the sign that the HUB address of a label is desired. If the label is already after an ORGH then putting "@" does nothing, really. (And if you're mixing Spin and PASM then "@" in PASM may only give you an offset rather than the final hub address, depending on the compiler you use.)

    Thanks Eric.

    Why would you want a call/jmp to use an offset rather than either a relative or absolute address? It would never be a correct address. I cannot even fathom why we have this third mode???

    We do need a table of some sorts, which includes the various compilers. Getting the wrong result without realising it doesn't help - it is a trap for everyone :(

    I specifically put the @ in the call and jmp/djnz/etc in my ROM code because the early pnut gave wrong results without it. Now pnut gives wrong results with it if it's mixed with spin2. I don't know about pnut with pure pasm.

    I have been having problems testing out my new SD pasm code (was pure pasm) and this could be at least one of the problems - I've been using both fastspin and to a lesser extent pnut.
  • evanhevanh Posts: 16,032
    Well, technically, even with pure pasm2, @ only works as hubRAM addresses because the binary is loaded at address zero. If it gets loaded anywhere else then you're in the same boat as spin2/pasm2 mixed.

  • ersmithersmith Posts: 6,068
    edited 2020-04-21 01:53
    @Cluso99: I think you got misled somehow by an early, buggy pnut, or something like that. But the meaning of "@" and "\" is fairly easy to remember. I'll cover the pure PASM situation first because all the compilers agree on it:

    (1) "\" modifies the instruction. That is, "jmp #\anything" causes the jmp to be an absolute jump. "anything" really can be anything there, it doesn't have to be a label. "jmp #\$400" generates an absolute jump to $400, whereas "jmp #$400" generates a relative jump if that's at all possible. If the jmp instruction is in COG or LUT then a relative jump to a HUB address isn't possible. Rather than failing the assembler will turn it into an absolute jump.

    "\" may only be used in instructions that have a relative and absolute form, i.e. jumps and LOC.

    (2) "@" modifies a label, and may only be put in front of one. It asks for the hub value of the label, i.e. where the code after that label was initially loaded into HUB memory. For labels defined after an ORGH but before any ORG, "label" and "@label" are the same.

    "@" may be used with any instruction, because again, it does not modify the instruction. It only affects the value used in the instruction. (OK, technically, changing the value could in some instances change the instruction, but that's a secondary effect and is not what "@" is for.) So "mov x, #@label" is legal, as long as the hub address of "label" fits into 9 bits.

    To illustrate: suppose we have
        orgh $400
        org  0
    cogval
        nop
    

    Then the label "cogval" has two values: its ordinary cog value 0, and its hub address $400 (where it initially is placed at load time). In all cases, the following equivalences hold (for pure PASM code, mixed PASM and Spin will be discussed below):
        jmp  #cogval   ' is exactly equivalent to jmp #0
        jmp  #@cogval  ' is exactly equivalent to jmp #$400
        jmp  #\cogval  ' is exactly equivalent to jmp #\0
        jmp  #\@cogval ' is exactly equivalent to jmp #\$400
    

    The jmp instructions with "\" will always be compiled as absolute jumps, so there's no ambiguity with any of them.
    The jmp instructions without "\" will be compiled as relative jumps if that's possible, i.e. if the jump target is in the same memory as the instruction. Whether or not there's a "@" sometimes affects which address the jmp is to, so in that sense it might affect whether it's relative or not, but that's a side effect. The same branches would be generated if you used plain numbers like "$400".

    If you're mixing PASM with Spin2 in Chip's compiler then I gather that there's a wrinkle, namely that the hub address is not known at compile time. Thus "@cogval" does not produce a sensible result. Basically you should never use it in PASM code that's mixed with Spin, unless you then go on to adjust it to the proper "final" address. This is not anything new, Spin1 worked the same way. That's why "@@@" had to be invented by some Spin1 compilers.

  • Cluso99Cluso99 Posts: 18,069
    Thanks Eric :)

    I'll digest it again a little later and maybe make a table.

    Meanwhile I've found another problem with my code which I think is the "@@@" issue. I'll post for Chip to solve next.
  • Cluso99Cluso99 Posts: 18,069
    Chip,
    Neither of the lines below compile/resolve to a correct hub address so that the correct string can be printed.
    _HubTxStrVer  mov       lmm_p,  ##_str_vers             ' send version string, $00 terminated
    _HubTxStrVer  mov       lmm_p,  ##@_str_vers             ' send version string, $00 terminated
    

    How do we solve this in spin2 for the pasm code ???

    code attached
  • Ray: Another way to think of it is that "@" means basically the same thing in Spin2/Pasm2 as it did in Spin1/Pasm1, and comes with the same limitations. Presumably you came up with workarounds for these limitations in your Spin1 code. The same workarounds will probably work for Spin2.
  • Cluso99Cluso99 Posts: 18,069
    edited 2020-04-21 02:24
    deleted
  • Cluso99Cluso99 Posts: 18,069
    edited 2020-04-21 02:43
    Eric,
    Your cogval example is not what happens with Chips' v34R with spin2. Let me try to explain. (refer to my post about 12 posts back)

    In the original pnut v32i the ROM code was compiled as follows
    fca88     fdbfffec _Start_Monitor  call    #@_reset_booter
    
    results correctly in a negative offset of 5 longs = 20 bytes as _reset_booter is a label on an instruction at hub $fca78 which is 4+1 instructions prior.

    v34R compiles DAT orgh code into a binary beginning at $00008 (from the binary listing in v34r). The loader loads this code into hub $01000 (at least in my example code above).
    So the instruction gets encoded as shown below (determined from a dump of hub code)
    01a88     fdbffbf4 _Start_Monitor  call    #@_reset_booter
    
    results in a bogus negative offset. Chip says this is an address relative to the object. No idea what use this would be as it certainly will not result in a correct relative address!

    So now we have this scenario...

    "@" must be used when referring to a label of an address in hub, BUT must not be used if the label is the address (hub or otherwise) of the target in a CALL/JMP/DJNZ/etc, at least when used with spin2.

    Do you see the confusion?




  • AribaAriba Posts: 2,690
    Cluso99 wrote: »
    ...
    _HubTxStrVer  mov       lmm_p,  ##_str_vers             ' send version string, $00 terminated
    _HubTxStrVer  mov       lmm_p,  ##@_str_vers             ' send version string, $00 terminated
    

    How do we solve this in spin2 for the pasm code ???

    I think you need to use LOC so the compiler can calculate the address relative:
    _HubTxStrVer  loc       lmm_p,  #_str_vers              ' send version string, $00 terminated
    
    But I have not tried it, just my guess.

    Andy
  • Ariba wrote: »
    Cluso99 wrote: »
    ...
    _HubTxStrVer  mov       lmm_p,  ##_str_vers             ' send version string, $00 terminated
    _HubTxStrVer  mov       lmm_p,  ##@_str_vers             ' send version string, $00 terminated
    

    How do we solve this in spin2 for the pasm code ???

    I think you need to use LOC so the compiler can calculate the address relative:
    _HubTxStrVer  loc       lmm_p,  #_str_vers              ' send version string, $00 terminated
    
    But I have not tried it, just my guess.

    Andy

    LOC can only be used with PA/PB/PTRA/PTRB registers.


  • As I pointed out in the last paragraph of my post, things change when Spin enters the mix. In that case @ becomes useless in some compilers, just as it is useless in pasm in Spin1. It's frustrating, but in that case you have to pass the address as a parameter from Spin to pasm. Or, if everything is hubexec you may be able to use LOC as Andy suggested. But in this scenario the LOC instruction must execute from hub memory.
  • Cluso99 wrote: »
    "@" must be used when referring to a label of an address in hub, BUT must not be used if the label is the address (hub or otherwise) of the target in a CALL/JMP/DJNZ/etc, at least when used with spin2.

    BTW it's not true that "@ must be used when referring to a hub address". That's only the case for labels with two addresses, i.e. labels in an ORG section where the ordinary address is in cog memory. For labels after ORGH the @ is optional and does nothing. Not that that helps you. Chip's Spin2 compiler is like his Spin1 compiler, the pasm code has no way to access the hub addresses of labels at compile time. It has to be done at run time.

    Fastspin, like bstc and homespun, does have a way to do this.
  • AribaAriba Posts: 2,690
    ozpropdev wrote: »
    Ariba wrote: »
    Cluso99 wrote: »
    ...
    _HubTxStrVer  mov       lmm_p,  ##_str_vers             ' send version string, $00 terminated
    _HubTxStrVer  mov       lmm_p,  ##@_str_vers             ' send version string, $00 terminated
    

    How do we solve this in spin2 for the pasm code ???

    I think you need to use LOC so the compiler can calculate the address relative:
    _HubTxStrVer  loc       lmm_p,  #_str_vers              ' send version string, $00 terminated
    
    But I have not tried it, just my guess.

    Andy

    LOC can only be used with PA/PB/PTRA/PTRB registers.


    Okay, so he could do it with two instructions:
    _HubTxStrVer  loc       pa   ,  #_str_vers              ' send version string, $00 terminated
                  mov       lmm_p,  pa
    
    These are two longs, just like the version with mov ..,##

    But better would be to modify the string output routine to use ptra or ptrb.
  • ElectrodudeElectrodude Posts: 1,660
    edited 2020-04-22 00:05
    Hi Chip, could you please make PNut's -c mode show compiler errors on the console instead of just failing silently? I'm using an external editor on Linux and trying to use PNut through Wine, and command-line mode isn't really useful if it doesn't ever show error messages. I want to be able to use both PNut and Fastspin; I'm currently only using Fastspin.

    Also, if it's easy, could you make PNut able to handle Unix line endings (i.e. just LF ($0a) without CR) in addition to Windows' CRLF line endings? Right now, PNut just ignores the LFs - it thinks the whole file is one long line. I don't mind if the display is wrong - I only need it to work in command-line mode. This isn't as important as having -c show error messages, since I can have my editor use the Windows line endings.

    Thanks!
  • Cluso99Cluso99 Posts: 18,069
    edited 2020-04-22 01:21
    Ariba wrote: »
    ozpropdev wrote: »
    Ariba wrote: »
    Cluso99 wrote: »
    ...
    _HubTxStrVer  mov       lmm_p,  ##_str_vers             ' send version string, $00 terminated
    _HubTxStrVer  mov       lmm_p,  ##@_str_vers             ' send version string, $00 terminated
    

    How do we solve this in spin2 for the pasm code ???

    I think you need to use LOC so the compiler can calculate the address relative:
    _HubTxStrVer  loc       lmm_p,  #_str_vers              ' send version string, $00 terminated
    
    But I have not tried it, just my guess.

    Andy

    LOC can only be used with PA/PB/PTRA/PTRB registers.


    Okay, so he could do it with two instructions:
    _HubTxStrVer  loc       pa   ,  #_str_vers              ' send version string, $00 terminated
                  mov       lmm_p,  pa
    
    These are two longs, just like the version with mov ..,##

    But better would be to modify the string output routine to use ptra or ptrb.

    You have to remember that the concept for the routines in ROM (and now being replaced in the exact ROM position) was to not use any resources if possible so as to allow the calling program free rain over the resources. Hence PA/PB/PTRA/PTRB etc were specifically not used. Only 16 cog registers were used which were $1E0-$1EF which were the top free 16 registers. Then spin grabbed them, hence the ROM code needing to be replaced.

    And I repeat again, this code compiles as pasm in both pnut (pasm only) and fastspin but it doesn't compile correctly in pnut if spin2 is used!
  • Cluso99Cluso99 Posts: 18,069
    edited 2020-04-22 04:10
    Question: Can I do this and if so how?

    PR0 := "ABCD"
    instead of
    PR0 := ("A"<<24) + ("B"<<16) + ("C"<<8)+"D"
    or
    PR0 := $41424344

    This would load register PR0 (ie $1D8) with the long $41_42_43_44 or $44_43_42_41 (not sure which way around)

  • Cluso99Cluso99 Posts: 18,069
    edited 2020-04-25 02:16
    Chip,
    The following instructions are being compiled as a relative addresses but the address at runtime is incorrect.
    CON
      _HubTx           = $fcaf0     ' Sends lmm_x           (can be up to 4 bytes)
    ...
                  call      #$fcaf0                         ' << bug? encoded as relative C8 C6 BF FD
                  call      #_HubTx                         ' << bug? encoded as relative C4 C6 BF FD
    
    Surely, when a specific address is specified, shouldn't it compile to an absolute address?

    BTW forcing absolute addressing does work
                  call      #\$fcaf0                         ' << force absolute addressing
                  call      #\_HubTx                         ' << force absolute addressing
    
  • evanhevanh Posts: 16,032
    Every label is a specific address when assembling.
  • AribaAriba Posts: 2,690
    For an absolute call use:
                  call      #\$fcaf0                         ' << bug? encoded as relative C8 C6 BF FD
                  call      #\_HubTx                         ' << bug? encoded as relative C4 C6 BF FD
    

    See also here
  • Cluso
    For immediate-branch and LOC address operands, "#" is used before the
    address. In cases where there is an option between absolute and relative
    addressing, the assembler will choose absolute addressing when the branch
    crosses between cog and hub domains, or relative addressing when the
    branch stays in the same domain. Absolute addressing can be forced by
    following "#" with "\".

    Your NOT crossing a domain so your call's will always be treated as relative.

Sign In or Register to comment.