Shop OBEX P1 Docs P2 Docs Learn Events
Pitfalls and crawling out... GetSec() behaves not as I expected, to slow and counting down — Parallax Forums

Pitfalls and crawling out... GetSec() behaves not as I expected, to slow and counting down

ErNaErNa Posts: 1,800
edited 2025-03-11 11:32 in PASM2/Spin2 (P2)

I use this setting for timing:

con { timing }

  CLK_FREQ = 200_000_000                                        ' system freq as a constant
  MS_001   = CLK_FREQ / 1_000                                   ' ticks in 1ms
  US_001   = CLK_FREQ / 1_000_000                               ' ticks in 1us

  _xtlfreq = 20_000_000 '25_000_000
  _clkfreq = CLK_FREQ                                           ' set system clock

repeat
    term.PutValhex ( 5, 15, "i", ":", GetCt() )
    term.PutValhex ( 5, 16, "T", ":", Getsec() )
    term.PutValhex ( 5, 17, "S", ":", GetmS() )


But GetSec() needs about 10 seconds to count. Do I have to configure something else?
The baud rate works perfect with the setting, I'm using a P2 Eval board
p.s. GetSec counts backward

Some more analysis: GetCt() works as expected, Getsec() counts when GetCt() wraps round. Getms() counts fast, but not milliseconds and GetSec and Getms start at $FFFF_FFFF and count down

Strange things happen: If I use Getsec() is a demo program, it works fine. But no longer in the application., running in a different COG. GetSec() actually counts backward at the overflow of GetCt().
I'll run more tests when time comes..

Comments

  • JonnyMacJonnyMac Posts: 9,243
    edited 2025-03-02 21:30

    It's very possible that you're creating a buffer overrun in the terminal you're using. There is no breathing room between loops in your code to let the terminal clear its buffer. If it takes more time to process/display your input than it does for the terminal to receive it, you'll eventually step on yourself.

    I ran a simple test and getsec() works as expected (incrementing count). I used PST (which has that overrun problem if you don't give it breathing room).

  • JonnyMacJonnyMac Posts: 9,243

    This seems to work, too:

  • ErNaErNa Posts: 1,800

    Thanks for help, it was just to take advantage of this new feature. The application is quite complex and doesn't work completely, I finally did it the old-fashioned way and now the display show the right ticks of seconds. The moment the screen updates all the variables (just now, it is reluctant), I'll give GetSec() another try.

  • ErNaErNa Posts: 1,800
    edited 2025-03-02 22:33

    Where to find the subtle difference between
    _clkfreq, clkfreq and clkfreq_?

  • evanhevanh Posts: 16,345
    edited 2025-03-02 23:09

    Last section, called Clock Setup, of Spin 2 Language Documentation - https://docs.google.com/document/d/16qVkmA6Co5fUNKJHF6pBfGfDupuRwDtf-wyieh_fbqw

    • _clkfreq and _clkmode are the user constants of desired startup sysclock frequency/mode to be compiled. Should never be used in methods. Only define in the CON section.
    • clkfreq_ and clkmode_ are the compiled constants of startup sysclock frequency/mode. Use these in your methods.
    • clkfreq and clkmode are system variables that contain dynamic runtime settings. These are adjusted by clkset(). If such is used then all timing methods should also use these variables in place of the above compiled constants.

    I used both in pllset() method. It adjusts the runtime variables as well as extracting board specific compile-time parameters from the constants - https://obex.parallax.com/obex/pllset/

  • ErNaErNa Posts: 1,800

    OK. I now have a first statement in the Main: clkset (clkmode_, clkfreq_) and the program show sound behavior, no symptoms of overrun. Another step. Thanks.

  • ErNaErNa Posts: 1,800

    I'm falling into another pit: as mentioned, I initated clkfreq : clkset (clkmode_, clkfreq_) A timer is running on a cog started. This timer created problems before, because I migrated software from the P1, that used clkfreq, the compiler was fine with that.
    Now I'm working to implement Cluso's LCD driver, overcome some hurdles, but so far, it's ok. What happens: In the main I create a tick reading clkfreq
    if (tick - GetCt()) < 0 Lcd_.HandsRoundclock() tick += clkfreq ' +1S
    This works as long as I do not activate the other cog creating a tick. I checked, I never write to clkfreq and I only once use clkset.
    If I change clkfreq to clkfreq_, it works fine.
    The behavior is, that clkfreq looks to be a constant, because ticks run for about the same time as they stall. I'll try to find the reason, but any idea is welcome.

  • If you only want to set speed once, do not use CLKSET, just set

    CON
    _CLKFREQ = 300_000_000 ' Or whatever you need it to be
    

    Computing the right clkmode value at runtime is tricky

  • ErNaErNa Posts: 1,800

    If I understood correctly, clkfreq and clkfreq are constants. clkfreq is a register. From Spin-documentation:
    CLKSET(NewCLKMODE, NewCLKFREQ) Safely establish new clock settings and update CLKMODE and CLKFREQ.
    As ClkFreq is located in Hub-Ram, I suspect, I accidently overwrite this location, have to investigate...

  • evanhevanh Posts: 16,345

    @ErNa said:
    clkfreq is a register.

    HubRAM variable only.

    As ClkFreq is located in Hub-Ram, I suspect, I accidently overwrite this location, have to investigate...

    That would be bad,

  • JonnyMacJonnyMac Posts: 9,243
    edited 2025-03-10 17:18

    I'm really simple. I set the program running speed from the constants section in my topmost cog.

    con { timing }
    
      CLK_FREQ = 200_000_000                                        ' system freq as a constant
      MS_001   = CLK_FREQ / 1_000                                   ' ticks in 1ms
      US_001   = CLK_FREQ / 1_000_000                               ' ticks in 1us
    
      _clkfreq = CLK_FREQ                                           ' set system clock 
    

    Since child objects don't have access to my CLK_FREQ constant, they use the system variable clkfreq to determine running speed when needed.

  • evanhevanh Posts: 16,345

    @JonnyMac said:
    Since child objects don't have access to my CLK_FREQ constant, they use the system variable clkfreq to determine running speed when needed.

    Wise move for library type code. It can then handle the user program making runtime frequency changes too.

  • ErNaErNa Posts: 1,800

    OK, it looks as if the hub ram is corrupted. I output the value, correct 200.000.000, the moment, the other program starts, it nullified. So there is a bug in another place and I have to find it. So using this register is a bug-indicator ;-)

  • ErNaErNa Posts: 1,800

    clkfreq is located $44 in hub memory. So it is unlikely I overwrite this location and the SPIN-interpreter is not corrupted? I tested $40 and $48, they are unchanged ;-(

  • ErNaErNa Posts: 1,800

    I'm coming close:

                 long[LONG[@Val011[MirrOffs]]] := ((long[LONG[@Val014[MirrOffs]]]*AnzaPoPa)<<12 / WklMeDiv)//3600  
                 long[LONG[@Val009[MirrOffs]]] :=   long[LONG[@Val014[MirrOffs]]]          <<12 / WklMeDiv
                 long[LONG[@Val007[MirrOffs]]] := (((long[LONG[@Val079[MirrOffs]]]*((ClkFreq~>8))) / long[LONG[@Val080[MirrOffs]]]~>8)*60) / IncrRevo
    

    I can see, that clkfreq ($44) is set to zero, if and only if, the last of the lines above is executed. If the line is commented out, the timer runs correctly! Maybe there is a bug only when this program is running on a P2. We'll see.

  • evanhevanh Posts: 16,345
    edited 2025-03-10 23:14

    Yep, the ~ operator changed from Spin1 to Spin2. It now erases the variable!
    From docs:

    var~ Return var, post-clear all bits in var

    EDIT: Oh, err, wow, never even knew about ~> operator. The equivalent Spin2 is: (ClkFreq SAR 8)

    PS: I wouldn't used that operator though. The frequency variable is unsigned in nature. Just use >> right-shift operator instead.

  • ErNaErNa Posts: 1,800
    edited 2025-03-11 07:55

    That's unexpected:
    Separation of ClkFreq fixes the problem!

                 fxck := ClkFreq
                 long[LONG[@Val007[MirrOffs]]] := (((long[LONG[@Val079[MirrOffs]]] * (( fxck~>8))) / long[LONG[@Val080[MirrOffs]]]~>8)*60) / IncrRevo
    

    Even if I shift ClkFreq~>2, the variable is set to $0

  • ErNaErNa Posts: 1,800

    @evanh said:
    Yep, the ~ operator changed from Spin1 to Spin2. It now erases the variable!
    From docs:

    var~ Return var, post-clear all bits in var

    PS: I wouldn't used that operator though. The frequency variable is unsigned in nature. Just use >> right-shift operator instead.

    Thanks, luckily you didn't know about this operator.
    I had changed ~> to SAR in other source files, but it slipped through here. You see other places, and I wouldn't have the starting point if not clkFreq was nulled. ;-) Lucky me.

  • ErNaErNa Posts: 1,800

    A next problem:

              x := byte[@SH00][sprev*2+1]   << 24
              x := x SAR 24
              drawLine(CX, CY, CX + byte[@SH00][sprev*2], CY + x, fgm)'bgd)   ' remove prev second hand
    '          drawLine(CX, CY, CX + byte[@SH00][s_cur*2], CY + byte[@SH00][s_cur*2+1], fgs)   ' show second hand
    

    I'm modifying Clusos LCD-demo to have a clock, I can move around. Adding byte valued hands coordinates to a long results in an error if the byte value is negative.

    Had to find SIGNX.

  • ErNaErNa Posts: 1,800

    I just run into a problem when migrating from DIRA[7..0] in P1 to the P2. I have to use Port B. For single pins it is working, but no range does what expected. Is there a simple replacement or do I really have to study the smart pins just now?
    PINLOW [39..32] works, but that is not a simple replacement. Is there a "PINTOGGLE" function?

  • Is there a "PINTOGGLE" function?

    Yes. Spin2 is documented here:
    -- https://docs.google.com/document/d/16qVkmA6Co5fUNKJHF6pBfGfDupuRwDtf-wyieh_fbqw/edit?tab=t.0#heading=h.1h0sz9w9bl25

    You'll find

    • pinhigh()
    • pinlow()
    • pintoggle()
    • pinwrite()
    • pinfloat()
    • pinread()

    To deal with multiple pins you need to create a pin group with addpins.

      pinlow(32 addpins 7)
    

    If you're writing to an 8-pin bus, you can do this

      pinwrite(32 addpins 7, value)
    

    To keep you code cleaner and easier to edit, you can define the bus pins group as a constant

    CON
    
      LCD_BUS = 32 addpins 7
    
Sign In or Register to comment.