Shop OBEX P1 Docs P2 Docs Learn Events
FlexProp: a complete programming system for P2 (and P1) - Page 62 — Parallax Forums

FlexProp: a complete programming system for P2 (and P1)

1565758596062»

Comments

  • RaymanRayman Posts: 16,157
    edited 2026-02-25 02:16

    Thanks @ersmith

    Wonder if the new exp and log use Cordic…

    Oops you just said they do…

  • @ersmith said:

    saw mention of packed structs in Spin2….

    I think they work in C now, you have to put __attribute__((packed)) after the struct keyword. There are probably a lot of bugs lurking, though!

    That's nice. I remember I struggeled a lot last time I needed packed structs for my EtherCat experiments. I'll need some UDP comunications for a new project, soon. I'll test it.

  • ersmithersmith Posts: 6,279

    @Rayman said:
    Thanks @ersmith

    Wonder if the new exp and log use Cordic…

    Oops you just said they do…

    Right, exp and log use cordic on P2 and the ROM tables on P1.

  • Hi,
    just a suggestion: Would it be possible to have the builtin ANSI Terminal support line lengths as broad as it's window?
    I think it is limited to 80 chars or so.
    Cheers Christof

  • ersmithersmith Posts: 6,279

    @"Christof Eb." said:
    Hi,
    just a suggestion: Would it be possible to have the builtin ANSI Terminal support line lengths as broad as it's window?
    I think it is limited to 80 chars or so.
    Cheers Christof

    I think the problem is that it's stuck to whatever its original dimensions are, and it always opens at 80 chars wide. I'll have to look to see if that can be changed at runtime, or if not maybe we can add a configuration option to have a different default size. Thanks for the suggestion.

  • roglohrogloh Posts: 6,292
    edited 2026-03-12 22:16

    So I'm (optimistically) trying to build the LVGL project with flexspin and am running into many build problems. Here's one of them:

    Is there a known reason why this example code doesn't work? I've pared it down from some failing source and put it into the single attached file if anyone wants to reproduce it, as well as a screenshot with numbered lines shown.

    I have two issues here. Some strange warning when returning a value from another called function in the calling function's return statement. Types match so I'm not sure why it complains. And also a bunch of build errors happen if I try to assign struct members from pointer dereferencing within a function, but yet it's okay when the same thing is done from main() using local variables instead of arguments...? I'm using v7.6.2 of flexspin here if that mattered. Plus why does it report the same thing multiple time for the same line? Maybe a bug? If so, can it be fixed. Assignments like this are scattered all thoughout the LVGL codebase and are reasonably common for C, it's not that exotic. Almost seems like flexspin is not maintaining all the structure/return types correctly or something like that perhaps and is getting confused as to what can be assigned to what. This is just one category of error I'm seeing but it's fairly common in the codebase. I think cleaning it up may help get a lot further with the build, if it's a bug with the type storage. The full list of source code problems is also attached (as warnings.txt and errors.txt) for reference and much of it relates to types.

    ❯ flexspin -2 error.c
    Propeller Spin/PASM Compiler 'FlexSpin' (c) 2011-2026 Total Spectrum Software Inc. and contributors
    Version 7.6.2 Compiled on: Mar 2 2026
    error.c
    /Users/roger/Documents/Code/temp/error.c:21: warning: incompatible pointer types in return: expected unknown type but got reference to unknown type
    /Users/roger/Documents/Code/temp/error.c:44: error: Expecting identifier after '.'
    /Users/roger/Documents/Code/temp/error.c:44: error: unknown identifier expression in class _struct___anon_9b3f68f60000001c
    /Users/roger/Documents/Code/temp/error.c:44: error: assignment to constant value
    /Users/roger/Documents/Code/temp/error.c:44: error: Expecting identifier after '.'
    /Users/roger/Documents/Code/temp/error.c:44: error: Expecting identifier after '.'
    /Users/roger/Documents/Code/temp/error.c:44: error: Expecting identifier after '.'
    /Users/roger/Documents/Code/temp/error.c:44: error: Expecting identifier after '.'

  • roglohrogloh Posts: 6,292
    edited 2026-03-12 22:23

    Also I found that when I provide a different/unique local name the problem I have in the post above doesn't occur and the build compiles okay. This is not good if we need unique names for struct members and function arguments. It's a lot of work to try to find all these in a large port using lots of structs.

    #if 0  // enabling this code cause build errors
    void lv_subject_set_color(lv_subject_t * subject, lv_color_t color)
    {
        subject->value.color = color;
    }
    #else // but this variant has no error if using a different local paramater name to the field in the struct?  What?
    void lv_subject_set_color(lv_subject_t * subject, lv_color_t color_)
    {
        subject->value.color = color_;
    }
    #endif
    
  • ersmithersmith Posts: 6,279

    @rogloh it looks like there's a fairly fundamental problem in flexspin with the parsing of multi-level method references (like a->b.c). But it's a weird error that's hard to pin down, as it is context dependent. I'll keep looking for it, but I don't know how long it will take to figure it out and come up with a fix.

    Thanks for the bug report!

  • roglohrogloh Posts: 6,292
    edited 2026-03-13 04:30

    @ersmith said:
    @rogloh it looks like there's a fairly fundamental problem in flexspin with the parsing of multi-level method references (like a->b.c). But it's a weird error that's hard to pin down, as it is context dependent. I'll keep looking for it, but I don't know how long it will take to figure it out and come up with a fix.

    Thanks for the bug report!

    No worries Eric :smile: . I'm happy that you are still willing to resolve some of these limitations/issues to help make flexspin an even better toolchain for the P2.

    As I narrow down and pinpoint it I will try to post some more things I've found as well that are preventing me from compiling this LVGL C99 code. Keep in mind I'm definitely not wanting to disparage what you've already got up and running as it's really useful but am just hoping we can improve it so more C code projects can be made to work on the P2 down the track. I feel this C based LVGL project, if it can be made to work okay on the P2, could be really useful for embedded systems with GUI style displays. It's feature rich code footprint can become large and would likely benefit from my external code caching system so it's something I'm looking at closely right now.

    One other question I have and perhaps something that could be altered to improve performance is related to the passing of structs as function return values. In looking into the disassembled function in my post above that related to the warning about unknown types:

    /Users/roger/Documents/Code/temp/error.c:21: warning: incompatible pointer types in return: expected unknown type but got reference to unknown type

    I found that the code it generates includes writing to the heap.

    _lv_color_make
        mov COUNT_, #0
        call    #pushregs_
        add ptra, #20
        add fp, #16
        wrbyte  arg01, fp
        add fp, #1
        wrbyte  arg02, fp
        add fp, #1
        wrbyte  arg03, fp
        sub fp, #18
        mov arg01, #4
        call    #__system___gc_alloc_managed
        mov arg01, result1
        mov arg02, fp
        add arg02, #16
        mov arg03, #4
        call    #__system____builtin_memmove
        mov ptra, fp
        call    #popregs_
    _lv_color_make_ret
        ret
    

    The __system___gc_alloc_managed function then does a bunch of other stuff.

    __system___gc_alloc_managed
        mov COUNT_, #1
        call    #pushregs_
        mov local01, arg01
        mov arg02, #0
        call    #__system___gc_doalloc
        mov arg02, result1 wz
     if_e   cmps    local01, #1 wc
     if_nc_and_z    mov result1, #0
     if_c_or_nz mov result1, arg02
        mov ptra, fp
        call    #popregs_
    __system___gc_alloc_managed_ret
        ret
    __system___gc_doalloc
        mov COUNT_, #3
        call    #pushregs_
        mov local01, arg01 wz
        mov local02, arg02
     if_e   mov result1, #0
     if_e   jmp #LR__0052
        add local01, #23
        andn    local01, #15
        shr local01, #4
        mov arg01, ptr___system__dat__
        add arg01, #24
        call    #__system___lockmem
        mov arg01, local01
        mov arg02, local02
        call    #__system___gc_tryalloc
        mov local03, result1 wz
     if_ne  jmp #LR__0050
        call    #__system___gc_docollect
        mov arg01, local01
        mov arg02, local02
        call    #__system___gc_tryalloc
        mov local03, result1
    LR__0050
        mov arg01, ptr___system__dat__
        add arg01, #24
        wrlong  #0, arg01
        cmp local03, #0 wz
     if_e   jmp #LR__0051
        shl local01, #4
        sub local01, #8
        shr local01, #2
        sub local01, #1 wc
     if_ae  setq    local01
     if_ae  wrlong  #0, local03
    LR__0051
        mov result1, local03
    LR__0052
        mov ptra, fp
        call    #popregs_
    __system___gc_doalloc_ret
        ret
    

    For a function that returned a 3 element structure it seemed like a whole lot of extra work is done and this need to use the heap was really unexpected, as it would add quite a bit of additional overhead on each invocation of the function whenever it returns a struct. I know in general it's not all that efficient to pass and return structures to/from C functions because a copy is required and it's typically better to use pointers to read/write struct members, but I didn't realize that flexspin would need to use the heap for doing this and need to lock memory and garbage collect etc.

    Most of the C compilers I've used would typically use the stack to propagate the struct. When I googled this "do C compilers use the heap or the stack to return structures" I got this:

    Now perhaps there is a way using the stack and local variables to return a struct that is more efficient than all this heap oriented code. I know the struct variable is created on the stack initially and ultimately needs to be copied to somewhere else back at the assignment statement of the caller. If you keep an intermediate COGRAM variable to point to the address that will accept the struct return value (which itself gets preserved on the stack for each level called like these 3 existing variables below do), you could then at return time do the copy from the callee's stack back to the caller at the correct location. Also if the function returning a struct is called and is never assigned to something, this destination pointer variable could just be passed as a NULL pointer which is checked before the copy happens. Obviously there are extra requirements related to keeping track of space for this in the stack frame of each function but seems like this type of approach is the better option for performance and only a single block copy is ever needed per return and no heap use and just one more element passed on the stack frame like the 3 below (one extra clock cycle for each setq transfer in pushregs and popregs and one extra COGRAM long). It's gotta be a lot faster this way, surely.

    What are your thoughts on this, and do you know why the heap was chosen instead of the stack? If you actually step through the entire amount of code that executes on the copying of this struct via the heap you'll see just how many extra functions need to be invoked. It's amazing to see in the code. You'd not want to ever call this underlying function in some inner loop.

    COUNT_
        long 0
    RETADDR_
        long 0
    fp
        long 0
    
  • roglohrogloh Posts: 6,292
    edited 2026-03-13 07:19

    @ersmith Here's another compilation problem I found with flexspin in my LVGL build that I've pared down to something even simpler. This C code compiles okay when defined as a static function, but enabling the "inline" modifier makes it fail to detect the correct types and the compilation fails with the following error.

    Propeller Spin/PASM Compiler 'FlexSpin' (c) 2011-2026 Total Spectrum Software Inc. and contributors
    Version 7.6.2 Compiled on: Mar 2 2026
    error.c
    /Users/roger/Documents/Code/temp/error.c:13: error: incompatible types in return: expected function of 2 args returning int but got int
    /Users/roger/Documents/Code/temp/error.c:19: warning: Bad number of parameters in call to image_cache_common_compare: expected 0 found 2

    Why does it think there should be 0 parameters passed when it's inlined?

    c
    c
    511B
  • roglohrogloh Posts: 6,292
    edited 2026-03-13 07:31

    Here's another one. Can't seem to get the address of a structure passed to a function. Error report seems to think it's getting passed a structure not an address but I'm using the & operator in the expression so it should be an address.

    Propeller Spin/PASM Compiler 'FlexSpin' (c) 2011-2026 Total Spectrum Software Inc. and contributors
    Version 7.6.2 Compiled on: Mar 2 2026
    error.c
    /Users/roger/Documents/Code/temp/error.c:11: error: incompatible types in assignment: expected pointer to _struct___anon_9b3f68f600000002 but got _struct___anon_9b3f68f600000002

    c
    c
    375B
  • roglohrogloh Posts: 6,292

    @ersmith Here's something that may be related to flexspin warnings generated during types checks when using unions and seems like a (minor?) bug. Looks like the check is only being applied to the first member of the union, and a warning is generated if an assignment is made to another member of the union with a different type. If I change the #ifdef to enable the second version it seems okay and does not generate a warning. In any case I found that the code generated is the same in both situations regardless of the warning.

    Propeller Spin/PASM Compiler 'FlexSpin' (c) 2011-2026 Total Spectrum Software Inc. and contributors
    Version 7.6.2 Compiled on: Mar 2 2026
    error.c
    /Users/roger/Documents/Code/temp/error.c:25: warning: mixing pointer and integer types in assignment: expected int but got pointer to const void unknown type
    error.p2asm
    Done.

    c
    c
    859B
  • evanhevanh Posts: 17,142

    @rogloh said:
    Here's another one. Can't seem to get the address of a structure passed to a function. Error report seems to think it's getting passed a structure not an address but I'm using the & operator in the expression so it should be an address.

    I suspect the problem is the attempt to pass the whole struct, rather than a pointer to the struct, as your function argument. That's probably one of those bloaty things that can be done in C++.

  • roglohrogloh Posts: 6,292
    edited 2026-03-14 04:46

    @evanh said:

    @rogloh said:
    Here's another one. Can't seem to get the address of a structure passed to a function. Error report seems to think it's getting passed a structure not an address but I'm using the & operator in the expression so it should be an address.

    I suspect the problem is the attempt to pass the whole struct, rather than a pointer to the struct, as your function argument. That's probably one of those bloaty things that can be done in C++.

    The complaint is on the line where it tries to get the address of the passed struct (ie. function's local copy). Passing the struct itself to the function is okay.
    Note: I changed the code to this instead to fix it.

    With various code tweaks I've fixed a lot of these random problems except for the myriad of dreaded:
    error: incompatible types in assignment: expected _struct___anon_98b868fb0000006d but got _struct___anon_d2d368f40000006d
    and
    error: incompatible types in assignment: expected _struct___anon_98b868fb0000006d but got unknown type
    type of error which I still don't know why are happening. If that problem can be resolved it may compile ok, or at least get to the next step.

  • roglohrogloh Posts: 6,292
    edited 2026-03-15 04:53

    @ersmith I may have found something.

    So I dug into this frequent error a little more:
    error: incompatible types in assignment: expected _struct___anon_98b868fb0000006d but got _struct___anon_d2d368f40000006d
    I wanted to see what is going on so I modified flexspin's frontend/types.c code slightly to output some extra debug where it happens in the code to print the left side of the AST tree for both the source and dest AST's used in the assignment statement (right side of the tree seemed to remain empty in this case so I left it out).

    Here's what I added:

                    ERROR(line, "incompatible types in %s: expected %s but got %s", msg, desttype_name, srctype_name);
                    printf("dest astkind=%d, src astkind=%d\n", desttype->kind, srctype->kind);
                    (IsPointerType(srctype)) ? printf("src is pointer type\n") : printf("src is not a pointer type\n");
                    printf("src AST left tree:\n");
                    AST *tmp = srctype->left;
                    if (tmp)
                    {
                        printf("\tsrc 2 left kind=%d\n", tmp->kind);
                        if (tmp->left)
                        {
                            printf("\t\tsrc 3 left kind=%d\n", tmp->left->kind);
                            if (tmp->left->left)
                            {
                                printf("\t\t\tsrc 4 left kind=%d\n", tmp->left->left->kind);
                                if (tmp->left->left->left)
                                    printf("\t\t\t\tsrc 5 left kind=%d\n", tmp->left->left->left->kind);
                            }
                        }
                    }
                    tmp = desttype->left;
                    (IsPointerType(desttype)) ? printf("dest is pointer type\n") : printf("dest is not a pointer type\n");
                    printf("dest AST left tree:\n");
                    if (tmp)
                    {
                        printf("\tdest 2 left kind=%d\n", tmp->kind);
                        if (tmp->left)
                        {
                            printf("\t\tdest 3 left kind=%d\n", tmp->left->kind);
                            if (tmp->left->left)
                            {
                                printf("\t\t\tdest 4 left kind=%d\n", tmp->left->left->kind);
                                if (tmp->left->left->left)
                                    printf("\t\t\t\tdest 5 left kind=%d\n", tmp->left->left->left->kind);
                            }
                        }
                    }
    
    

    When I feed this simple C code into the flexspin compiler to trigger the error:

      1 #include <stdint.h>
      2 typedef struct {
      3 uint8_t blue;
      4 uint8_t green;
      5 uint8_t red;
      6 } lv_color_t;
      7 
      8 
      9 uint32_t lv_color_to_int(lv_color_t c)
     10 {
     11     lv_color_t *p = &c;
     12     return p->red;
     13 }
     14 
     15 void main (void)
     16 {
     17     lv_color_t x;
     18     uint32_t p=lv_color_to_int (x);
     19 }
    
    

    I get this output showing only that the destination of the assignment is a pointer type. Also for reference here are the AST kind enums in use:
    83= AST_PTRTYPE,
    54= AST_OBJDECL,
    51= AST_OBJECT,
    4= AST_IDENTIFIER

    /Users/roger/Documents/Code/temp/error.c:11: error: incompatible types in assignment: expected pointer to _struct___anon_9b3f68f600000002 but got _struct___anon_9b3f68f600000002
    dest astkind=83, src astkind=51
    src is not a pointer type
    src AST left tree:
        src 2 left kind=54
            src 3 left kind=4
    dest is pointer type
    dest AST left tree:
        dest 2 left kind=51
            dest 3 left kind=54
                dest 4 left kind=4
    

    But when I modifed the test C code to improperly assign the local struct directly to the pointer without an address of operator, I just get the exact same result below. It's as if the address operator (&) is not being parsed correctly into the AST tree somewhere. You may possibly know where this should happen and whether it's a bug in the parser code or some other issue.

    uint32_t lv_color_to_int(lv_color_t c)
    {
        lv_color_t *p = c;
        return p->red;
    }
    

    You can see it's the exact same set of type numbers used in the AST tree. It's like the & has had zero effect when constructing the tree.
    83= AST_PTRTYPE,
    54= AST_OBJDECL,
    51= AST_OBJECT,
    4= AST_IDENTIFIER

    /Users/roger/Documents/Code/temp/error.c:11: error: incompatible types in assignment: expected pointer to _struct___anon_9b3f68f600000002 but got _struct___anon_9b3f68f600000002
    dest astkind=83, src astkind=51
    src is not a pointer type
    src AST left tree:
        src 2 left kind=54
            src 3 left kind=4
    dest is pointer type
    dest AST left tree:
        dest 2 left kind=51
            dest 3 left kind=54
                dest 4 left kind=4
    

    Cheers
    Roger.

  • ersmithersmith Posts: 6,279

    @rogloh said:
    @ersmith I may have found something.

    So I dug into this frequent error a little more:
    error: incompatible types in assignment: expected _struct___anon_98b868fb0000006d but got _struct___anon_d2d368f40000006d
    I wanted to see what is going on so I modified flexspin's frontend/types.c code slightly to output some extra debug where it happens in the code to print the left side of the AST tree for both the source and dest AST's used in the assignment statement (right side of the tree seemed to remain empty in this case so I left it out).

    Thanks for digging in to it so deeply! I think what's happening here is that one part of the code is trying to pass the structure by value, because it's a small struct that fits into a register. But another part of the code wants to pass it by reference, because accessing the individual members (uint8_t) requires memory access -- getting at the individual bytes of a register is slightly complicated for the compiler (mostly for historical reasons and for P1 compatibility). The by-reference side is silently converting the &c back into a regular c (because under the hood a reference c is really a pointer) whereas in fact c is just a regular variable.

    One thing that might serve as a work-around is declaring the struct as having bitfield members, like:

    typedef struct {
        unsigned blue:8;
        unsigned green:8;
        unsigned red:8;
    } lv_color_t;
    

    Those are handled in a radically different way by flexspin because (IIRC) taking the address of a bitfield is forbidden, so we don't have to worry about producing a pointer like &foo.blue.

    Regards,
    Eric

  • @rogloh said:
    @ersmith I may have found something.

    So I dug into this frequent error a little more:
    error: incompatible types in assignment: expected _struct___anon_98b868fb0000006d but got _struct___anon_d2d368f40000006d
    I wanted to see what is going on so I modified flexspin's frontend/types.c code slightly to output some extra debug where it happens in the code to print the left side of the AST tree for both the source and dest AST's used in the assignment statement (right side of the tree seemed to remain empty in this case so I left it out).

    Note that there's a DumpAST function you can use that prints out the given AST in an XML-like manner.

  • roglohrogloh Posts: 6,292

    @Wuerfel_21 said:
    Note that there's a DumpAST function you can use that prints out the given AST in an XML-like manner.

    Thanks Ada, that's useful.

  • roglohrogloh Posts: 6,292
    edited 2026-03-16 01:57

    @ersmith said:

    @rogloh said:
    @ersmith I may have found something.

    One thing that might serve as a work-around is declaring the struct as having bitfield members, like:

    typedef struct {
        unsigned blue:8;
        unsigned green:8;
        unsigned red:8;
    } lv_color_t;
    

    Those are handled in a radically different way by flexspin because (IIRC) taking the address of a bitfield is forbidden, so we don't have to worry about producing a pointer like &foo.blue.

    Regards,
    Eric

    Ok thanks Eric. I'll try this. There were a LOT of flexspin errors related to this particular lv_color_t structure so it may get rid of a lot of them in one go with any luck.
    EDIT: nope, doing that didn't change any of the errors unfortunately. It's the exact same set of errors/warnings I get before I changed it to use bitfields.

Sign In or Register to comment.