CLKFREQ returns 4
Daniel Nagy
Posts: 26
Hello,
In PropGCC I'm implementing a simple millisecond timer that runs in a separate cog.
By using CLKFREQ it does not work. After debugging it turns out CLKFREQ returns 4(?), in a system running at 80MHz.
The main call is like this:
The called function looks like this:
I have some faded memories about the actual clock freq is somewhere in memory, and CLKFREQ reads that out, but what overwrites it, if it is the case here? Where does 4 come from?
In PropGCC I'm implementing a simple millisecond timer that runs in a separate cog.
By using CLKFREQ it does not work. After debugging it turns out CLKFREQ returns 4(?), in a system running at 80MHz.
The main call is like this:
cog_run(&clockCycle, 10);
The called function looks like this:
// .h #ifndef CLOCK_H #define CLOCK_H #include <propeller.h> volatile int missionTime; void clockCycle(); #endif // .c #include "clock.h" void clockCycle(){ int dT = CLKFREQ / 1000; //doesn't work, because CLKFREQ returns 4. If I supplement it with dT = 80000 then all is fine. int T = CNT; while(1){ T += dT; waitcnt(T); missionTime++; } }
I have some faded memories about the actual clock freq is somewhere in memory, and CLKFREQ reads that out, but what overwrites it, if it is the case here? Where does 4 come from?
Comments
EDIT: Also the second parameter in your call to cog_run is 10. I believe this should be a pointer to a stack.
EDIT2: The SimpleTools documentation says that the second parameter is the stack size, and it recommends a value of at least 40. As long as you have enough memory I would go with a larger stack size, such as 100 or even 200. A value of 10 is way to small.
EDIT: cog_run should test whether the malloc succeeded, and return 0 if it didn't. It also seems odd that it stores the cog number + 1 at the first long of the stack and returns a pointer to the stack. You could check the return value from cog_run to see what it returns.
Thanks.
I've tried higher values for stack, the behavior is the same.
According to GCC reference, the second parameter is "Number of extra int variables for local variable declarations and call/return stack. This also needs to cover any local variable declarations in functions that your function calls, including library functions. Be liberal with extra stack space for prototyping, and if in doubt, 40 to whatever value you calculate."
But you are right, sometimes it is referred as it should be a pointer to a memory area that could be used as a stack. I'm confused.
(My code is quite small, by the way, 10kbyte or so is sent, and if I comment out the only print, it drops to 4k.) It's only an experiment with an SPI g sensor and an I2C pressure sensor. The print prints out the received data. Now I wanted to add timestamps.
int id;
id = cog_run(&clockCycle, 10);
In LMM mode it returns 17456 (decimal)
In CMM mode it is 10412 (decimal) and CLKFREQ returns 80M as it should.
EDIT: Ah the number returned by cog_run are actually pointers, and not COG IDs (0-7) so the huge numbers are normal. The original problem I still don't understand. In CMM mode it works, in LMM it doesn't.
This evening I'll strip down the code, and if the problem exists with the bare minimum, I'll post it.
Thanks the help so far.
Location 0 contains the frequency of the clock. It should have a value of 80,000,000 if the frequency is 80 MHz. If it contains a value of 4 it must have been overwritten by user code. A NULL pointer is the usual primary suspect when location 0 gets overwritten by C code.
Thanks for your effort. Your logic is not only clear, but you are right as well.
I found that my
i2c_open(hp03_bus, PIN_HP03_SCK, PIN_HP03_SDA, 0);
line is the guilty.
And the root cause is that I don't understand what the first parameter should be.
I've allocated a pointer like this:
i2c* hp03_bus;
and that is the variable you see as the first parameter.
Now I understand i2c_open writes something where that pointer points, and that is an uninitialized zero, hence it overwrites addres 0;.
This is clearly not how that first parameter should be used, I'll have to solve that.
So it appears that the Prop has an interesting way to detect a write using a null pointer. Just check if CLKFREQ changes from the expected value. A diagnostic could run in a separate cog that would spin in a loop checking CLKFREQ, and it could light an LED or print a message if it detects a bad value. Maybe there are other things that a diagnostic cog could look for.
Yes I've already figured out and had done the way you suggested.
Thank you again for your help and thoughts!
Or even better, slaps the dumb programmer's hand if trying to use a null pointer.
Fly Squatter, rubber band and servo? @Erco's flame thrower?
All just one diagnostic cog away!
Enjoy!
Mike
Daniel,
You can go to your first post, and go to the Advanced option. In the mean time, I have done it for you.