Shop OBEX P1 Docs P2 Docs Learn Events
Assmbly instruction speed due to clock adjust — Parallax Forums

Assmbly instruction speed due to clock adjust

electric550electric550 Posts: 122
edited 2009-06-10 08:29 in Propeller 1
So I have seen that there are multiple clock frequencies that are allowed with the propeller. I have tried a few different ones. My question concerns code being used with different clock frequencies. I have seen that the spin code allows for configuration of different crystals so that the same code can be used with different xtals by changing the XINFREQ variable. But with assembly it looks as if there is no way to use the same assembly code without modifying it? So for example if I wanted to use the spi object or the serial object (both of which have portions of assembly), I would have to add nops or something similar to slow the code? Thanks for the help!

Comments

  • electric550electric550 Posts: 122
    edited 2009-06-09 22:23
    OK So I just did my own Little test, Someone please explain to me how this is happening. I understand how spin instructions can be scaled, but I am confused as to how the assembly is still working.

    The test used three different Crystals using the 16x pll. The code Involved a combination of reading adc values from the MCP3208 using the spi object on OBEX, then sending the data to a terminal using the fullduplexserialplus at 115200 from OBEX.

    Crystal 1

    I Put in a 5MHz Xtal made the first lines

    CON

    _clkmode = xtal1 + pll16x 'Run at the full 80MHz
    _xinfreq = 5_000_000

    It works Great

    Crystal 2
    I Put in a 6MHz Xtal made the first lines

    CON

    _clkmode = xtal1 + pll16x 'Run at the full 80MHz
    _xinfreq = 6_000_000

    It works Great!

    Crystal 3
    I Put in a 7.3728MHz Xtal made the first lines

    CON

    _clkmode = xtal1 + pll16x 'Run at the full 80MHz
    _xinfreq = 7_372_800

    It works Great!


    So I am really confused as to how all of this code works properly, There is assembly involved and I assumed that the assembly ran 1 instruction per 4 clock cycles... So changing the clk in would surely change the speed at which the assembly runs, thereby creating an error when running the code, such as serial that requires precise timing....

    So since all of these things worked it indicates to me that the assembly routines are running at the same speed with different xtals, does this mean that using a faster xtal is not going to increase the speed of the instruction rate. I guess I am just missing something special that the compiler is doing in order to make this work. Anyways any explanation would be great!
  • TimmooreTimmoore Posts: 1,031
    edited 2009-06-09 22:33
    There are several ways I have seen this. One is the count for waitcnt is calculated either in spin and passed in (e.g. serial port, look for bit_ticks). or in asm (the clock freq is at a fixed place in memory). Or they use a different technique altogether.
  • Mike GreenMike Green Posts: 23,101
    edited 2009-06-09 22:43
    Wrong assumptions ...

    The instruction execution time indeed is different with the different crystals. It's just that it doesn't matter to your hardware. The MCP3208 will operate over a range of speeds as will many external parts.

    The _CLKMODE and _XINFREQ/_CLKFREQ statements are used by the compiler to compute two values: 1) A system clock frequency stored as a long in locations 0-3; 2) A clock mode value stored as a byte in location 4.

    The ROM bootloader uses the RCFAST built-in clock and switches to the specified clock mode (from location 4) just before starting up the Spin interpreter.

    The clock frequency value in locations 0-3 is used by most of the timing dependent I/O drivers to adjust various timing values. The serial drivers use it to compute WAITCNT times for the user specified Bauds. The TV and VGA drivers use it to compute various timing values for the video generators. The assembly I2C driver uses it to compute WAITCNT times for bus timing. All the compiler does is to translate CLKFREQ to LONG[noparse][[/noparse] 0 ] and to place the user specified values in the binary file being produced.

    In assembly language, you can fetch the system clock frequency by using "RDLONG <dest>,#0"

    If you need to reset the clock mode, you can fetch the value of _CLKMODE by using "RDBYTE <dest>,#4"

    Post Edited (Mike Green) : 6/9/2009 10:48:21 PM GMT
  • electric550electric550 Posts: 122
    edited 2009-06-09 23:55
    OK Thanks! So the serial driver's assembly code reads that variable to get the clock counts sinked up? That is interesting I wonder what line in the code is doing that in the fullduplexserialplus driver?

    I also did another experiment I ran the following code with three different crystals

    '' From Parallax Inc. Propeller Education Kit - 4: I/O and Timing Basics Lab

    '' File: LedOnOffP4.spin

    CON

    _clkmode = xtal1 + pll16x 'Run at the full 80MHz
    _xinfreq = 7_372_800
    PUB LedOnOff

    dira[noparse][[/noparse]16] := 1

    repeat
    outa[noparse][[/noparse]16] := 1
    waitcnt(clkfreq/1000+cnt)
    outa[noparse][[/noparse]16] := 0
    waitcnt(clkfreq/1000+cnt)


    and monitored pin 16 with an o-scope the results are...

    With 7.372MHz Crystal and
    CON

    _clkmode = xtal1 + pll16x
    _xinfreq = 7_372_800

    The Square Wave has a period of 2ms

    WITH---6MHz Crystal and
    CON

    _clkmode = xtal1 + pll16x
    _xinfreq = 6_000_000

    The Square Wave has a period of 2ms (Full wave)

    WITH---5MHx Crystal and

    CON

    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000

    The Square Wave has a period of 2ms (Full wave)


    But if I Leave the xinfreq at 5_000_000 for all of them so

    CON

    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000

    with a 5MHz
    The Square Wave has a period of 2ms (Full wave)

    with a 6MHz
    The Square Wave has a period of 1.71ms (Full wave)

    with a 7.3728MHz
    The Square Wave has a period of 1.38ms (Full wave)



    Sorry for the Rough numbers I did not make incredibly accurate measurements. I will try some assembly code and see what the results are when done in that case, anyways thanks!

    Post Edited (electric550) : 6/10/2009 12:48:37 AM GMT
  • electric550electric550 Posts: 122
    edited 2009-06-10 00:19
    I have no Idea if the above calculations are correct btw. I had to ad the 1000 instruction delay because my oscope does not go fast enough
  • electric550electric550 Posts: 122
    edited 2009-06-10 00:24
    OOOPS the above must be way off someone please correct me because the 1000 is not 1000 instructions it is 1000 clk cycles, not only that there are two of them. I will leave the above until the right numbers are found.
  • electric550electric550 Posts: 122
    edited 2009-06-10 00:26
    Just for the fun of it I changed the code to read

    '' From Parallax Inc. Propeller Education Kit - 4: I/O and Timing Basics Lab

    '' File: LedOnOffP4.spin

    CON

    _clkmode = xtal1 + pll16x 'Run at the full 80MHz
    _xinfreq = 30000
    PUB LedOnOff

    dira[noparse][[/noparse]16] := 1

    repeat
    outa[noparse][[/noparse]16] := 1
    waitcnt(clkfreq/1000+cnt)
    outa[noparse][[/noparse]16] := 0
    waitcnt(clkfreq/1000+cnt)

    30000 was the lowest number that still let the prop run...
    and used a clock of 5MHz and on the oscope it is showing that the period of the square wave is 44us

    I just thought I would throw that out there for now
  • electric550electric550 Posts: 122
    edited 2009-06-10 00:27
    So How do I get the above code to run at the 20MIPS that is expected with a 5MHz crystal? Or is it already doing that.
  • kuronekokuroneko Posts: 3,623
    edited 2009-06-10 00:30
    electric550 said...
    So How do I get the above code to run at the 20MIPS that is expected with a 5MHz crystal? Or is it already doing that.
    It already is, MIPS is measured at [noparse][[/noparse]P]ASM level. Not counting hub instructions and waitcnt & Co, one instruction requires 4 clock cycles. At 80MHz that's 20MIPS.
  • electric550electric550 Posts: 122
    edited 2009-06-10 00:43
    Yea I don't know how to factor in the waitcnt at the moment for that calculation, I will have to check it on an oscope that can monitor actual speed without the waitcnts
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-06-10 06:22
    _clkmode = xtal1 + pll16x 'Run at the full 80MHz
    [b]_xinfreq = 30000[/b]
    
    

    is only setting the value for clkfreq (compiler is taking care of that), it is NOT changing·the real speed of the propeller. The real speed of the propeller is FIXED by the crystal you use. The only way to change the real speed is to choose another pll-mode or change to RCFast/RCSlow.
    5MHz crystal·and PLL16 -> 80MHz -> 20MIPS
    5MHz crystal·and PLL 8 -> 40MHz -> 10MIPS
    5MHz crystal and PLL 4 -> 20MHz -> 5MIPS

    So, what happened in your code:
    - say you used the 5MHz crystal and pll16x -> your prop runs with 80MHz (which is 20MIPS for PASM code)
    - but you set _xinfreq to 30000 which will give you the value of 30000*16 (_xinfreq*pll) as clkfreq variable (right value would be 80_000_000)
    - if you now say waitcnt( clkfreq / 1000 + cnt) it's not 1ms which it would be if you would have·given the right _xinfreq. Instead·it is 30_000/80_000_000 * 1ms

    Even below 30_000 the propeller runs. It's only that the waitcnt has a execution time. And for SPIN we talk about some hundred clockcycles of execution time per instruction. So, if the time you want to wait is smaller than the execution-time you will simply miss the right cnt-value and the propeller waits for ~50seconds.

    By the way .. with your experiments you run the prop with up to ~117MHz (@7,3728MHz crystal)

    Advice:
    For _xinfreq you should always give the right frequency. Because objects that need proper timing rely on the right value there.

    The fastest frequency you get with SPIN is:
    repeat
      !out[noparse][[/noparse]16]
    

    If you have to use waitcnt the max. frequency will decrease a lot, because waitcnt needs execution time and the calculation needs execution time as well.

    In general:
    clkfreq is the number of cycles the clock signal has in one second (if you set it correctly;o)
    so, if you say waitcnt( clkfreq+cnt ) the prop will wait for one second at any crystal you use ( again - as long as you set _xinfreq correctly)
    if you say waitcnt( clkfreq/1000 + cnt ) the prop waits for 1ms
    ·
  • electric550electric550 Posts: 122
    edited 2009-06-10 08:13
    Thanks. I just finished reading desilva's assembly paper. So when I get some time I am going to write up the assembly and check with the oscope...I am sure it will turn out the way it has been described. I was trying to use the waitcnt to slow down the pin so it was easier to see on the oscope, but I didnt realize that waitcnt was not the best way to test the clk speed. Anyways thanks again!
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-06-10 08:29
    If you want to measure the clock-frequency then simply use a counter to toggle a pin. The counters are driven by the clock. With counter-mode and the frequency register of the counter you can slow down the toggle (divide it), so it's not to fast for you scope.
Sign In or Register to comment.