Beauty of _clkfreq
Erlend
Posts: 612
I am wondering - the example I have been following so far, to set the clocking frequency is this:
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
-but it is so convenient to define time constants based on _clkfreq, so I like this format better:
CON
_clkmode = xtal1 + pll16x
_clkfreq = 80_000_000
mSec = _clkfreq / 1000
uSec = mSec / 1000
CintBitDurVM2 = _clkfreq / 9600
Is there a nuance I am not aware of? - if not, why is this format not used more frequntly?
Erlend
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
-but it is so convenient to define time constants based on _clkfreq, so I like this format better:
CON
_clkmode = xtal1 + pll16x
_clkfreq = 80_000_000
mSec = _clkfreq / 1000
uSec = mSec / 1000
CintBitDurVM2 = _clkfreq / 9600
Is there a nuance I am not aware of? - if not, why is this format not used more frequntly?
Erlend
Comments
even if you define:
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
you can still do:
mSec = _clkfreq / 1000
uSec = mSec / 1000
CintBitDurVM2 = _clkfreq / 9600
the compiler will do that for you. Where is the problem?
Enjoy!
Mike
So I thought, but when I tried it the compiler complained that _clkfreq was an undefined sybol.
Erlend
his reply
I think that is where it ended, still a mystery. It really isn't a big deal. If you need the startup clock frequency, store it in ram or eeprom during initialization.
-it really is handy.
Erlend
Erlend
Sandy
I do projects with different crystals (using 6.5 in one now), so I like this form.
I like your way of doing things, too. You don't need to subtract xtal1 from _clkmode, though, since that value gets shifted out.
-Phil
Yes. I looked up my code where I did this and pik33 is absolutely right!
So the _clkfreq is not available but clkfreq is. Funny.
Enjoy!
Mike
I will adopt this method:
Thank you for the discussion
Erlend
CLKSET(mode,frequency)
It mysteriously does not digest _clkfreq when the project has been started using _clkmode and _xinfreq. The goal is to switch modes and then at times switch back to the original mode declared at the top. I like the approach using
__clkfreq = (_clkmode >> 6) * _xinfreq ' double underscore for __clkfreq
So, the mode declared at the top can still be changed for the project as a whole. However, time constants based on that such as MSEC and USEC would then apply only when that particular frequency is active.
I still prefer to read the actual clkfreq as the program starts up and store that in a variable or even in user eeprom. If an object that becomes subsumed under another top object, that parent object's declarations prevail and the constants in the child version are ignored. Better to track the real time clkfreq variable.
You can see this in the Eddie firmware which defines: …and uses _clkfreq in constants, for example using this line to wait half a second:
— David Carrier
Parallax Inc.
The child object that contains the above code contains another child object that has the actual wait routine: This is called from just about every object in the project. Things seemed fine for the most part but occasionally it's almost as if there is no wait at all (I have a 5 second wait in the top object that doesn't seem like it waits at all and previously had an issue where the wait is less than expected. Am I missing something? If clkfreq is a variable (should be global?) then why would I be having problems. And why wouldn't this be popping up all over the place?
(edit)
I was able to fix my issue by changing this in the child object containing the wait routine:
And then changing the parent object code to:
I still don't understand why this is an issue. Is it that the clkfreq variable propagates from parent to child but not from child to parent?
Hard to say without more clues. clkfreq is a system variable accessible anywhere, so the parent-child propagation is unlikely an issue. More likely a timing issue. When operating at 20kHz, it can take longer than expected to execute spin code. And when switching down in frequency, data left unsent or received in serial buffers can cause insidious problems. Do your ReadExpander and WriteExpander methods by any chance rely on asynchronous serial?
Thanks for your response. The expander methods rely on I2C (spin) so this isn't the issue. I've been having difficulty determining the issue since obvious bug really doesn't make sense to me. The clock has been running for quite some time when the program reaches the offending code. I wish I could post the entire code but am unable to at this time. Here's the offending portion of code:
The issue was that the 5 second pause never paused. (Or if it did, it was less than a second) I should have noted the other bugs as I went. If memory serves correct, the waitcnt right after switching clock frequency was formatted using the pause1ms and didn't pause either. I have not changed the formatting back yet since I have other issues bumping around. The one thing I can say is I'm pretty sure it's NOT stack issues. Other than that, I'm not sure what to do in order to track these issues further.
(edit)
One more piece of info, at this point the program never switches back to an internal clock source. Still just trying to get everything working. Hopefully I won't have too many issues when switching to internal clock since this is just done for power saving when the system will be idle for extended periods of time.
clkfreq returns the current system clock frequency while _clkfreq returns to system clock frequency at startup. Page 64 in the Propeller Manual v1.1.
Sandy
That was the way I originally fixed that problem (as well as a few other instances of this bug). The update ticks method works and now the bug has completely disappeared. Now I'm going back and replacing the instances of waitcnt with pause1ms. This is my preferred method as I can use named constants (in MS) and it's quite a bit easier to read. I just thought it was a very strange problem to have and still don't understand what was causing it. I should have run it through a few different compilers to see if it was PropTool specific.
For some reason, this is not evaluated properly. This is the same program as before, that starts on RCfast, then enables Xin + PLLx8 @80Mhz. But I bet
repeat until (rxbyte := rxcheck(port)) => 0 or (cnt - t) / (cons.getMS) > ms will work fine!
edit
...
Nope, that waits forever as well... hmmm?
The advantage is that it can respond faster in case there is already a char waiting in the receive buffer when the RxTime method first executes. It doesn't have to evaluate the time condition unless the buffer is empty, so it can keep up with a faster stream and avoid dropping characters. It is better still if ticksPerMs can be pre-evaluated in a Start method and with each clockset change of clock frequency. The variable ticksPerMs will not be a global variable like clkfreq though.
You show accessing your timeout value via a method in another object, cons.updateTicks. Does that value propagate to the object (fds4port) that contains the RxTime method? That should be done along with restarting the serial port driver.
@JM. I am starting serial driver AFTER the clock change.
@TA. I was just thinking about something similar. But I'll get to that in a minute...
XBee_ObjectC.spin contains RXtime. Settings.spin is cons.xxx The PUB SetClock(mode) method is contained in MemWrapper.spin.
This is Settings.spin
So the answer to " Does that value propagate to the object (fds4port) that contains the RxTime method? " should be yes? (Since ms is declared as dat?)
I'm wondering if I should move the PUB SetClock(mode) method into Settings.Spin
The way I was thinking about evaluating the timeout was:
I did find an error.. I was running my clockset at the wrong entry point, so ABORT ?could? mess with clock setting? IE.
Don't know what this would have to do with it...
But, for some reason.