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

16364656668

Comments

  • ersmith wrote:
    I've also added "." to the BASIC PRINT USING statement, so you can format the numbers directly in BASIC if you want (e.g. print using "##.####"; x)

    SWEET! That little mod really makes a difference in my world. Thank you for all the fixes!



  • ManAtWork wrote: »
    ersmith wrote: »
    The assignment to the variable happens *after* all the calculations are performed, so the type is "int" during the shift. That is, the expression is parsed as:
      uint32_t mask = (0xffffffff >> (32-bit));
    
    and not as
      (uint32_t mask = 0xffffffff) >> (32-bit);
    

    Ok, that makes sense and I finally get it. That's what I hate about C. Those implicit typecasts are very dangerous. An expression that looks perfectly correct at first sight could actually contain bugs that are very hard to spot.
    Well, that is one reason to put explicit casts in.

    It turns out though that integer constants starting with 0x should be interpreted as unsigned if they are too big to fit in an "int" (decimal constants are always "int"). I'll fix that in the next version of fastspin.
  • Rayman wrote: »
    @ersmith Forsee any way to start more cogs running FlexC?

    That's already in there, you can run a function in another cog with _cogstart(func, arg, stack, size), where:
    func is a pointer to the function, which has signature void (*func)(void *arg)
    arg is the parameter to pass
    stack is the base of the stack to use
    size is the length of the stack in bytes
    

    Or, if you're being non-portable (code is for FlexC only), you can just do
    int stack[64]; // or whatever size you need
    int cogid = __builtin_cogstart(func(arg), stack)
    
    which works just like Spin's cogstart()
    How about interrupt handling? Is that possible?

    No, interrupt handling is not possible.
  • RaymanRayman Posts: 11,372
    edited 2020-10-12 - 15:02:48
    Can you start a PASM2 cog that handles interrupts?
    That should work, right?

    I'm trying to remember if I already seen the @garryj Spin2/PASM2 USB kb/mouse code working with FlexC...
    I seem to recall that PASM2 driver uses interrupts...
  • That's great! For some reason, I thought you couldn't...

    How does the heap work in that case? Can only the first cog use the heap? Or, can they really share it?
    ersmith wrote: »

    That's already in there, you can run a function in another cog with _cogstart(func, arg, stack, size), where:
    func is a pointer to the function, which has signature void (*func)(void *arg)
    arg is the parameter to pass
    stack is the base of the stack to use
    size is the length of the stack in bytes
    

  • I think I'm seeing this code not work right when not referencing an array by the address of the first element...

    This works:
    void selftestLSM9DS1()
    {
        float accel_noST[3] = { 0., 0., 0. }, accel_ST[3] = { 0., 0., 0. };
        float gyro_noST[3] = { 0., 0., 0. }, gyro_ST[3] = { 0., 0., 0. };
    
        writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG10, 0x00); // disable self test
        accelgyrocalLSM9DS1(&gyro_noST[0], &accel_noST[0]);
        writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG10, 0x05); // enable gyro/accel self test
        accelgyrocalLSM9DS1(&gyro_ST[0], &accel_ST[0]);
    ...
    

    This doesn't:
    void selftestLSM9DS1()
    {
        float accel_noST[3] = { 0., 0., 0. }, accel_ST[3] = { 0., 0., 0. };
        float gyro_noST[3] = { 0., 0., 0. }, gyro_ST[3] = { 0., 0., 0. };
    
        writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG10, 0x00); // disable self test
        accelgyrocalLSM9DS1(gyro_noST, accel_noST);
        writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG10, 0x05); // enable gyro/accel self test
        accelgyrocalLSM9DS1(gyro_ST, accel_ST);
      ...
    

    The data in the arrays like "gyro_ST" stays 0 unless accelgyrocalLSM9DS1() is passed the address of the first element in the array and not the array name...
  • RaymanRayman Posts: 11,372
    edited 2020-10-12 - 17:39:29
    Also seeing that this (from Arduino code again) doesn't work as expected:
                printf("ax = %d", (int) 1000 * ax);
                printf(" ay = %d", (int) 1000 * ay);
                printf(" az = %d", (int)1000 * az);
    

    But this does:
                printf("ax = %d", (int) (1000. * ax));
                printf(" ay = %d", (int) (1000. * ay));
                printf(" az = %d", (int) (1000. * az));
    
  • Rayman wrote: »
    Can you start a PASM2 cog that handles interrupts?
    That should work, right?

    I'm trying to remember if I already seen the @garryj Spin2/PASM2 USB kb/mouse code working with FlexC...
    I seem to recall that PASM2 driver uses interrupts...

    Sure, other PASM2 COGs can do anything they like. I've used garryj's USB code with FlexC and it did work at the time; it's been a while since I tried it, but I'd be very surprised if anything changed.

    The heap isn't protected yet for use between different COGs, so you'll have to manually add lock/unlock around any heap allocations if you want multiple COGs to use the heap. In general I'd suggest just keeping the heap allocation to the main COG.
                printf("ax = %d", (int) 1000 * ax);
    

    The cast to int has a higher precedence than multiplication, so the expression is parsed as ((int) 1000) * ax. If ax is a float then the whole thing produces a float, which won't print right with %d. This happens with GCC on Linux too, so it's not a bug in fastspin. I can't see how the original Arduino code could have worked.

    Not sure what's happening with the arrays, I'll have to look into that, but for now your workaround of using &arrayname[0] instead of arrayname is a good one.

    Thanks,
    Eric
  • @ersmith There is an oddity with PRINT USING. This code works:
    dim f as single
    f = 0.12345
    print using "#.#####"; f    ' <-- notice leading # in the 1's position
    
    This code throws a "child killed: segmentation violation" during compilation:
    dim f as single
    f = 0.12345
    print using ".#####"; f    ' <-- notice no leading #
    
    Also, about every fifth compile, the FlexGUI editor hangs and Windows 10 says it is "not responding". Given time (a minute or two), it does eventually wake-up and throw the "child killed/seg vio" error and the FlexGUI editor responds again.

    ADDED: After some further testing, it seems that any failure to put a leading "#." in the format specifier causes an error. All of these cause that same segmentation error:
    print using "-.#####"; f
    print using "+.#####"; f
    print using "%.#####"; f
    
    This is definitely not a show-stopper, but the next time you have the code open, you might see what mischief is afoot.
  • JRoarkJRoark Posts: 564
    edited 2020-10-12 - 23:07:20
    @ersmith Another oddity involving multiplication and expotentiation with a floating point number as the base and an integer exponent. (This is using the latest version of the compiler obtained this PM from Patreon). This code assumes you are using the default (floating-point) math package. It is not dependent on the optimization level selected:
    	dim f as single
    	
    	f = 1.1234567 * (1.14 ^ 2)		'works
    	print f
    	
    	f = 1.1234567 * (1.14 * 1.14)           'works
    	print f
    	
    	f = 1.1234567 * (1.14 ^ 3)		'returns NAN
    	print f
    	
    	f = 1.1234567 * (1.14 * 1.14 * 1.14)	'works
    	print f
    
    	f = 1.1234567 * (1.14 ^ 4)		'returns NAN
    	print f
    	
    	f = 1.1234567 * (1.14 * 1.14 * 1.14 * 1.14) 'works
    	print f
    
    Specifying a floating point number instead of an integer for the exponent produces the same results.
  • @JRoark: Yes, there is a problem with leaving off the leading digit when outputting floats. I can kind of hack around it, but the leading digit will still be printed, so for now I recommend always putting a # in front of .

    The exponentiation problem is a real head-scratcher; internally fastspin was using a C powf() function which is very well tested (it dates back to Sun Microsystems in 1993). I can only assume that our floating point addition/multiplcation routines are subtly wrong in a way that breaks powf(). I want to replace those eventually anyway (I know they're not quite IEEE compliant) but that's a big job. For now I've replaced powf() with a version that uses the P2 CORDIC.

    I hope to have a new release soon.
  • Rayman wrote: »
    Also, the code uses the include sys/timeb.h to get the seconds and milliseconds of time and then form milliseconds.
    We don't have that, so I did a bad hack.
    Is there a good way to do that?

    Sorry, I missed this earlier. I've been working on adding the "gettimeofday()" function, which is the POSIX way to get seconds and microseconds. For now though you can use "_getms()" to get a 32 bit unsigned integer containing milliseconds since the last time the system clock counter rolled over.
  • Thanks. _getms() would be a perfect fit there.
  • There's a new binary release of fastspin at https://github.com/totalspectrum/spin2cpp/releases. The change log is:
    - Added a warning for C functions with mismatched parameters (it used to silently accept this)
    - Added "." character for PRINT USING in BASIC
    - Added support for binary floating point constants in C
    - Added __builtin_clz() for C
    - Added gettimeofday() / settimeofday()
    - Added scanf() family of functions for C
    - Allowed empty FOR loops in BASIC
    - Fixed a number of problems in C struct initialization
    - Fixed printing floats in C when --fixedreal is given
    - Fixed BASIC FOR loops with negative floating point steps
    - Fixed binary and hex constants in C to be unsigned when appropriate
    - Fixed a problem with passing small arrays as parameters in C
    - Fixed ^ in BASIC
    - Made expf and logf use the CORDIC on P2 and ROM on P1
    - Made FIXED a reserved keyword in BASIC (for future expansion)
    - Updated time functions to work sensibly.
    
  • I know what I’m doing today! Thanks for the updates!
  • gettimeofday() sounds interesting... I assume this gives microseconds and seconds since boot, right?

    Guessing can't be used with a RTC. Does it actually use a time zone parameter?
  • Rayman wrote: »
    gettimeofday() sounds interesting... I assume this gives microseconds and seconds since boot, right?

    Guessing can't be used with a RTC. Does it actually use a time zone parameter?

    It's a bit more complicated than "seconds and microseconds since boot", it keeps an internal seconds count and microseconds since the last "official" second. The internals seconds count starts at an arbitrary value but can be adjusted by settimeofday(). You'd use it with an RTC by reading the RTC values and calling settimeofday() based on those.

    Internally time is kept as UTC. You can specify a time zone in an environment variable TZ (using setenv()) but I expect most people will just ignore the issue and pretend that UTC and local time are the same.
  • JRoarkJRoark Posts: 564
    edited 2020-10-19 - 23:20:51
    @ersmith I hit a snag in FlexBASIC. When using FlexGUI vers 4.4.1-Beta and the just-released binary for FastSpin, when "--fixed" is specifed as a compiler command line option, and if expotention is used in the program, the compiler throws a "error: exponentiation operator not supported in fixed point mode"

    This is the BASIC code fragment that demonstrates the error:
    	dim f as single
    	dim x as single
    	x = 1.14
    	f = 1.1 * (x ^ 2)		
    	print f
    
    Note that the error is not dependant on the optimization level specified.

    Request for feature: How about adding a "-v" option to the compiler that will simply return the compiler version/date info and then quit?
  • ersmithersmith Posts: 4,429
    edited 2020-10-21 - 10:55:32
    JRoark wrote: »
    @ersmith I hit a snag in FlexBASIC. When using FlexGUI vers 4.4.1-Beta and the just-released binary for FastSpin, when "--fixed" is specifed as a compiler command line option, and if expotention is used in the program, the compiler throws a "error: exponentiation operator not supported in fixed point mode"

    Aargh! I actually implemented exponentiation in fixed point mode as part of the bug fixes for the C pow(), exp(), and log() functions, but I forgot to go back and test it in BASIC. I've uploaded a FlexProp beta to my Patreon page that should have this fixed.
    Request for feature: How about adding a "-v" option to the compiler that will simply return the compiler version/date info and then quit?

    openspin uses "-v" for something else, but I've added "--version".

    Thanks!
  • Is there a way to home and/or clear the terminal?
  • Rayman wrote: »
    Is there a way to home and/or clear the terminal?

    The terminal is just the standard Windows terminal. This uses standard ANSI escape codes (https://en.wikipedia.org/wiki/ANSI_escape_code). For example, home is ESC-[-H, clear from current cursor position to end of screen is ESC-[-J.
  • MAJOR CHANGES AHEAD:

    For the next release (5.0.0) "fastspin" is going to be named "flexspin", and there will also be a C specific "flexcc" front end. Both "flexspin" and "flexcc" will accept all of the same languages, the differences are just cosmetic. The flexcc options will be more like traditional Unix cc.

    There's also going to be a .o file format. For now this is just a pre-processed version of the input source, so it's not really "interesting" from a programming point of view, but it should make adapting Makefiles to use flexcc a lot easier. Eventually I plan to have a "flexar" and a new .a file format, but that's not done yet.

    There's a beta version of the new FlexProp up on my Patreon page.
  • Cool!
  • I've got mixed feelings on the naming of flexC, or is it really flexCC?
    One reason I'm using it is that people want the code to be in C (and not anything else).
    So, it'd be nice for me to have a name that clearly signifies C compatibility...
  • jmgjmg Posts: 14,495
    ersmith wrote: »
    MAJOR CHANGES AHEAD:

    For the next release (5.0.0) "fastspin" is going to be named "flexspin", and there will also be a C specific "flexcc" front end. Both "flexspin" and "flexcc" will accept all of the same languages, the differences are just cosmetic. The flexcc options will be more like traditional Unix cc.

    It's a good idea to change from fastspin, but "flexspin" excludes the multi-language nature of this, so to me it's nice to have a wider-scope name.

    The name also needs to be google-findable, so something like "FlexPSuite" keeps the "Flex", adds "P" for P1/P2 and uses "Suite" to signify multiple languages in the box.
    "Suite" may not be super trendy, but embedded designers do know what that means.

    Users can then choose & mix any language in there.

  • I vote for “Eric’s Big Freakin’ Compiler Suite, Propeller Style”. Or just “EBFCSPS” for short?

    (Why are the crickets suddenly so loud? Lol)
  • Rayman wrote: »
    I've got mixed feelings on the naming of flexC, or is it really flexCC?
    One reason I'm using it is that people want the code to be in C (and not anything else).
    So, it'd be nice for me to have a name that clearly signifies C compatibility...

    FlexProp is the whole suite, and is also what the GUI is called (probably a bad name, perhaps FlexPropGUI would be better, but that's awkward).

    FlexC is the language (the C dialect that the FlexProp tools accepts). It will eventually be C99 compatible, with some C++ extensions and support for external modules.

    flexcc.exe is the command line tool that can compile FlexC programs. It's designed to be command line compatible with other C compilers, like cc (the standard Unix C compiler), gcc (the GNU C compiler), tcc (the Tiny C Compiler) and so on. flexcc also happens to be able to compile FlexSpin and FlexBASIC programs too, but perhaps some users won't care about that.

    Similarly, flexspin.exe is the command line tool for compiling Spin and Spin2 programs within FlexProp. It's designed to be mostly command line compatible with openspin and bstc. It can compile FlexBASIC and FlexC programs too.

    If you're designing an IDE (as I happen to know you've done, @Rayman :)) you can choose to include either or both of these, whichever is most convenient for integrating with your IDE. If you've already got a Spin compatible one, flexspin.exe is probably the tool of choice. If you've got a C IDE, it will probably have a cc/gcc compatible interface, so flexcc.exe is probably easier to integrate. Both will be available in the zip file, and both really do the same thing; they just have slightly different defaults and different names for the various options.

  • I still will try to press for ECC, Eric's Compiler Collection.

    Enjoy!

    Mike
  • I'd keep the fastspin command as-is (or include a redirect of sorts, but that's somewhat troublesome) so as to not break preexisting shell scripts
  • I’d be fine with “FlexProp C“.
Sign In or Register to comment.