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

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

16465666769

Comments

  • @RossH said:
    Did you read the links I posted?

    The difference in fread(buf, 1000, 1, stream) and fread(buf, 1, 1000, stream) is, that in the first case you get only one chunk of 1000 bytes or nothing, if the file is smaller and in the second case you get everything in the file less than and up to 1000 bytes.

    That is not actually the case. fread is allowed to read a partial elements (and not tell you about it). It's just broken.

  • RossHRossH Posts: 5,476
    edited 2024-12-09 01:27

    @Wuerfel_21 said:

    @RossH said:
    Did you read the links I posted?

    The difference in fread(buf, 1000, 1, stream) and fread(buf, 1, 1000, stream) is, that in the first case you get only one chunk of 1000 bytes or nothing, if the file is smaller and in the second case you get everything in the file less than and up to 1000 bytes.

    That is not actually the case. fread is allowed to read a partial elements (and not tell you about it). It's just broken.

    It is not "broken". What an implementation does in such error situations is "indeterminate". But that's entirely normal and to be expected.

    But what the function returns even in such cases is perfectly well defined.

  • But that's not an error, that's just what the function does when it reaches the end of the file. It reads the partial record into your buffer and then forgets about it. That's rarely useful behaviour that unnecessarily adds a divide instruction where it isn't needed.

    C library has lots of stuff that's just dumb or broken (gets, anyone?), it's fine, they designed it in the stone age when no one really knew how to do it better.

  • RossHRossH Posts: 5,476

    @Wuerfel_21 said:

    C library has lots of stuff that's just dumb or broken (gets, anyone?), it's fine, they designed it in the stone age when no one really knew how to do it better.

    There's good reasons why C is still wildly popular, despite its flaws (which few would deny). Even on the Propeller - which is a bleeding edge microcontroller - C is still the most functional language on offer.

    However, this is now getting off-topic. If you want to continue the discussion I'm happy to do so, but I'd suggest starting a separate thread.

  • cgraceycgracey Posts: 14,206
    edited 2024-12-09 07:01

    Jon, I got this fixed. It was an oversight that it didn't work, in the first place. I will get a new v47 out soon with this fix.

  • cgraceycgracey Posts: 14,206
    edited 2024-12-09 11:08

    I uploaded a new v47 into the OBEX (see top of thread).

    PNut_v47.exe can now load and run binary files from the command line.

    I also added the #register syntax, so #pr0 returns $1D8 as expected, instead of an error.

  • JonnyMacJonnyMac Posts: 9,156

    Is this to say that the -c option compiles a binary image that is identical to what would be found in the Flash after it was written by the loader? In the past, the binary image portion had holes that were filled in by the flash loader. I need a complete binary that I can send to a customer who will put in on an SD card for self-updating.

  • cgraceycgracey Posts: 14,206
    edited 2024-12-09 22:44

    @JonnyMac said:
    Is this to say that the -c option compiles a binary image that is identical to what would be found in the Flash after it was written by the loader? In the past, the binary image portion had holes that were filled in by the flash loader. I need a complete binary that I can send to a customer who will put in on an SD card for self-updating.

    The flash loader that is prepended to the compiled image programs the flash and prepends a loader that always pulls the main app code in on boot-up.

    To compile with flash:

    PNut_v47 filename.spin2 -cf

    That makes a binary filename.bin file.

    Then, to download the binary and have it program the flash:

    PNut_v47 filename.bin -b

    So, you give the customer the .bin file and PNut app, plus maybe a .bat file to execute the command above. They plug the PropPlug into your product and then run the .bat file to do the firmware update.

  • JonnyMacJonnyMac Posts: 9,156
    edited 2024-12-10 01:46

    So, you give the customer the .bin file and PNut app,

    No. I want to give my customer a clean BIN file that they can put onto the SD card in their product. One boot-up the app looks for the update and copies it to flash if its there (the app then removes it from the SD).

    Please, just give us a clean BIN like Propeller Tool does for the P1.

    In the P1 -- and what we want to do with the P2 -- is download the BIN file via XBee to the product (which has an SD). For that reason I want dead code removal and an image that will just run (like the P1 BIN file)

  • roglohrogloh Posts: 5,837

    Agree that it's a far nicer experience for an end user customer if they can avoid needing to install vendor or other special software tools for doing updates. Especially if there are lots of them and they are not necessarily especially tech savvy. I'd expect more of them would be able to put a downloaded/emailed file attachment onto an SD card but not all would necessarily have Prop-Plugs or know anything about what PNut/Loadp2 is etc.

  • roglohrogloh Posts: 5,837

    @JonnyMac said:
    For that reason I want dead code removal and an image that will just run.

    Dead code removal +100. Then I can finally start to write a sample graphics lib that won't have to bloat the P2.

  • RaymanRayman Posts: 14,744

    Agree with @JonnyMac
    Finding the flashing very confusing/difficult, especially with non-Parallax boards/software.
    Seems like was so much easier with P1.

  • @Rayman said:
    Finding the flashing very confusing/difficult, especially with non-Parallax boards/software.

    Recently loadp2 gained a -FLASH flag that JustWorksTM. It was slightly silly before that.

    The confusion here stems from the fact that the P2 ROM does not just load the whole flash image automatically. It only reads the first block and then that has to contain a bootloader stub to read the rest.
    So the binary that comes out of the compiler is useful for serial download or _BOOT_P2.BIX SD boot, but can't just be dumped into a flash chip as-is.
    So @JonnyMac is actually asking for the opposite of a "clean binary that just runs", one that has extra guff specific to Chip's flash boot stub prepended onto it, so he can dump it into flash without the (trivial) extra work of figuring out the file size and checksum.
    For the particular usecase of self-updating the flash in the field, I'd really urge for modifying the boot stub so after a failed update it can fall back to a second copy of the software instead of just failing to boot.

  • roglohrogloh Posts: 5,837

    @Wuerfel_21 said:

    @Rayman said:
    Finding the flashing very confusing/difficult, especially with non-Parallax boards/software.

    Recently loadp2 gained a -FLASH flag that JustWorksTM. It was slightly silly before that.

    Hopefully it now allows image sizes up to the full 512kB.

  • RaymanRayman Posts: 14,744

    Thanks @Wuerfel_21
    Remembering that now…

    Anybody know why the P2 rom doesn’t load like the P1 rom?

  • RaymanRayman Posts: 14,744
    edited 2024-12-09 23:58

    Oh, maybe for speed?
    Perhaps starting in RC clock mode would make boot too slow?

    That must be it.

  • @Rayman said:
    Thanks @Wuerfel_21
    Remembering that now…

    Anybody know why the P2 rom doesn’t load like the P1 rom?

    IIRC Making it more tolerant to different flash chip types + more flexibility in how the data is loaded.
    The way that the P1 does it is kinda weird, too. It always launches into the Spin interpreter, so if you want to run your own ASM you need at least the tiniest bit of spin bytecode to make it happen.

  • RaymanRayman Posts: 14,744

    Ok, I’m still with @JonnyMac though
    Just give me a binary that I can copy to flash myself.

    That part is not hard.

  • ersmithersmith Posts: 6,068

    @rogloh said:

    @Wuerfel_21 said:

    @Rayman said:
    Finding the flashing very confusing/difficult, especially with non-Parallax boards/software.

    Recently loadp2 gained a -FLASH flag that JustWorksTM. It was slightly silly before that.

    Hopefully it now allows image sizes up to the full 512kB.

    It allows bigger image sizes, in fact (riscvp2 can run code directly from flash, which was one impetus for the -FLASH flag).

  • cgraceycgracey Posts: 14,206

    @rogloh said:

    @JonnyMac said:
    For that reason I want dead code removal and an image that will just run.

    Dead code removal +100. Then I can finally start to write a sample graphics lib that won't have to bloat the P2.

    Rogloh, are you interested in Spin2 method removal, or PASM code removal?

  • RaymanRayman Posts: 14,744
    edited 2024-12-10 01:53

    Any chance it’s possible to have one binary that can be loaded by serial or directly to flash?

  • JonnyMacJonnyMac Posts: 9,156

    @Rayman said:
    Ok, I’m still with @JonnyMac though
    Just give me a binary that I can copy to flash myself.

    That part is not hard.

    I proved it isn't by writing a small Python program that removes the flash-writing header and plugs the holes left in the code (these must be plugged so the P2 will boot the code from flash).

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    #  p2img.py
    #  -- started 01 SEP 2024
    #  -- updated 01 SEP 2024
    #
    #  By Jon McPhalen with big assists from
    #  - w3schools.com
    #  - stackoverflow.com
    #  - ChatGPT
    #
    
    import sys
    import os
    import struct
    import time
    
    
    def process_file(infile):
        outfile = os.path.splitext(infile)[0]+'.p2img'
        print(f'Converting {infile} to {outfile}')
    
        filesize = os.path.getsize(infile)
        print(f'- Input file size is {filesize} bytes')
    
        imgsize = filesize - 0x160
        print(f'- Output file size is {imgsize} bytes')
    
        sectors = (imgsize + 4095) // 4096
        print(f'- P2 image requires {sectors} flash sectors in P2')
    
        pages = (imgsize + 255) // 256
        print(f'- P2 image occupies {pages} flash pages')
        print()
    
        print('Loader Segment Touch-up')
    
        applongs = (imgsize - 0x90) // 4
        print(f'- ${applongs:08X} longs in application segment')
    
        # open file
        # skip past flash programmer segment
        # convert to list of longs
    
        with open(infile, 'rb') as file: 
            file.seek(0x160) 
            ibytes = file.read() 
    
        n = len(ibytes) // 4  
        ilongs = list(struct.unpack(f'{n}I', ibytes))
    
        # calculate & neg sum of longs in application 
    
        appsum = 0
        for x in range(0x24, len(ilongs)):
            appsum += ilongs[x]
    
        appsum = 0x100000000 - (appsum & 0xFFFFFFFF)       # -appsum (32-bit)
    
        print(f'- ${appsum:08X} is the sum of application longs')
    
        # modify loader image to calculate final loader sum
    
        ilongs[0x20] = applongs
        ilongs[0x21] = applongs
        ilongs[0x22] = appsum
    
        loadersum = 0
        for x in range(0, 256):
            loadersum += ilongs[x]
    
        loadersum = 0x100000000 - (loadersum & 0xFFFFFFFF) # -loadersum (32-bit)
    
        print(f'- ${loadersum:08X} is the loader sum')
    
        # update loader sum and validate checksum
    
        ilongs[0x23] = loadersum
    
        checksum = 0
        for x in range(0, 256):
            checksum += ilongs[x]
    
        checksum &= 0xFFFFFFFF
    
        print(f'- ${checksum:08X} is the checksum')
    
        if checksum == 0x706F7250:
            print('- Pass!')
        else:
            print('- Fail... Aborting.')
            return -1
    
        # convert modified longs to bytes and write to output file
    
        obytes = struct.pack(f'{len(ilongs)}I', *ilongs)
    
        with open(outfile, 'wb') as file:
            file.write(obytes)
    
        print('- Conversion complete!')
    
        time.sleep(0.2)                                # let terminal finish
    
        return 0
    
    
    def check_file(fname):
        if os.path.exists(fname):
            return 0
        else:
            print(f'Error: {fname} not found')
            return -1
    
    
    def show_help():
        print('P2IMG\nConvert PNut Binary to P2IMG file')
        print('Error: Invalid number of arguments') 
        print('-- Use: python p2img.py IN_FILE')
    
    
    def main(args):
        if len(args) == 2:  
            if check_file(args[1]) != 0:
                return -2
            if process_file(args[1]) == 0:
                return 0
            else:
                return -3
        else:
            show_help()    
            return -1
    
    
    if __name__ == '__main__':
        sys.exit(main(sys.argv))
    
    
  • ke4pjwke4pjw Posts: 1,169

    I think what Jon wants is this:

    The Flash Image, not a Binary Image. I use a Binary image named _BOOT_P2.BIX to boot my light controllers. He needs an image that can be copied directly to flash.

  • roglohrogloh Posts: 5,837

    @cgracey said:

    @rogloh said:

    @JonnyMac said:
    For that reason I want dead code removal and an image that will just run.

    Dead code removal +100. Then I can finally start to write a sample graphics lib that won't have to bloat the P2.

    Rogloh, are you interested in Spin2 method removal, or PASM code removal?

    Well primarily SPIN2 method removal, but automatically based on what is called in the object hierarchy, not done by finely grained control with a conditional #ifdef for every method for example, that's too tedious at that level once the size of the library gets very large. Hopefully any inline PASM defined in these methods could also be culled.

    For example if we wanted to make a graphics library that contains multiple methods for drawing items such as points, circles, lines, and rectangles, and a bunch of other drawing capabilities, and the client application code just so happens to only ever draw rectangles, we don't want every single library method to be included in the build.

    Flexspin already removes methods that are never referenced, but PNut does not do that and just you get everything defined in the object, creating code bloat for library style objects. Bloat like that would turn people off using these larger libraries, especially when memory constrained so no one can really provide these libraries with the expectation that people will use them. The only solution right now is to only release these to operate under flexspin (which I'd prefer not to do).

  • cgraceycgracey Posts: 14,206
    edited 2024-12-10 08:36

    @ke4pjw said:
    I think what Jon wants is this:

    The Flash Image, not a Binary Image. I use a Binary image named _BOOT_P2.BIX to boot my light controllers. He needs an image that can be copied directly to flash.

    Understood. PNut is currently saving a raw binary image file if you just use "filename -c".

    I didn't write the uSD loader that is in the P2 ROM, so I am not sure how it works, but my understanding is that if you put a binary file on a formatted SD card called "_BOOT_P2.BIX", it will boot from that.

    Perhaps this does not answer your question, though.

  • maccamacca Posts: 806

    Self Promotion ON

    Just to remember that Spin Tools IDE has most of the features you are looking for, unused method removal, P2 flash image export (thanks to @JonnyMac advice), preprocessor, and many others.

    I know that PNut is the reference implementation and officially supported, and that Spin Tools IDE may be a bit behind the latest implementations, may show some bugs, certainly is not perfect, but I'm doing my best to make it work realiably and better than anything else. So, give it a try.

    Self Promotion OFF

  • cgraceycgracey Posts: 14,206

    @rogloh said:

    @cgracey said:

    @rogloh said:

    @JonnyMac said:
    For that reason I want dead code removal and an image that will just run.

    Dead code removal +100. Then I can finally start to write a sample graphics lib that won't have to bloat the P2.

    Rogloh, are you interested in Spin2 method removal, or PASM code removal?

    Well primarily SPIN2 method removal, but automatically based on what is called in the object hierarchy, not done by finely grained control with a conditional #ifdef for every method for example, that's too tedious at that level once the size of the library gets very large. Hopefully any inline PASM defined in these methods could also be culled.

    For example if we wanted to make a graphics library that contains multiple methods for drawing items such as points, circles, lines, and rectangles, and a bunch of other drawing capabilities, and the client application code just so happens to only ever draw rectangles, we don't want every single library method to be included in the build.

    Flexspin already removes methods that are never referenced, but PNut does not do that and just you get everything defined in the object, creating code bloat for library style objects. Bloat like that would turn people off using these larger libraries, especially when memory constrained so no one can really provide these libraries with the expectation that people will use them. The only solution right now is to only release these to operate under flexspin (which I'd prefer not to do).

    Method removal may be reasonably simple to achieve. I think it would look like this:

    • Method dependencies are any of the following occurrences within PUB/PRI methods:

    method()
    object{[]}.method()
    @method
    @object{[]}.method

    1) Identify all inter-method dependencies within each file, starting from each PUB method.

    2) Identify all inter-object dependencies within each file by noting which PUB/PRI methods referenced which child OBJects' PUB methods.

    3) After top-level compilation (compilation started at the bottom levels), a complete list of all dependencies can be assembled, revealing dead objects and methods within each file.

    4) Recompile, but this time skip over all dead OBJ's, PUB's, and PRI's in each file.

    Maybe it would be good to also allow for local indented CON/VAR/DAT sub-blocks to be defined within PUB/PRI blocks, so that they could be skipped, too, along with their associated unused methods.

    Not sure if this is a complete approach, but it might be.

  • roglohrogloh Posts: 5,837
    edited 2024-12-10 10:49

    It's a starting approach, which is good. Would the inline PASM blocks also get removed if the method defining them goes away? I take it that code is stored in the bytecode for the method, not tacked onto some DAT section, although I don't know the internals.

    Perhaps the conditional pre-processor work can also be part of it somehow if the file is going to need to be parsed multiple times anyway, assuming it can be leveraged. If not, keep it separate.

  • cgraceycgracey Posts: 14,206

    @rogloh said:
    It's a starting approach, which is good. Would the inline PASM blocks also get removed if the method defining them goes away? I take it that code is stored in the bytecode for the method, not tacked onto some DAT section, although I don't know the internals.

    Perhaps the conditional pre-processor work can also be part of it somehow if the file is going to need to be parsed multiple times anyway, assuming it can be leveraged. If not, keep it separate.

    Yes, inline PASM code is inserted right into the method code, not a DAT section.

  • RaymanRayman Posts: 14,744

    @ke4pjw said:
    I think what Jon wants is this:

    Is this true? Does the "Save Flash File" create a file that can be directly copied into the flash boot chip without modification?

Sign In or Register to comment.