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

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

1101102104106107122

Comments

  • evanhevanh Posts: 15,967

    @ersmith said:

    @evanh said:
    With 5.9.21, I'm getting some extraneous emitted text when -gbrk is specified. It looks like maybe the baud is wrong with presumably the [COG0] startup message is being emitted. I'm defining DEBUG_BAUD as 230400.

    What language are you using? Do you have some sample cod you can share? It could be a case problem, if it's in C.

    Source attached.

    If all else fails put -D_BAUD=230400 on the command line; that's the way FlexProp defines the baud and it always seems to work.

    Yep, that's it. I now get the typical initial debug message:

    Cog0  INIT $0000_0000 $0000_0000 load
    Cog0  INIT $0000_0404 $0000_0000 load
    
    Text=Hello World    len=11
    

    So I guess the enum ain't working.

    c
    c
  • @ersmith said:

    The following simple program should print "Text=Hello World len=11"

    It does for me using FlexProp 5.9.21. Which version were you trying it with?

    Ok, thanks. I've just upgraded from 5.9.20 to 5.9.21 and I can confirm that it works as expected, now. My much bigger program ported from ARM C source code which relys on some statically initialized data now also works, again.
    :)

  • @evanh : Ah, I see now: DEBUG_BAUD is a Spin only symbol. For C and BASIC you have to use -D_BAUD=.

  • Was the "DOS" version of FlexSpin dropped last year? The latest version I can run is 5.5.2 dated Jul 26 2021. Newer versions complain about a missing Windows DLL.

  • @TonyB_ said:
    Was the "DOS" version of FlexSpin dropped last year? The latest version I can run is 5.5.2 dated Jul 26 2021. Newer versions complain about a missing Windows DLL.

    I've never intentionally released a DOS version of flexspin. If a Windows version ran under DOS then it did so by accident. That said, it shouldn't be hard to compile it for DOS; the hardest part would probably be finding a DOS C compiler that was C99 compliant.

  • @ersmith said:
    the hardest part would probably be finding a DOS C compiler that was C99 compliant.

    DJGPP is still being updated to new GCC releases, so you can indeed compile C++23 for DOS if you want.

  • TonyB_TonyB_ Posts: 2,186
    edited 2022-12-12 17:31

    @ersmith said:

    @TonyB_ said:
    Was the "DOS" version of FlexSpin dropped last year? The latest version I can run is 5.5.2 dated Jul 26 2021. Newer versions complain about a missing Windows DLL.

    I've never intentionally released a DOS version of flexspin. If a Windows version ran under DOS then it did so by accident. That said, it shouldn't be hard to compile it for DOS; the hardest part would probably be finding a DOS C compiler that was C99 compliant.

    What I mean by "DOS" is the Windows 98 SE command line. (I was given an XP machine but it stopped booting, I had no XP discs and so I upgraded it, speed-wise at least, to 98SE.) Anyway, it seems something changed in FlexSpin after 5.5.2 for it to no longer run on 98SE. All I need it to do is assemble P2ASM files. I use loadp2 v0.029c to get the binary into the P2 via a 'real' serial cable.

  • @Wuerfel_21 said:

    @ersmith said:
    the hardest part would probably be finding a DOS C compiler that was C99 compliant.

    DJGPP is still being updated to new GCC releases, so you can indeed compile C++23 for DOS if you want.

    I found this website http://delorie.com/djgpp/dl/ofc/ and it says:

    To build C programs, you'll need djdev205.zip, gcc*b.zip, and bnu*b.zip. For C++, also get gpp*b.zip.

    At http://delorie.com/pub/djgpp/current/v2gnu/ there is only bnu2351b.zip but a big choice for gcc*b.zip and gpp*b.zip.

  • @TonyB_ said:

    @Wuerfel_21 said:

    @ersmith said:
    the hardest part would probably be finding a DOS C compiler that was C99 compliant.

    DJGPP is still being updated to new GCC releases, so you can indeed compile C++23 for DOS if you want.

    I found this website http://delorie.com/djgpp/dl/ofc/ and it says:

    To build C programs, you'll need djdev205.zip, gcc*b.zip, and bnu*b.zip. For C++, also get gpp*b.zip.

    At http://delorie.com/pub/djgpp/current/v2gnu/ there is only bnu2351b.zip but a big choice for gcc*b.zip and gpp*b.zip.

    Just use the highest number.

  • evanhevanh Posts: 15,967
    edited 2022-12-17 18:36

    There's a small error in the compiled clock mode calculation using Flexspin and the Prop2 clock enums/constants. When there is more than one possible solution with equal minimum deviation from target it will incorrectly choose the highest XIN divider value when it should choose the lowest XIN divider instead.

    Chip's original Delphi code had a specific way of resolving this issue. It relied on order of the increment against the equality or non-equality of the error to give priority to the lowest divider.

    Here's a snippet of my interpretation in Spin2. (I think I reversed the search order and equality check but gives the same outcome as Chip's code.)

            ...
            repeat divd from 64 to 1
                Fpfd := div33( xinfreq, divd )
                mult := muldiv65( divp * divd, targetfreq, xinfreq )
                Fvco := muldiv65( xinfreq, mult, divd )
    
                if Fpfd >= 250_000 and mult <= 1024 and Fvco > 99_000_000 and Fvco <= vcolimit
                    error := div33( Fvco, divp ) - targetfreq
    
                    if abs( error ) <= abs( besterror )     ' the last iteration at equality gets priority
                        besterror := error
            ...
    
  • evanhevanh Posts: 15,967
    edited 2022-12-17 23:23

    Huh, it's not that simple ... Been trying some more cases this morning that should be tripping up but they don't ... okay the one case I've found so far is for _clkfreq = 242_726_000. It produces XIN divider of 44 and multiplier of 534 when it should be 22 and 267 respectively.

    PS: Total fluke I found this then. I only tried that target frequency because Tony had posted it https://forums.parallax.com/discussion/comment/1546450/#Comment_1546450 And I only noticed the compiler got it wrong because the specific testing involved a rather rare checking of the clock mode components.

    PPS: Flexspin Version 5.9.22-beta-v5.9.21-2-g01c31036 Compiled on: Dec 12 2022

  • evanhevanh Posts: 15,967
    edited 2022-12-17 23:39

    Best guess now is it's likely just a rounding error causing the compare to favour the larger divider ... yeah, and it looks like the rounding problem is with the multiplier component rather than the divider. I've now got a new case of _clkfreq = 211_100_000. It comes up with a divider of 45 and multiplier of 475, when it should be 9 and 95 respectively.

    Right, and making more sense to think along those lines now too since the calculation for mult has the most steps.

  • evanhevanh Posts: 15,967
    edited 2022-12-18 02:46

    Thanks for the link Ada. I had tried to find it but was really clueless as to where to look.

    Well, I see I've avoided using Fpfd in subsequent calculations which is different to both Flexspin and Pnut ... [deleted comment] err, huh, I thought Pnut got the same bad outcome for a moment but it's fine.

    EDIT2: What is interesting is my library code also produces different answers for the calculated final frequency when compiled with Pnut instead of Flexspin. With Flexspin, my code gives answer of 211_110_900 Hz. With Pnut, my code gives answer of 211_111_111 Hz ... Pnut is bang on correct. 20e6 / 9 * 95 = 211_111_111.

  • evanhevanh Posts: 15,967
    edited 2022-12-18 10:26

    Okay, so, Flexspin's rounding errors are a bigger problem than just the compile time clock calculations. It's affecting runtime as well. And what's more, it's an integer problem. I'm quite puzzled how that library code is off when compiled with Flexspin ... I need a break though ...

    EDIT: Ah, duh, Flexspin hasn't generated the correct compile time boot value for clkfreq here. The library code uses the compiled constant clkfreq_ to calculate XIN frequency. Everything else is thrown off because the resulting calculation doesn't match the actual 20 MHz.

    Okay, back to the original problem then ...

    EDIT2: Right, think I've fixed it. Testing good now anyway. The rounding function on the Fpfd variable was making a problem. It was rounding just fine but for some reason that wasn't a suitable thing to do. I've removed it and did the same for the other two similar variables, Fvco and Fout, that aren't needed to be whole numbers.

                Fpfd = xinfreq / (double)divd;
                mult = round(clkfreq * post / Fpfd);
                Fvco = Fpfd * mult;
                Fout = Fvco / post;
                e = fabs(Fout - clkfreq);
    

    I wonder now if Chip has also made a later correction in his code too.
    My code doesn't use Fpfd for calculating, only for compare.

    EDIT3: Damn! It looks like Chip has converted it to x86 assembly for Pnut. WTF?! I guess that's a high chance of not being an exact 1:1 of the Delphi code then.

  • evanhevanh Posts: 15,967
    edited 2022-12-18 10:36

    Oh, Eric,
    Now I see where I got my version from. Chip had posted a later revision and not updated the opening post. Naughty Chip. It's here -https://forums.parallax.com/discussion/comment/1486815/#Comment_1486815

    The revised edition, like mine, also doesn't use Fpfd for calculations. I'll let you chose if you use my above changes or change to Chip's revised code.

  • @evanh : Thanks for tracking this down. I've checked in a version of the code that matches Chip's, I think.

  • @ersmith it would be really handy to have a version of this code that can be called from the various languages as a function to change the clock freq on the fly. Right now I use a function that I wrote in FlexBASIC called CPUSpeed(freq) based (somewhat) on Chip’s code. It’s pretty ugly, but it works, and it lets me “shift gears” when I need to save power.

    It would be a real benefit to all of the Flex languages to have something “official” that we could call without having to know all of the underpinnings needed with hubset. Any interest in making this a thing?

  • evanhevanh Posts: 15,967
    edited 2022-12-19 00:17

    @JRoark said:
    It would be a real benefit to all of the Flex languages to have something “official” that we could call without having to know all of the underpinnings needed with hubset. Any interest in making this a thing?

    There's a few inputs needed on top of the target clkfreq. Namely the XI frequency and oscillator operating mode. These can be carried over from the compile time clkmode word assuming they were set correctly. Here's the code for that from my stdlib.spin2 above.

        mode := clkmode_
    
        if clkmode_ >> 24 & 1                           ' compiled with PLL on
            divd := clkmode_ >> 18 & $3f + 1
            mult := clkmode_ >> 8 & $3ff + 1
            divp := (clkmode_ >> 4 + 1) & $f
            divp := divp ? divp * 2 : 1
            xinfreq := muldiv65( divp * divd, clkfreq_, mult )
    
        elseif clkmode_ >> 2 & 3                        ' compiled with PLL off
            xinfreq := clkfreq_                     ' clock pass-through
        else                                            ' unknown build mode
            xinfreq := 20_000_000                   ' default to 20 MHz crystal
            mode := %10_00                          ' default to 15 pF loading
    
        mode := %11_11 & mode | %11                     ' keep %CC, force %SS, ditch the rest
    

    PS: And, because clkmode_ and clkfreq_ are both constants, that optimises down to two lines: One setting xinfreq and one setting mode.

  • JRoarkJRoark Posts: 1,215
    edited 2022-12-19 01:00

    @evanh said:
    There's a few inputs needed on top of the target clkfreq. Namely the XI frequency and oscillator operating mode. These can be carried over from the compile time clkmode word assuming they were set correctly. Here's the code for that from my stdlib.spin2 above.

      mode := clkmode_
    
      if clkmode_ >> 24 & 1                           ' compiled with PLL on
          divd := clkmode_ >> 18 & $3f + 1
          mult := clkmode_ >> 8 & $3ff + 1
          divp := (clkmode_ >> 4 + 1) & $f
          divp := divp ? divp * 2 : 1
          xinfreq := muldiv65( divp * divd, clkfreq_, mult )
    
      elseif clkmode_ >> 2 & 3                        ' compiled with PLL off
          xinfreq := clkfreq_                     ' clock pass-through
      else                                            ' unknown build mode
          xinfreq := 20_000_000                   ' default to 20 MHz crystal
          mode := %10_00                          ' default to 15 pF loading
    
      mode := %11_11 & mode | %11                     ' keep %CC, force %SS, ditch the rest
    

    PS: And, because clkmode_ and clkfreq_ are both constants, that optimises down to two lines: One setting xinfreq and one setting mode.

    Bingo! (Remember when I said mine was “ugly”? Well… there ya go. Heheheh)

    We really do need a resident function that does this. Mine also returns the actual freq set, (which may be slightly different than the one requested due to osc granularity issues), so that would be something else to consider.

    @ersmith was probably looking for something to do over the winter break anyway. (-ducking!-) 🤣

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

  • RaymanRayman Posts: 14,681

    @ersmith Was thinking it'd be nice to use printf in a way that only outputs when debug is enabled.
    Maybe this is already there?

    I see this in the docs, but don't know what it means:
    [ -g ] enable debug statements (default printf method)

    Is this saying I can literally replace "printf" with "debug" and do this?

  • Wuerfel_21Wuerfel_21 Posts: 5,074
    edited 2022-12-19 19:32

    @Rayman said:
    @ersmith Was thinking it'd be nice to use printf in a way that only outputs when debug is enabled.
    Maybe this is already there?

    I see this in the docs, but don't know what it means:
    [ -g ] enable debug statements (default printf method)

    Is this saying I can literally replace "printf" with "debug" and do this?

    No, that's not how that works. It just means that DEBUG lines will be translated to printfs (as opposed to using -gbrk, which uses an actual debug blob like PNut)

  • RaymanRayman Posts: 14,681

    Ok, then I wish there was something like a "printg" or "printd" that would only be compiled when debug was enabled...
    I like the format options for standard printf a lot more than for debug.

    But, I've seen that people use #ifdef to do this, so maybe that is how to handle it...

  • @Rayman said:
    Ok, then I wish there was something like a "printg" or "printd" that would only be compiled when debug was enabled...
    I like the format options for standard printf a lot more than for debug.

    But, I've seen that people use #ifdef to do this, so maybe that is how to handle it...

    Yes, typically people do something like:

    #ifdef __DEBUG__
    #define printd(x, ...) printf(x, __VA_ARGS__)
    #else
    #define printd(x, ...)
    #endif
    
  • RaymanRayman Posts: 14,681

    Thanks @ersmith , that looks better than what I was thinking…

  • @Rayman : Oops, I messed that up slightly; in case you want to be able to do printd() with just one string (no variables) you actually need:

    #ifdef DEBUG
    #define printd(...) printf(__VA_ARGS__)
    #else
    #define printd(...)
    #endif
    

    Also note that you'll have to define the symbol DEBUG yourself somehow. The next version will automatically define a built in symbol __DEBUG__ when the -g flag is given on the command line.

  • evanhevanh Posts: 15,967
    edited 2022-12-20 09:40

    @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.

  • RaymanRayman Posts: 14,681

    @ersmith said:

    The next version will automatically define a built in symbol __DEBUG__ when the -g flag is given on the command line.

    Thanks, that sounds useful.
    I also like they way Wiznet handled it, with each module having its own conditional debug.
    But, I don't think this ifdef does anything useful in FlexC, right?

    /* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */
    
    #ifdef _DHCP_DEBUG_
       #include <stdio.h>
    #endif   
    
  • @Rayman said:
    I also like they way Wiznet handled it, with each module having its own conditional debug.
    But, I don't think this ifdef does anything useful in FlexC, right?

    /* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */
    
    #ifdef _DHCP_DEBUG_
       #include <stdio.h>
    #endif   
    

    ??? ifdef is the same in FlexC as in any other C compiler. If the symbol is defined, the code inside is compiled, otherwise it isn't. Not sure why you'd think otherwise?

Sign In or Register to comment.