I believe I am finding some clarity. I tweaked the simple test to estimate the loop count for 30 seconds, so the 32kHz timer count would be approximately the same regardless of clock rate to reduce/eliminate the impact of timer granularity. This also means the test will ābakeā for 30 seconds at each clock rate, where before it spent 30 second at 32MHz, then ~3 seconds each at 288MHz, 320MHz. Weāll see the impact of that pretty readily.
Also added calculation of the clocks per iteration, so I donāt have to calculate that manually.
The test does a trial at 32MHz, 288MHz and 320MHz, in that order, and I see results like this, where the first number is the return value of metal_clock_set_rate_hz() and the second number is clock cycles * 10:
starting test
32000000: 946
288000000: 946
320000000: 945 : Consistent 94.5/94.6 clocks per loop. Awesome
32000000: 946
288000000: 946
-42450944: 0 : Error setting 320MHz; letās hit the MCU with dust-off to cool it down
32000000: 946
288000000: 946
320000000: 946 : ah, thatās better, a little more dust-off
32000000: 946
288000000: 946
320000000: 946 : still good, no more dust-off
32000000: 946
288000000: 945
320000000: 945 : still good!
32000000: 946
288000000: 945
-42450944: 0 : whoops, warmed-up again (continued trials have the same result)
First of all, with a better test that eliminates granularity errors in the measurement, I get the same result, 94.6 clocks per call to mrand48(). Second, heating seems to make the PLL fail to lock at 320MHz.
I think Iāve cleared-up my own confusion here; sorry for the fire-drill.
Dana
Hereās the code for the test function:
void
do_run(long clock_rate)
{
struct metal_rtc *rtcd;
long new_cpu_clock;
uint64_t t1, t2;
static long last_cpu_clock = 0;
float cycles;
int32_t loop_count;
new_cpu_clock = metal_clock_set_rate_hz(&__metal_dt_clock_4.clock,
clock_rate);
last_cpu_clock = new_cpu_clock;
/* estimate loop count for 30 seconds */
loop_count = ((double)new_cpu_clock * 30.0) / 95.0;
rtcd = metal_rtc_get_device(0);
t1 = metal_rtc_get_count(rtcd);
for (int32_t i = 0; i < loop_count; i++) {
// (void) metal_gpio_toggle_pin(gpd, 5);
(void)mrand48();
}
t2 = metal_rtc_get_count(rtcd);
cycles = (((double)(t2 - t1) / 32768.0) * new_cpu_clock) / loop_count;
printf("%ld: %d\n", new_cpu_clock, (int)(cycles * 10.0));
}