Assmbly instruction speed due to clock adjust
electric550
Posts: 122
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
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!
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
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
'' 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
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:
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
·