Shop OBEX P1 Docs P2 Docs Learn Events
PNut/Spin2 Latest Version (v52 - New MOVBYTS(), ENDIANL(), ENDIANW(), NEXT/QUIT <level>, DEBUG end) - Page 76 — Parallax Forums

PNut/Spin2 Latest Version (v52 - New MOVBYTS(), ENDIANL(), ENDIANW(), NEXT/QUIT <level>, DEBUG end)

1707172737476»

Comments

  • RaymanRayman Posts: 15,721
    edited 2025-08-18 22:19

    Said flash loader could also attempt to load from uSD, if desired, right?
    Could be useful if uSD is on different pins and/or has a power switch.

    Also, could maybe do something fancy like look for a backup boot file if the first one is missing...

    Also, guess this could allow for long file names and directories...

    4-pin uSD booting should be faster. Wonder if that'd make a difference...

  • Wuerfel_21Wuerfel_21 Posts: 5,651
    edited 2025-08-18 22:38

    @Rayman said:
    Said flash loader could also attempt to load from uSD, if desired, right?
    Could be useful if uSD is on different pins and/or has a power switch.

    Only if you can figure out how to hot-patch the SD boot code to do that - a full SD driver is probably too heavy for the 1024 bytes of bootloader space - just use the stock flash bootloader and then make the SD loader be the payload of that.

    @Rayman said:
    4-pin uSD booting should be faster. Wonder if that'd make a difference...

    You can make the SD boot A LOT faster as-is by making _BOOT_P2.BIX a tiny stub that sets the clock, patches some stuff in the ROM code and then pivots into a different boot file. I had one like that:

    CON _CLKFREQ = 300_000_000
    DAT
                  org 0
                  asmclk
                  '' Patch pullup check
                  wrlong #0,##$fc5b4 ' not sure why it fails but ok
                  '' Move filename into place
                  mov $1DC,name+0
                  mov $1DD,name+1
                  mov $1DE,name+2
                  drvh #38 ' Set LED
                  call #$fc578
                  drvl #38 ' Clear LED if fail
                  jmp #$
    
    name          byte "LOADTEST","BIX",0
    

    (as seen, this tries to load LOADTEST.BIX - also note the Pin 38 LED, change or remove that if necessary)
    Booting a large ~400K executable is a lot faster like that.

    You can also compress the executable you're booting. Flexspin and SpinTools have this option built-in, I also made a standalone version

  • ke4pjwke4pjw Posts: 1,231

    I can confirm this is a "me" problem. I am unsure why it does not boot properly, but I will figure it out. A simple program booted correctly from SD.

  • ke4pjwke4pjw Posts: 1,231

    Well, it's working as it should now. Maybe the card was flakey, but all is well now.

    The good news: No code changes for my code to work with PNUT v51a!

  • evanhevanh Posts: 16,779

    Chip,
    I just bumped into something that has changed in recent releases of Pnut. I don't know if this is an explicit change you intended or not. The following compiled and ran when I was compiling with Pnut v46:

        send( "SPI cmode: CPOL=", CPOL + "0", " CPHA=", CPHA + "0", 13,10 )
    

    But now, with Pnut v51a, I need to add an extra set of brackets as per the following:

        send( "SPI cmode: CPOL=", (CPOL + "0"), " CPHA=", (CPHA + "0"), 13,10 )
    

    Otherwise I basically get a syntax error. Pnut v51a reports a missing comma or closing bracket without the edit.

  • cgraceycgracey Posts: 14,285
    edited 2025-10-09 03:54

    There is a new version (v52) of PNut.exe at the top of this thread.

    v52 - 2025.10.08

    • New MOVBYTS(), ENDIANL(), ENDIANW() methods.

    • NEXT/QUIT now allowed to select nesting level of operation.

    • DEBUG(DEBUG_END_SESSION) now ends DEBUG session and exits PNut if -rd was used on command line.

    • New DEBUG Display TERM color commands for added simplicity.

  • @cgracey said:
    There is a new version (v52) of PNut.exe at the top of this thread.

    v52 - 2025.10.08

    • NEXT/QUIT now allowed to select nesting level of operation.

    Blimey! That arrived almost instantly! :smiley:

  • maccamacca Posts: 937
    edited 2025-10-09 10:03

    @cgracey said:

    • NEXT/QUIT now allowed to select nesting level of operation.

    Seems something is broken, I got an error on a simple if/else block:

    Can be reproduced also with the parser.spin2 (and other sources in the PNut package) example.

    Am i missing something ?

    Edit: worst than expected, seems that nothing can be added after a quit statement:

  • @macca Is a number now compulsory ? Does it work with "quit 0" or "quit 1" ?

    (Sure, that would be silly, but just an interesting test / workaround. I'm not able to try it at the moment).

  • maccamacca Posts: 937

    @VonSzarvas said:
    @macca Is a number now compulsory ? Does it work with "quit 0" or "quit 1" ?

    (Sure, that would be silly, but just an interesting test / workaround. I'm not able to try it at the moment).

    Ah, yes, with quit 1 it works (quit 0 is not valid since must be 1 to 16).

  • Oh goody. Might just need the default case adding back into the compiler.

    @cgracey
    May we have an override for "quit" and "next" without a parameter to behave like they used to, equivalent to "quit 1" and "next 1" ?

  • cgraceycgracey Posts: 14,285
    edited 2025-10-09 14:08

    Sorry, Guys!

    I see the problem. It's in my parsing of what comes after NEXT or QUIT. I need to back up when there is a line end, indicating there will be no constant.

    I will have this straightened up in a few hours.

  • cgraceycgracey Posts: 14,285
    edited 2025-10-10 00:09

    The new v52 is now posted on the OBEX and on Github.

    https://obex.parallax.com/obex/pnut-spin2-latest-version/

    NEXT and QUIT do not require integers after them, but an integer is needed if you want to NEXT/QUIT from outside your current REPEAT block. That integer would need to be a value of 2 or more.

  • cgraceycgracey Posts: 14,285
    edited 2025-10-10 00:14

    I added a new file into the .zip called PointerFlexibility.spin2. It gives coding examples of how you can use byte/word/long pointers. The same basic rules apply to structure pointers, as well.

    Here is that file, in case anyone wants to get a quick tour of pointers:

    {Spin2_v52}
    
    pub go() | ^byte p, byte buff[20]       'declare a byte pointer and a 20-byte buffer
    
      [p] := @buff                          'point the pointer to the buffer
    
      p[++].byte := $50                     'write a byte into the buffer, step pointer
      p[++].long := $77777777               'write a long, step pointer
      p[++].word := endianw($BEEF)          'write a big-endian word, step pointer
      p[++].byte := $01                     'write a byte, step pointer (.byte is for clarity, not needed)
      p[++].byte := $02                     'write a byte, step pointer
      p[++].byte := $03                     'write a byte, step pointer
      p[++].long := $FFFFFFFF               'write a long, step pointer
    
      debug(uhex_byte_array_(@buff,20))     'show the buffer
    
      [--]p.word := $5555                   'back up and write a word
      [++]p.word := $AAAA                   'move ahead and write a word
    
      debug(uhex_byte_array_(@buff,20))     'show the buffer
    
      p := $22                              'write a byte
      p[-1] := $33                          'write a byte at [-1]
    
      debug(uhex_byte_array_(@buff,20))     'show the buffer
    
      p++                                   'inc byte
      p[1]--                                'dec byte at [1]
    
      debug(uhex_byte_array_(@buff,20))     'show the buffer
    
      p~~                                   'set byte
      [--]p.long[-1].[31..28]++             'back up long pointer, increment top nibble of long at [-1]
    
      debug(uhex_byte_array_(@buff,20))     'show the buffer
    
    
    '
    ' Pointers are longs and they can be read/modified/written by putting brackets around them:
    '
    ' [p]                   'the actual pointer value (not the data being pointed to)
    ' @[p]                  'the address of the actual pointer value
    '
    '
    ' Once assigned, pointers can be used to read/modify/write the data they point to in
    ' these root syntax forms:
    '
    ' p                     'r/m/w the data being pointed to
    ' [++]p                 'pre-inc pointer by size, then r/m/w the data being pointed to
    ' [--]p                 'pre-dec pointer by size, then r/m/w the data being pointed to
    ' p[++]                 'r/m/w the data being pointed to, then post-inc pointer by size 
    ' p[--]                 'r/m/w the data being pointed to, then post-dec pointer by size 
    '
    '
    ' Any of these root syntax forms can be appended with an optional size override,
    ' an optional index, and an optional bitfield, in that order.
    '
    ' An optional size override starts with a period followed by BYTE/WORD/LONG:
    '
    '       .BYTE           'sets the data size to byte, regardless of the pointer data size
    '       .WORD           'sets the data size to word, regardless of the pointer data size
    '       .LONG           'sets the data size to long, regardless of the pointer data size
    '
    ' ...followed by an optional index in brackets:
    '
    '       [index]         'index gets scaled for byte/word/long addressing
    ' 
    ' ...followed by an optional bitfield, which is a period followed by a bitfield in brackets:
    '
    '       .[bitfield]     'selects a portion of the byte/word/long to read/modify/write
    '
    
  • VonSzarvasVonSzarvas Posts: 3,615
    edited 2025-10-10 05:01

    @cgracey said:
    The new v52 is now posted on the OBEX and on Github.

    https://obex.parallax.com/obex/pnut-spin2-latest-version/

    NEXT and QUIT do not require integers after them, but an integer is needed if you want to NEXT/QUIT from outside your current REPEAT block. That integer would need to be a value of 2 or more.

    .

    NEXT and QUIT can each be followed by an integer value 1..16 to alter the nesting level at which they are to occur. If no integer value is expressed, the default value of 1 is used, which means the current nesting level, The value 2 would mean the outer nesting level, while three would mean the next outer nesting level, and so on.

    What is the intended behavior when the nesting level integer exceeded the number of levels?
    For example, would QUIT maxLevel+1 be the same as QUIT maxLevel ? (Or should that throw a compiler error- or warning at least?...)

  • cgraceycgracey Posts: 14,285
    edited 2025-10-10 06:29

    The compiler will error if you try to go too many levels out. It knows the REPEAT nesting depth.

    I have a question:

    Rather than using integers 1..16 to specify level, might 0..15 be better? It would go like this:

    0 = This REPEAT block, no change in level (the default for NEXT/QUIT)
    1 = The first-outer REPEAT block
    2 = The second-outer REPEAT block

    Would that be better? If I change it, I should do it soon, before any serious code gets written by anyone.

    That feels a lot better to me. The way it is has been bugging me.

  • The languages I've used this with before, PHP and maybe Bash, both use 1-indexed. Personally I wouldn't change it. It's done; move on and conquer!

    Really it's just a human language issue - how we explain the feature in docs could be worded to make either way seem like the most natural.

  • @cgracey said:
    Rather than using integers 1..16 to specify level, might 0..15 be better? It would go like this:

    0 = This REPEAT block, no change in level (the default for NEXT/QUIT)
    1 = The first-outer REPEAT block
    2 = The second-outer REPEAT block

    Would that be better? If I change it, I should do it soon, before any serious code gets written by anyone.

    Yes, I think it would be better since it represents the number of levels to go back, also may I suggest to use (or allow) negative numbers ? I think that quit -n better represents quit back n level(s).

    Even better would be to have some kind of label to clearly indicate what repeat level is referred, not sure what a good syntax may be, something like repeat : label maybe.

    Also, can you check if the following snippet generates the correct bytecode ?

    {Spin2_v52}
    PUB main() | a, b, c
    
        repeat a from b to c
            quit
            next
            repeat a from b to c
                quit 2
                next 2
            a++
    

    I had just a quick look and probably I miss something, but seems to me that the inner next 2 statement doesn't pop the inner loop stack, quit 2 correctly pops both the inner and outer stacks. Today I'm a bit busy so I may not be able to look at this with more details.

    Thanks.

  • @macca said:
    Even better would be to have some kind of label to clearly indicate what repeat level is referred, not sure what a good syntax may be, something like repeat : label maybe.

    Yes, named breaks are good because you can't get the number wrong and can't misread it. Languages like Rust do it this way.

Sign In or Register to comment.