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

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

1545556575860»

Comments

  • Could it be that the function __builtin_frac is not implemented although it is in the documentation (c.pdf)? I get an error "unknown identifier _builtin_frac used in function call" when trying to do something like

        _pinstart (pinDrClk, MODE_DRCLK, 1, __builtin_frac(FREQ_DRCLK, CLK_FREQ));
    

    Do I need to #include something else additionally to "propeller2.h" to make it work?

  • ersmithersmith Posts: 6,202

    __builtin_frac was supposed to be a builtin keyword to C, but somehow it's missing from the C keywords table. I will fix that in the next release (it's fixed in github now). Thanks for catching this!

    In the meantime you can work around this by defining a function like:

    unsigned myfrac(unsigned a, unsigned b) {
        unsigned r = 0;
        __asm {
            setq a
            qdiv r, b
            getqx r
        }
        return r;
    }
    

    which should usually expand to the same code as the builtin, at least on P2 (the builtin will also work in some other environments).

  • Christof Eb.Christof Eb. Posts: 1,410
    edited 2025-08-19 10:01

    Hi,
    is there something wrong with _cogstop() ? (version 7.4.1)
    I had crashes with it, while

       __asm {
       cogstop tos 
       } ;
    

    works.

    Christof

  • ersmithersmith Posts: 6,202

    @"Christof Eb." said:
    Hi,
    is there something wrong with _cogstop() ? (version 7.4.1)
    I had crashes with it, while

       __asm {
       cogstop tos 
       } ;
    

    works.

    _cogstop is defined with the same inline assembly, so it should generate the exact same code. Do you have an example where it doesn't? (You can always look at the .p2asm file, or the listing file id -l is given). Any details of the context or surrounding code?

  • MicksterMickster Posts: 2,874

    Just playing around the other day, blinking an LED in its own cog. Cogstop didn't behave as expected, the LED started blinking erratically. This was FlexBasic.

  • ersmithersmith Posts: 6,202

    @Mickster @"Christof Eb." Do either of you have any examples of these problems? cpustop works in the examples I've tried, so it's not obviously broken. Whatever problem you're having is somehow context dependent, and I don't have enough information to debug it.

  • Another riddle, perhaps related?

    #define TOS PR0
    ....
    
    
    // scaling: ( cos*10000 -- degrees*10000 )
            TOS= (int)(572957.795130823*acos((1.0*(int)TOS)/10000.0)); // works 
    
    // TOS= (int)(572957.795130823*acos((1.0*TOS)/10000.0)); // did only work for positive arguments
    

    Why is this (int) before TOS needed?

    I have for cogstop:

    /*
    PRIMI(cogstop) { // ( COGnr -- )  stop the cog -- does not work
       _cogstop(TOS); 
       _drop();
    }
    */
    
    PRIMI(cogstop) { // ( COGnr -- ) \ stop the cog
       __asm {
       cogstop tos 
       } ;
       _drop();
    }
    
  • @"Christof Eb." To answer "why does this work but that not" questions like that, grab the .p2asm file the compiler generates for both versions and run them through a diff tool.

  • @Wuerfel_21 said:
    @"Christof Eb." To answer "why does this work but that not" questions like that, grab the .p2asm file the compiler generates for both versions and run them through a diff tool.

    Yes, I could dive into this question. At the moment I am busy doing other things. I do mostly not understand, how the compiler works or it's floating point library. It's a tool for me. So I would have to invest ???? time.
    My question was on another level. I asked (myself), why this (int) does change anything, as TOS alias PR0 already is a signed int32. In my opinion up to now (allways learning :# ), this (int) should not be necessary.
    Christof

  • MicksterMickster Posts: 2,874

    @ersmith said:
    @Mickster @"Christof Eb." Do either of you have any examples of these problems? cpustop works in the examples I've tried, so it's not obviously broken. Whatever problem you're having is somehow context dependent, and I don't have enough information to debug it.

    Oh, naturally it started to work now :D

    const _clkfreq = 280_000_000
    
    sub for "cog" blink()
       do
         pintoggle(57)
         pausems 200
       loop
    end sub
    
    sub blinkstub()
      blink()
    end sub
    
    dim mystack as byte(128)
    
    var cogid = cpu(blinkstub(), @mystack(0))
    print cogid
    pausems(4000)
    cpustop(cogid)
    

    Incidentally, this is the example that you provided to demonstrate the need for the stub procedure.
    Was this a temporary thing or a standard requirement?

    Regards,

    Craig

  • ersmithersmith Posts: 6,202

    @"Christof Eb." said:
    Another riddle, perhaps related?

    ```

    define TOS PR0

    ....

    Why is this (int) before TOS needed?

    Most hardware registers are considered to be unsigned integers. In order to treat them as signed you have to explicitly cast them. PR0 to PR7 aren't exactly hardware registers, but they're still treated as such.

    I have for cogstop:

    /*
    PRIMI(cogstop) { // ( COGnr -- )  stop the cog -- does not work
       _cogstop(TOS); 
       _drop();
    }
    */
    
    PRIMI(cogstop) { // ( COGnr -- ) \ stop the cog
       __asm {
       cogstop tos 
       } ;
       _drop();
    }
    

    TOS and tos are different identifiers in C, so these codes will do different things.

  • ersmithersmith Posts: 6,202

    @Mickster The stub is no longer necessary on P2. It is still required on P1 (and will produce an error message in that case).

  • MicksterMickster Posts: 2,874

    @ersmith said:
    @Mickster The stub is no longer necessary on P2. It is still required on P1 (and will produce an error message in that case).

    Sure enough...tested :+1::)

  • Christof Eb.Christof Eb. Posts: 1,410
    edited 2025-08-21 06:54

    @ersmith said:

    @"Christof Eb." said:
    Another riddle, perhaps related?

    ```

    define TOS PR0

    ....

    Why is this (int) before TOS needed?

    Most hardware registers are considered to be unsigned integers. In order to treat them as signed you have to explicitly cast them. PR0 to PR7 aren't exactly hardware registers, but they're still treated as such.

    Hm, it is most important for my Forth compiler, that PR0...PR7 are sitting in cog ram and I see each cell of this memory space as a "hardware register", as all of them can do maths like a traditional accumulator. This is the way I can share the same registers between assembler in a Spin2 file and C.

    I have for cogstop:

    /*
    PRIMI(cogstop) { // ( COGnr -- )  stop the cog -- does not work
       _cogstop(TOS); 
       _drop();
    }
    */
    
    PRIMI(cogstop) { // ( COGnr -- ) \ stop the cog
       __asm {
       cogstop tos 
       } ;
       _drop();
    }
    

    TOS and tos are different identifiers in C, so these codes will do different things.

    Oh, sorry, of course there is

    ....
    // PR0–PR7 are in $1D8–$1DF
    #define tos PR0
    #define TOS PR0
    ....
    

    So after preprocessing, the compiler should see the same thing.

    I will try to provide full/real code later.

  • Perhaps you could modify the text somehow to reflect that it is really
    "extern register unsigned int"

    Global Register variables
    Global variables are normally placed in HUB memory, and local variables in COG memory (registers). The assembly backends permit variables to be declared as extern register, in which case they are placed in COG memory. Such variables cannot be initialized.

    extern register int *interpreter_pc;

    int fetch() {
    return *interpreter_pc++;
    }

  • ersmithersmith Posts: 6,202

    @"Christof Eb." said:
    Perhaps you could modify the text somehow to reflect that it is really
    "extern register unsigned int"

    Variables that are explicitly defined as extern register will have whatever type they are declared as, e.g. in

    extern register int *pc;
    

    has type int * (pointer to int).

    The builtin registers like _OUTA and _PR0 have type unsigned int. But they can be cast to any type you like.

  • @ersmith said:

    @"Christof Eb." said:
    Perhaps you could modify the text somehow to reflect that it is really
    "extern register unsigned int"

    Variables that are explicitly defined as extern register will have whatever type they are declared as, e.g. in

    extern register int *pc;
    

    has type int * (pointer to int).

    The builtin registers like _OUTA and _PR0 have type unsigned int. But they can be cast to any type you like.

    Ah, thank you for this explanation!

Sign In or Register to comment.