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

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

17677798182122

Comments

  • I guess it could just be a user-defined thing - i.e. if the code has a __handle_nullcall function, call that, otherwise hang.

  • how about calling reset instead of calling address 0?

    Or simply ignoring a call to address 0?

    Mike

  • RaymanRayman Posts: 14,648

    Yes, the code now checks and skips function call with NULL address. I was trying to figure out if this is a bug in the code or intended behavior. This code was adapted from Unix to PC long ago... I'm now thinking it's a bug somewhere.
    Hasn't happened again though, so maybe it was a fluke. Got my eye on it though...

  • Yes, I found a problem with some code I was converting that used call backs.

    `#include <stdio.h>

    include <propeller.h>

    typedef long (*test)(int x, int y);

    int main(int argc, char** argv)
    {
    printf("Starting\n");

    printf("Call Back: %x\n", callback);
    
    callit(16, 20, callback);
    
    printf("Done\n");
    
    while (1)
    {
        _waitms(1000);
    }
    

    }

    long callback(int x, int y)
    {
    printf("X: %d, Y: %d\n", x, y);
    return -1;
    }

    void callit(int x, int y, test v)
    {
    int i;

    printf("call back: %x\n", v);
    
    i = v(x, y);
    
    printf("I: %d\n", i);
    

    }
    `
    Based on where the Include file was the compiler would generate a call to the pointer to the function and in the other case generate a call to the function.

    I ended up adding an & in front of the function so that it would use the address of instead of the pointer to get around it.

    Looks like code blocks are not working for C code.

    Mike

  • Looks like code blocks are not working for C code.

    They are, but the button to insert code blocks doesn't insert the right kind.
    Do this:

    ```
    Your code here
    ```

  • @iseries : I think there's a problem (or more accurately an inconsistency) with trying to print a function address. In printf() function addresses are not converted to full method pointers, but whenever they are passed to a function that's expecting a function pointer they are. That's weird, but I don't think it'll actually mess anything up (except perhaps making debugging a bit harder). But I think you've hit on the work-around, always use & in front of functions if you want function pointers.

  • @Rayman : calling a NULL pointer is always a bug, on every platform. What it ends up doing will vary by platform (and on some platforms it may be benign) but the C standard is pretty clear that you shouldn't do that.

  • Yes, it took me about 10 hours to find that bad function call. All I was getting is double printing of my code as it rebooted and ran the code twice and stopped.

    Had to start by tracing the code with LED's to see where it was stopping. Since it was a passed function call back it made it a little harder to find.

    Printing the function pointer didn't help as it printed some strange value not an address to the function that corresponded to the assembly code. Tried several configuration to see if I could get the correct address but to no avail.

    Finally just added the Ampersand to the function and it worked. Not the outcome I was looking for as it makes the code inconsistent as all the other calls do not have the Ampersand.

    Mike

  • @iseries said:
    Yes, it took me about 10 hours to find that bad function call. All I was getting is double printing of my code as it rebooted and ran the code twice and stopped.

    Had to start by tracing the code with LED's to see where it was stopping. Since it was a passed function call back it made it a little harder to find.

    Printing the function pointer didn't help as it printed some strange value not an address to the function that corresponded to the assembly code. Tried several configuration to see if I could get the correct address but to no avail.

    Finally just added the Ampersand to the function and it worked. Not the outcome I was looking for as it makes the code inconsistent as all the other calls do not have the Ampersand.

    Mike

    This is a case where you need a source code debugger with singlestepping. You can find such an error in minutes.

  • @ersmith I hit a snag in defining two-dimensional arrays in FlexBASIC 5.0.9.

    This syntax works:

    dim myArray(0 to 8) as long
    dim myArray2(8, 16) as long
    

    But when it comes to defining a 2-dimensional array with explicit upper and lower bounds like below, the compiler throws an error:

    dim myArray2(0 to 8, 0 to 16)
    
  • @JRoark said:
    @ersmith I hit a snag in defining two-dimensional arrays in FlexBASIC 5.0.9.
    This syntax works:
    dim myArray(0 to 8) as long
    dim myArray2(8, 16) as long
    But when it comes to defining a 2-dimensional array with explicit upper and lower bounds like below, the compiler throws an error:
    dim myArray2(0 to 8, 0 to 16)

    That was actually documented under the ARRAYS section of the manual. I can relax things a little bit and allow the "to" form, but both dimensions in a two dimensional array will have to start at the same place (so dim myArray(0 to 8, 1 to 6) will not work. (There's an internal limitation, arrays only have one "base" field at present, which was why I only allowed the "to" form on one dimensional arrays.)

  • @ersmith I’m not sure how I missed that. Oops. :) In that case it is probably best to leave the syntax as it is.

  • RaymanRayman Posts: 14,648
    edited 2021-02-10 17:34

    Is something wrong with isprint() ?
    I'm getting errors like this trying to use it:
    1>C:/FlexSpin/include/libc/misc/isprint.c:7: error: __ctype is not an array

    Trying it like this after including ctype.h
    int x1 = isprint((int)'x');//test

  • ersmithersmith Posts: 6,053
    edited 2021-02-10 18:40

    Yes, it looks like isprint() is broken. I'll fix it in the next release. For now I suggest working around by using some of the other isxxx() functions, or just doing something like:

    #define isprint(x) (isspace(x) || ( ((x) < 0x7f) && ((x) >= 0x20))
    
  • RaymanRayman Posts: 14,648
    edited 2021-02-10 20:44

    ~~Should something like this work? I seem to remember something about a structure not being able to reference itself...
    It compiles, but something is wrong...~~

    `

    typedef struct Line Line;
    struct Line {
        char *s;  /* string content */
        size_t l; /* length excluding \0 */
        size_t v; /* visual length */
        size_t m; /* multiples of LINSIZ? */
        Line *p;  /* previous line */
        Line *n;  /* next line */
    };
    

    `

    Nevermind... It works... (Trying to strike out the text above doesn't work though...)

  • Cluso99Cluso99 Posts: 18,069

    @ersmith
    I have a problem and I think it's linked to my old problem of relative addressing in the compilers.

    In my code I have a big set of variables that contain values and address pointers that get passed to child objects, some of which are pure pasm drivers.
    Here is a snippet

    dat { port/slots configuration, parameters and buffers}
    ''                orgh
    '' ====================================================================================================================
    '' WARNING: Within the following groups, the order and size must be maintained !!!
    
    port_lcd_config     {3 longs}                   '\ LCD configuration
        long            @port_params                '| ptr to port_params
        byte            0<<7 | LCD_SLOT             '| inactive | slot#         where: 1=active, bbbb=slot#
        byte            LCD_CE                      '| LCD: Serial clock enable pin
        byte            LCD_RST                     '| LCD: Reset pin (can be reset by software)
        byte            LCD_DC                      '| LCD: Data / Command selection pin
        byte            LCD_SDA                     '| LCD: Serial Data MOSI pin
        byte            LCD_CLK                     '| LCD: Serial Clock pin
        byte            LCD_LED                     '| LCD: LED backlight enable pin (hi to enable - ~2.4mA)
        byte            LCD_SDO                     '/ LCD: Serial Data MISO pin
    

    This compiles to this from the listing

    01ed4                 | 
    01ed4                 | port_lcd_config     {3 longs}                   '\ LCD configuration
    01ed4     20 00 00 00 |     long            @port_params                '| ptr to port_params
    01ed8     02          |     byte            0<<7 | LCD_SLOT             '| inactive | slot#         where: 1=active, bbbb=slot#
    01ed9     2F          |     byte            LCD_CE                      '| LCD: Serial clock enable pin
    01eda     2E          |     byte            LCD_RST                     '| LCD: Reset pin (can be reset by software)
    01edb     2D          |     byte            LCD_DC                      '| LCD: Data / Command selection pin
    01edc     2C          |     byte            LCD_SDA                     '| LCD: Serial Data MOSI pin
    01edd     2B          |     byte            LCD_CLK                     '| LCD: Serial Clock pin
    01ede     2A          |     byte            LCD_LED                     '| LCD: LED backlight enable pin (hi to enable - ~2.4mA)
    01edf     29          |     byte            LCD_SDO                     '/ LCD: Serial Data MISO pin
    01ee0                 | 
    .....
    01ef4                 | 
    01ef4                 | port_params     {16*4 = 64 longs}               '\ max (16 ports) of 4 longs... port[slot]: buffer ptrs to p_head, p_tail, p_start, p_end
    01ef4     20 01 00 00 |     long    {0}     @BUF0                       '| \ {slot  0}  p_head    SERIAL-RX                 (ptr to current head of buffer)
    01ef8     20 01 00 00 |     long            @BUF0                       '| |            p_tail       "                      (ptr to current tail of buffer)
    01efc     20 01 00 00 |     long            @BUF0                       '| |            p_start      "                      (ptr to start        of buffer)
    01f00     60 01 00 00 |     long            @BUF0+BUF_SIZE              '| /            p_end        "                      (ptr to end+1        of buffer)
    

    In spin if I get @port_params

      addr2 := @port_params
      ser.fstr1(string("Port-params     %8x\r\n"), addr2)
      ser.txdump(addr2, addr2+(4*4*16)-1)
    

    with this result on the screen

    Port-params         1EF4
    01EF4: 20 01 00 00  20 01 00 00  20 01 00 00  60 01 00 00  ' ... ... ...`...'
    0
    

    The real hub address is $1ef4 but when I pull out the long from hub it contains the wrong address.
    Is there any way around this problem???

    I have >100 lines of parameters mixed with addresses.
    Due to this problem I decided to not pass parameters to routines just to set a pile of pointers and constants as it became unwieldly to call the routines/objects to do this and overly made the program so complex it was embarassing.
    Help!!!

  • In flexspin you can use @@@ in PASM to get the absolute address. So in all of the DAT blocks if you replace "@" with "@@@" it will probably do what you want. But that's flexspin only, I don't think Chip's Spin2 has anything like that.

    One alternative is to fix up the DAT section at run time as part of your start routine. As you've seen, @ does the right thing in Spin methods (because it's evaluated as a run time rather than compile time expression) so you could add something to your start function like:

       if not fixup_done
          fixup_done := 1
          port_params[0] := @buf0
          port_params[1] := @buf0
         ' and so on
    

    No doubt you can come up with a more elegant variation e.g. involving a loop. The value stored in the DAT section for a plain @ is the offset from the start of the object, so you could fix up by adding the object starting address to everything that need it.

    Another alternative is to store only offsets in the structure (which is effectively what @ does at compile time) and then do the calculations at run time, using the structure values as indices into an array.

  • Cluso99Cluso99 Posts: 18,069

    Unfortunately no it can’t be filled in at runtime, only adjusted as it’s the user who fills in the table. I will give the @@@ a try tomorrow. Thanks Eric.

  • Cluso99Cluso99 Posts: 18,069

    Woohoo :smiley:

    @@@ works.
    Not sure if this solves everything but it sure helps.
    I've spent days chasing some bugs that are all probably to do with this problem.

    Thanks Eric :smiley:

  • RaymanRayman Posts: 14,648

    @ersmith Been at least a day since I asked for anything... :)

    What do you thing about adding vsnprintf() ?
    A vi-like editor I'm looking at uses this to print the status line at the bottom of the screen.
    I substituted in vsprintf(), which looks to do about the same thing, but doesn't clip the size of the result (if I see it right).

  • RaymanRayman Posts: 14,648
    edited 2021-02-12 15:53

    What decides how many spaces you get with a tab using printf() ?

    After thinking about this, I guess it's the terminal program that decides...

  • Is this suppose to work:

    #include <stdio.h>
    #include <propeller.h>
    
    
    char Values[][10] = {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
    char *temp;
    
    
    int main()
    {
        temp = Values[1];
    
        printf("Value: %s\n", temp);
    
        while (1)
        {
            _waitms(1000);
        }
    
    }
    
    

    Mike

  • RaymanRayman Posts: 14,648

    Seems to work with this:
    char* Values[10] = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };

  • Cluso99Cluso99 Posts: 18,069
    edited 2021-02-12 18:36

    Eric,
    Is there any way you could add using a DAT section with ORGH $someaddress when using it with spin mixed in?

    These DAT sections could be after all spin code. It would probably need to be zero padded to fill to the ORGH address tho this can be done easily as we do with pasm only. I can use the @@@ to get absolute addresses - thanks for this :)

    I need to get some hubexec pasm code and some buffers and variables into upper fixed hub addresses, where they will remain resident. It’s for my P2 OS and Z80/CPM emulator too. I probably need to use $7B000-$7BFFF which is immediately below the dual mapped top 16KB that Chip’s using for debug and shortly to be the spin interpreter too.

    Now I realise why I’ve been having so many problems getting my pasm SD Driver working with spin code. Been using @ where I should be using @@@.

  • @Rayman: as you guessed, tabs are determined by the terminal program. I think most default to having 8 characters between tab stops.

    snprintf() should be easy to add, I'll do that.

    @iseries: I think that should work, but as you can see it doesn't in the current flexcc. It seems something is broken in the set-up for two dimensional character arrays. If you change it to an array of pointers (so declare Values as "char *Values[]" instead of "char Values[][10]") then it should be OK.

  • @Cluso99 : Making ORGH work with Spin code present would be a serious headache, I don't think it's practical.

    Can you compile the "stay resident" stuff seperately? flexspin lets you build at any starting address, so you could certainly build a binary blob that goes at $78000 and then a main program that goes at $0, but you'd have to arrange to copy the binary blob to the correct final address at boot time (or else use loadp2 to load it there; loadp2 is able to put multiple files into memory before starting the first one).

  • RaymanRayman Posts: 14,648
    edited 2021-02-12 19:18

    @ersmith regarding the asmclk thing...

    Is there a subroutine around that we could use to do something like this:

    #define asmclk call _asmclk
    
    DAT           org
    
    
                  asmclk
    
  • RaymanRayman Posts: 14,648

    Is there a way to launch a compiled PASM2 binary from within Spin2? Something like this:

    PUB Main()
        coginit(1,@launcher,0)
        repeat
    
    DAT          'launcher 
    orgh
    launcher 
    file "8080GamesEmulator.bin"
    
  • Cluso99Cluso99 Posts: 18,069

    @ersmith said:
    @Cluso99 : Making ORGH work with Spin code present would be a serious headache, I don't think it's practical.

    Can you compile the "stay resident" stuff seperately? flexspin lets you build at any starting address, so you could certainly build a binary blob that goes at $78000 and then a main program that goes at $0, but you'd have to arrange to copy the binary blob to the correct final address at boot time (or else use loadp2 to load it there; loadp2 is able to put multiple files into memory before starting the first one).

    Yes, I may have to resort to loading a separately compiled binary blob. Not sure yet. At least I've found a reason why I've been chasing bugs for month's with different results. I've probably been overwriting lower hub indiscriminately :(

  • @Rayman: Chip gives a definition for asmclk in his Spin2 document. I'll look again at it later, maybe I can hack something in.

    As for launching a compiled binary from within Spin2, sure, your example should work fine.

Sign In or Register to comment.