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

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

1102103105107108123

Comments

  • @evanh said:

    @ersmith said:
    @JRoark I'm pretty busy right now, but I'm always open to code submissions...

    Here's a tidied up spin2 edition, if that helps. It's good to use as is of course. Maybe just put in with example files.

    EDIT: Updated return value comments.

    Thank you for that, @evanh !

  • RaymanRayman Posts: 14,755
    edited 2022-12-20 15:01

    I meant that not having "#include <stdio.h>" doesn't really help because code that isn't used is cut from final binary anyway....

    But, I guess that's just the header anyway, so maybe it doesn't matter...

  • evanhevanh Posts: 16,032
    edited 2022-12-20 15:08

    My pleasure. If I convince Chip to add a clean way of coding hubexec'd pasm routines then I'll come back and put that in for those two divide functions as well.

    I could still add a conditional compile for Flexspin's asm/asmend directives. That would enable hubexec with Flexspin right now. But conditional compiling looks messy in the source code and it's not a big advantage to use hubexec so I decided to bug Chip first.

  • RaymanRayman Posts: 14,755
    edited 2022-12-23 19:59

    @ersmith Couple questions, nothing that important...

    Have a Spin2 SPI code, called from a C program, to start an assembly cog. But, it stopped working at some point.
    Problem seems to be that code is expecting the variables; Dpin, Cpin, Value, and pValue to be consecutive in hub ram, but seems that pValue is somewhere else...
    I'm not really sure if this is documented to be the case that they are consecutive, but think it used to be and is in Parallax version Spin1 (and Spin2?)
    Not really sure if this qualifies as bug or not, might just be bad programming style :)
    Easily fixed, now that I found the problem..

    Update: Looks like @Value is before @Dpin and @Dpin, @Cpin, @pValue are in order...

    PUB Read8(Dpin, Cpin): Value|pValue 'read 8 bits
        pValue:=@Value 'this will be the last parameter
        SendCommand(Read8_,@Dpin)
        'wait for this command to finish
        repeat
        until command==0
        return Value
    

    Other question: Should assembly debug statements work in a Spin2 file embedded in a C program?
    Never mind. See now that need to use "-gbrk"

  • @Rayman : In Spin1 the return value always comes first in memory, then the parameters, then the local variables. It looks like Chip changed this for Spin2 (yet another incompatibility, sigh!) and unfortunately I didn't realize this. Flexspin still uses the Spin1 memory layout.

  • JRoarkJRoark Posts: 1,215
    edited 2022-12-24 16:05

    @ersmith I just installed Version 5.9.22-beta-v5.9.21-14-g557ac5f1 Compiled on: Dec 17 2022. Editing/compilation works fine, but when I attempt to download and run to a P2-ES Rev C I get the following error:

    wrong # args: should be "term_insert s"
    wrong # args: should be "term_insert s"
    while executing
    "term_insert [format %[set space_rem_on_line]s ""] $tag_list"
    (procedure "term_clear_to_eos" line 15)
    invoked from within
    "term_clear_to_eos"
    (procedure "process_ansi_csi" line 56)
    invoked from within
    "process_ansi_csi $cur_save_str $c"
    (procedure "term_recv" line 193)
    invoked from within
    "term_recv $c"
    (procedure "::TkTerm::Terminal_Data" line 10)
    invoked from within

    "::TkTerm::Terminal_Data "

    After that... the serial terminal is hung. Reverting to 5.9.21 using the same FlexBASIC code gives successful compilation and download/run, so it seems like this is a 5.9.22 beta thing. FWIW, this is with the Options->Use Internal ANSI Terminal selected.

    EDIT: No idea why the forum software is doing monkey-business with the font/bolding. I swear I'm not screaming. :blush:

  • RaymanRayman Posts: 14,755
    edited 2022-12-24 19:27

    @ersmith Thanks for the explanation. Not sure this kind of thing is documented anywhere, but maybe it is.
    I think the code was working at one point this way, but I guess that must have been with the PropTool.
    Easily fixed, now that I see what's wrong. But, maybe I should fix it in a way that works with both PropTool and Flexspin...

    Think the idea was adapted from P1 code. But there, you didn't have to specify a return value, even if you had one. Must be how that worked without confusion...

    Fixed it like this to work with both PropTool and Flexspin:

    PUB Read8(Dpin, Cpin): Value|pValue 'read 8 bits
        'Note:  24Dec22:  Had to adapt code to work with both FlexProp and PropTool.
        '       FlexProp puts Value before Dpin in memory, but PropTool leaves Value after Cpin
        pValue:=Value:=@Value 'This way, the third variable will have @Value in both FlexProp and PropTool
        SendCommand(Read8_,@Dpin)
        'wait for this command to finish
        repeat
        until command==0
        return Value
    
  • @JRoark : a typo crept in for responding to one particular ANSI escape sequence. It should be fixed now in 5.9.22. Thanks for the bug report!

  •  warning: Unhandled debug format uhex_byte_array
    

    @ersmith Is it planned for the near future to implement the byte/word/long array DEBUG commands? They are very useful when dealing with buffers. Or the byte_array can also be used to reverse little-endian to big-endian longs.

  • @ManAtWork said:

     warning: Unhandled debug format uhex_byte_array
    

    @ersmith Is it planned for the near future to implement the byte/word/long array DEBUG commands? They are very useful when dealing with buffers. Or the byte_array can also be used to reverse little-endian to big-endian longs.

    I think they're already handled in -gbrk debugging. Doing them in plain -g debugging is a little hard, because in that version DEBUG gets translated into printf, and there's no printf format for printing arrays.

  • @ersmith said:
    I think they're already handled in -gbrk debugging. Doing them in plain -g debugging is a little hard, because in that version DEBUG gets translated into printf, and there's no printf format for printing arrays.

    Ok, if has to be done by translating them into calls to a function containing a loop. Not too hard but probably more work than necessary. Can I use -gbrk debugging safely when I use C and Spin2 together? I thought there was some problem with printf() and debug() stomping on each others feet. How can I call printf() in a debug()-friendly manner?

  • @ManAtWork said:

    @ersmith said:
    I think they're already handled in -gbrk debugging. Doing them in plain -g debugging is a little hard, because in that version DEBUG gets translated into printf, and there's no printf format for printing arrays.

    Ok, if has to be done by translating them into calls to a function containing a loop. Not too hard but probably more work than necessary. Can I use -gbrk debugging safely when I use C and Spin2 together? I thought there was some problem with printf() and debug() stomping on each others feet. How can I call printf() in a debug()-friendly manner?

    I don't think there's any inherent conflict between gbrk debugging and printf, although if you call debug() from a different COG while a printf is in progress it can interrupt the printf -- the characters should be OK but the debug message will come out in the middle of the printf string.

  • RaymanRayman Posts: 14,755
    edited 2022-12-29 20:10

    @ersmith What's going on with "Field"? Looks like it's a reserved word inside debug statements, but should we still be able to use it elsewhere?

    Seems all my Spin2 VGA type codes inherited the name "Field" as the start of the field loop. This gives an error now in FlexSpin, but not Prop Tool....

    Ok, I see now it's not just for use inside debug statements... But, why doesn't Prop Tool give me an error?

    On a more positive note, just found today that some Gameduino examples that didn't work before are now working. Think all your work on C is definitely making it better.

  • @Rayman said:
    @ersmith What's going on with "Field"? Looks like it's a reserved word inside debug statements, but should we still be able to use it elsewhere?

    Seems all my Spin2 VGA type codes inherited the name "Field" as the start of the field loop. This gives an error now in FlexSpin, but not Prop Tool....

    Ok, I see now it's not just for use inside debug statements... But, why doesn't Prop Tool give me an error?

    On a more positive note, just found today that some Gameduino examples that didn't work before are now working. Think all your work on C is definitely making it better.

    @cgracey made FIELD a reserved word in Spin2. I don't know if Jeff has updated PropTool to have the new PNut yet, but once he does it will be reserved there too.

  • Happy to report that @ersmith changes to the internal Flex terminal seemed to have cured several random oddities! That was a nice holiday gift.

  • @JRoark said:
    Happy to report that @ersmith changes to the internal Flex terminal seemed to have cured several random oddities! That was a nice holiday gift.

    Glad it worked for you, Jeff!

  • Defining a union containing fields with conflicting names causes the compiler to crash or at least exit without an error message and without a hint to a line number where the problem is. Example:

    typedef struct // Reply HLP header starts at long boundary
    {   //rhlp_header                     
        union {
            struct {    // high level protocol (HLP) header
          uint8_t       rply_len;     // number of HLP data bytes (without rply_len)
          uint8_t       rply_type;
                uint16_t    buf_gauge;    // number of FIFO entries
                uint16_t    ref_num;      // trace buffer reference
              uint8_t       status;
                int8_t      rsv;          // padding
                int32_t     data[MAX_NUMAXES];
                uint8_t     inputs[MAX_IO_BYTES];
            };
    
        struct {
          uint8_t       rply_len;     // number of HLP data bytes (without rply_len)
          uint8_t       rply_type;
              uint8_t   version[76];  // Versionsstring für RESCOM
        };
        };
    } Hlp_Reply_Data;
    

    Terminal output:

    Version 5.9.21 Compiled on: Dec 6 2022
    B2M_main.c
    The terminal process "C:\Program Files\Git\bin\bash.exe '--login', '-c', 'flexspin.exe -2 -g -D_BAUD=230400 -Wabs-paths -Wmax-errors=99 B2M_main.c'" terminated with exit code: 2816.

  • @ManAtWork : Thank you for the bug report. I've fixed the crash when duplicate names are defined for anonymous structures in the current github source code (5.9.23).

  • @ersmith : Do method pointers in spin1 have any restrictions that spin2 doesn't?
    The following code:

    obj
    
        ch: "ch1"
    
    pub main() | putchar, getchar
    
        ch.init(@pmethod, @gmethod)
    
        repeat
            if ch.g() == 1
                repeat
                    !outa[56]
    
    pub pmethod(c)
    
        outa[26] := c
    
    pub gmethod(): s
    
        return ina[26]
    

    and the child

    var
    
        long p, g
    
    pub init(pm, gm)
    
        p := pm
        g := gm
    
    pub method1()
    
        p(1)
    
    pub method2(): c
    
        return g():1    ' tried with and without the :1 
    

    fails to build with

    Press ENTER or type command to continue
    Propeller Spin/PASM Compiler 'FlexSpin' (c) 2011-2022 Total Spectrum Software Inc.
    Version 5.9.24-beta-v5.9.23-4-g1b710c54 Compiled on: Jan  2 2023
    mp1.spin
    |-ch1.spin
    mp1.spin:10: error: Object called is not a function
    mp1.spin:10: error: Object called is not a function
    mp1.spin:10: error: Unhandled indirect FUNCALL symbol
    error: bad fixup
    Program size:    1336 bytes
    Variable size:   1048 bytes
    Stack/Free:     30368 bytes
    

    but the equivalent in spin2 builds ok. I haven't yet tried it functionally, but it does seem to build when using the pasm backend.
    I have a zmodem utility that I'd originally written as an #include because I couldn't find a better/less invasive way to integrate it with something like a serial connection, but I recently had an epiphany: rewrite it as an object and point it to putchar() and getchar() methods in the serial object. This has worked great so far in spin2, but when trying to backport it to spin1 I encountered the above build failure. I have a fear it may not be possible due to some technical reason, but hope I'm wrong.
    BTW method pointers have got to be one of the handiest things...it's a really slick way to fix some problems...thanks for adding support for them!

  • @avsa242 : I had intended this to work in Spin1, but it's missing some checks. I'll try to add those soon. In the meantime you can work around it by changing the line

            if ch.g() == 1
    

    to

            if ch.g():1 == 1
    

    (i.e. adding a Spin2 style function return specification to the method pointer call site)

    Just out of curiosity, why backport the code to Spin1? Flexspin can build Spin2 code for the P1, including for P1 bytecode output.

  • avsa242avsa242 Posts: 452
    edited 2023-01-04 13:55

    @ersmith said:
    @avsa242 : I had intended this to work in Spin1, but it's missing some checks. I'll try to add those soon. In the meantime you can work around it by changing the line

            if ch.g() == 1
    

    to

            if ch.g():1 == 1
    

    (i.e. adding a Spin2 style function return specification to the method pointer call site)

    Okay that's simple enough, thanks 👍

    Just out of curiosity, why backport the code to Spin1? Flexspin can build Spin2 code for the P1, including for P1 bytecode output.

    In principle, I guess there's no real reason I couldn't... I know moving my spin1 lib to spin2 has crossed my mind before, as it takes a lot of extra time to maintain both codebases. I suppose any chip-specific bits could then be handled by preprocessor code within the same file.

  • @avsa242 said:

    Just out of curiosity, why backport the code to Spin1? Flexspin can build Spin2 code for the P1, including for P1 bytecode output.

    In principle, I guess there's no real reason I couldn't... I know moving my spin1 lib to spin2 has crossed my mind before, as it takes a lot of extra time to maintain both codebases. I suppose any chip-specific bits could then be handled by preprocessor code within the same file.

    Also note that mixing Spin1 and Spin2 objects should work fine in flexspin, so you could keep your older objects in Spin1 and create newer ones in Spin2 (with, as you say, preprocessor code to handle chip specific code). Of course if you want to interoperate with PropTool this wouldn't work :( but then PropTool doesn't support method pointers in Spin1 at all.

  • Yeah... when I started working on my library I was trying to keep it all compatible with PropTool but not having things like dead code removal, a preprocessor, and now method pointers make it too limiting (that and never had a great experience using it in Wine).

  • ManAtWorkManAtWork Posts: 2,178
    edited 2023-01-05 16:50

    When I start a function in a seperate cog with _cogstart_C() do I have to pay special attention to pass all variables as arguments of the function or does the function have normal access to global variables?

    char motionStack[256];
    BusBuffer* rdBuf;
    
    void MotionLoop (void* arg)
    {
      ... // some code
      printf ("2 rdBuf=%X\n", rdBuf);
      ...
    }
    
    int main (void)
    {
      Startup ();
      rdBuf= bus.GetReadBuf ();
      printf ("1 rdBuf=%X\n", rdBuf);
      _cogstart_C (MotionLoop, 0, motionStack, sizeof(motionStack));
    ...
    }
    

    I ask because I have this strange phenomenon, it outputs

    Cog0  (&ReadBuf) = $1_7324
    1 rdBuf=17324
    Cog5  INIT $0000_0404 $0000_9CFC load
    2 rdBuf=9D88
    

    So the value of rdBuf seems to differ depending on the cog/scope. It could also be that my code accidentally overwrites memory. But before I waste a lot of time I'd like to make sure that I don't do anything fundamentally wrong.

    Edit: Ok, I found out that the global variable rdBuf can be accessed normally. If I put the printf() directly at the beginning of MotionLoop() it prints correctly. But I fear there is another compiler bug. printing it inside a switch/case inside a for loop with all other code commented out shows the wrong value, again. I have to extract a small example program that can demonstrate it. At the moment the code is too complex... I'll be back on saturday.

  • @ManAtWork : Yes, global variables can be accessed by any cog.

    If you're running into mysterious failures with code running in another cog, the first thing you should try is to increase the stack size given to that cog (and all the cogs, for that matter). Stack overflow is a common source of problems with multi-cog code.

  • ManAtWorkManAtWork Posts: 2,178
    edited 2023-01-07 12:40

    @ersmith said:
    @ManAtWork : ...
    If you're running into mysterious failures with code running in another cog, the first thing you should try is to increase the stack size given to that cog (and all the cogs, for that matter). Stack overflow is a common source of problems with multi-cog code.

    That was a good hint. Originally, I set the stack size to 256 bytes because the docs recommended 64 or 128 as minimum and my code doesn't include any recursive or deeply nested calls. It's only a single function calling several other functions without many local variables, I mean less than a dozen ints and pointers but no structures or anything else that would take a serious amount of stack space.

    But indeed, increasing the stack size from 256 to 512 bytes cured the problem :) . So I guess that calling (sub-)functions pushes a lot of registers onto the stack. Anyway, no problem, we just need to be aware of it.

    Edit: After re-inserting the function calls I have commented out I had to increase the stack size to 1024. This would mean that each sub-function call level needed >256 bytes of stack which I find hard to believe. I fear the increased stack only moved the variables further away from a buffer overflow problem somewhere else in my code. I need to debug this further...

  • Wuerfel_21Wuerfel_21 Posts: 5,106
    edited 2023-01-07 15:33

    The recommended stack space isn't 128 bytes, it's 128 longs. 128 bytes are just 32 longs, which are used up surprisingly quick. Each stack frame of a non-leaf function takes 3 longs plus any registers that it needs to save (which is roughly equal to the amount of total locals+arguments). Also, the top-level function of a cog (including main) creates a stack frame even though that's completely pointless.

  • FlexSipn doc (c.pdf) says

     For example:
    static long stack[32];
    id = __builtin_cogstart(somefunc(a, b), &stac
    ...
    The amount of space required for the stack depends on
    code to run, but must be at least 16 longs (64 bytes).
    

    But I don't want to argue, obviously that's not enough.

  • Yeah, I was thinking of the general adage of 128 long stacks, didn't even know the FlexC doc says that. IDK where that 16 long figure comes from, I think that's not actually the bare minimum, but of course is not enough for any serious code.

  • ke4pjwke4pjw Posts: 1,169
    edited 2023-01-07 22:33

    @ManAtWork said:
    But indeed, increasing the stack size from 256 to 512 bytes cured the problem :) . So I guess that calling (sub-)functions pushes a lot of registers onto the stack. Anyway, no problem, we just need to be aware of it.

    Edit: After re-inserting the function calls I have commented out I had to increase the stack size to 1024. This would mean that each sub-function call level needed >256 bytes of stack which I find hard to believe. I fear the increased stack only moved the variables further away from a buffer overflow problem somewhere else in my code. I need to debug this further...

    I just had to extend the allocated stack to 1024 for my watchdog cog. Not sure why either.

    *** Mine wasn't with flexpin, so please ignore ***

Sign In or Register to comment.