switching 3.x between 96MHz/48MHz/24MHz (same F_PLL) on the fly ?

Status
Not open for further replies.

vladn

Well-known member
Is there a simple way to switch 3.x CPU core between between these specific CPU frequencies on the fly without the Snooze library ? All these modes have the same 96MHz PLL frequency, hence I assume that the switch should not affect active peripheral operation.
 
Yes, or maybe, depending on your idea of simple, and no.

Yes, you can switch by just writing to SIM_CLKDIV1. But not all combinations are legal. The hardware has some smart logic to detect and ignore writes with illegal combinations, which you could imagine as making thing simpler (at least horribly wrong things don't happen), but I can assure you it feels pretty frustrating when you're experimenting and all your mistakes result in no apparent changes because there's no feedback you wrote a wrong combination, other than everything stays as it was. However, the logic doesn't keep you from overclocking, and trying to overclock the flash too much will result in crashing.

And no, your assumption about not affecting the peripherals isn't quite right. Almost all the peripherals run from F_BUS, which is also controlled by SIM_CLKDIV1. If you alter F_BUS, all the peripherals change speed. If you go with F_BUS at only 24 MHz, then you'll have much more flexibility to alter the CPU speed. If you use the faster speeds which are the default, those rules about which combinations are legal will come into play and give you very few choices that don't mess up all the peripherals.
 
Thanks Paul,
You gave me a good starting point. Basically at 16ksps audio path I fit into 24MHz CPU speed, but with occasional USB Serial lock-up that requires an effort to recover from (disconnecting the audio board, removing the Windows drivers etc.). This is not surprising since the AudioProcessorUsageMax (corrected to the 16ksps) reports 45% utilization. At 48MHz this does not seem to happen, so I want to add a special UI-selectable mode where I can turn the Serial OFF then slow down to 24MHz, or the opposite - switch to 48MHz and turn the serial ON.
 
It took some effort but the dynamic 24/48 switching seem to work. I have used a 24MHz compile setting and then modified only the core/system clock. I did not change the 24MHz bus clock since it brings up a lot of dependencies. The system/core clock affected only millis() timer, which was trivial to fix, and required slight hacking of the micros() function in the pins_teensy.c file. I've even tried the core clock 96MHz, but the I2C module generated errors running on the 24MHz bus. Basically the core frequency toggle looks like this:
Code:
cpu_2x ^= 1;
SIM_CLKDIV1 = (SIM_CLKDIV1&0x0fffffff)|((3>>cpu_2x)<<28);
SYST_RVR = (F_CPU<<cpu_2x)/1000-1;

My loop() timing improves about 2x at 48MHz, but the AudioProcessorUsageMax() does not change. I did not investigate deeper wether it needs a calculation hack or is it due to DMA timing on a slow bus. I'll check the stability of the USB serial in this 48/24 hybrid mode and report later.

Update: I figured out how to tweak AudioStream.h so I get the correct AudioProcessorUsageMax() reports reducing nearly in half @48MHz core.
However I got another USB lockup in 48M/24M hybrid mode as I did before with the standard 24M. The Windows driver says that it failed to properly reset the USB device. It could be my board or interference with DMA or something else. I need to investigate the 24MHz USB issue further.
 
Last edited:
Status
Not open for further replies.
Back
Top