Can the F_BUS_ACTUAL (peripheral clock) be increased?

Is it possible to increase the F_BUS_ACTUAL clock in order to get higher timer clocks?

Usually yes, but officially NXP says 150 MHz is the maximum peripheral clock, so technically anything faster is overclocking.


Another question: Why is the F_CPU_ACTUAL not 600MHz?

It is 600 MHz, unless you choose a different speed from Tools > CPU Speed.

To confirm, just run this:

Code:
void setup() {
}

void loop() {
  Serial.println(F_CPU_ACTUAL);
  delay(500);
}

The variable is initialized to 396 MHz because the chip defaults to 396 MHz at boot. It only becomes 600 MHz when the startup code runs and programs the PLL for your clock speed.
 
As far as I have now understood from the code, the cpu clock and the bus clock are related by a factor of 4: F_BUS_ACTUAL * 4 = F_CPU_ACTUAL. That means, with 1008 MHz overclock I would have a 252 MHz bus clock. Should work with very good cooling?
 
Indeed the BUS factors up with CPU speed.

With enough cooling it typically works - out of spec - and hard on the chip reducing lifespan even when cool enough with higher voltage in use ... typical OC caveats.

Fan and heat sink combo safest and measure the temps.
 
Should work with very good cooling?

There are never any guarantees or promises regarding overclocking.

In my personal experience, 1.008 GHz wasn't reliable with a moderately sized heatsink. It got very hot.

All substantial overclocking which has to raise the CPU core voltage can be expected to decrease the longevity of the IMXRT chip. Again, how much isn't really known. But without a heatsink, the part won't last long. As I recall, Defragster confirmed this some time ago.
 
Indeed changed out T_4.0 with heat sink and IDE set at ~900 MHz to a fresh bare T_4.0 without adjusting 'forgotten' clock setting.

But was first try with an i2c display - kept hanging and assumed it was display code ... recompiled and tried diagnosing the 'display issue' and after an hour or so of that - mosyly sitting powered but idle reading code - it was burned up.
 
You can also just decrease the divisor to two. The lets you use CPU 600MHz / BUS 300MHz, so you overclock the bus only. No overheating.
But even that is sometimes unstable. I tried that in the T4 beta phase. If you don't use much FBUS connected periphals, it's ok. As soon you do more, it's not 100% stable anymore, and sometimes (not often) you get weird effects. I'd just try that. Or, perhaps div 3 is OK? Don't remember if that worked or was possible.
 
Seems tried it at /3 to see if RAM2/DMAMEM ran faster ... didn't seem much faster and may have been some issue - so wasn't going to mention that ...
 
I have an application where I would have to count around 100 MHz with GPT1. 110MHz would be even better. If I have understood the whole thing correctly, I need a bus frequency of >=220 MHz. Right?
 
Last edited:
You can also just decrease the divisor to two. The lets you use CPU 600MHz / BUS 300MHz, so you overclock the bus only. No overheating.
But even that is sometimes unstable. I tried that in the T4 beta phase. If you don't use much FBUS connected periphals, it's ok. As soon you do more, it's not 100% stable anymore, and sometimes (not often) you get weird effects. I'd just try that. Or, perhaps div 3 is OK? Don't remember if that worked or was possible.

Is it allowed to change the divisor? Then I could do CPU=450MHz (/divisor=2) -> BUS=225 MHz? Here only the bus would be overclocked. I want to count the pulses on pin 25 with GPT1 and capture the counter reading with a 2nd capture pin.
 
Early in the development of Teensy 4 (like in 2018, before the first beta test boards) I had wanted to make the CPU speed easy to change at runtime. That's why I went to so much trouble to write the set_arm_clock() function which today is in clockspeed.c. That's why all the timing code uses F_BUS_ACTUAL and F_CPU_ACTUAL.... in hope of someday making the speed easily scalable at runtime.

But unfortunately NXP didn't give us a glitchless mux for the peripheral clock. A lingering question which I've never really had time to go back and explore, is whether we can safely change the IPG_PODF bits in the CCM_CBCDR register after peripherals are configured and running. It's just not clear to me.
 
Would you repeat your video ... with the Teensy 4.1?

No, or at least not anytime reasonably soon. Those sorts of edited videos take an incredible amount of time. I'm far behind on several important software developments, and on written docs (which are also time consuming, but nothing like editing video) so I just don't have the extra hours to produce videos right now. Hope to be able to do more of those videos someday, but the realistic, that day seems to be quite a long way in the future.
 
Teensy 4.1: What is wrong here? At 10 MHz I have exactly 10 MHz on the counter. Increasing the oscillator >10 MHz leads to incorrect counting results.

Code:
static inline void counter_init(void)
{
  CCM_CCGR1 |= CCM_CCGR1_GPT(CCM_CCGR_ON) ;  // enable GPT1 module
  GPT1_CR = 0;
  GPT1_SR = 0x3F; // clear all prior status
  GPT1_CR =  GPT_CR_CLKSRC(3);// | GPT_CR_FRR ;// 3 external clock
  *(portConfigRegister(25)) = 1;  // ALT 1
}

static inline void counter_start(void)
{
  GPT1_CR |= GPT_CR_EN; // enable
}

static inline uint32_t counter_read(void)
{
  return GPT1_CNT;
}

volatile uint32_t count_ready;
volatile uint32_t count_output;
volatile uint32_t count_prev;

void tmr_callback() 
{
  uint32_t count = counter_read();
  count_output = count - count_prev;
  count_prev = count;
  count_ready = 1;
}

IntervalTimer it1;

void setup() 
{
  Serial.begin(9600);
  while (!Serial);
  
  analogWriteFrequency(11, 10'000'000);  // test jumper 11 to 25
  analogWrite(11, 128);

  Serial.print("CPU clock: ");
  Serial.print(F_CPU_ACTUAL / 1E6);
  Serial.println(" MHz");

  Serial.print("BUS clock: ");
  Serial.print(F_BUS_ACTUAL / 1E6);
  Serial.println(" MHz");

  counter_init();
  it1.begin(tmr_callback, 1'000'000);  // us
  counter_start();
}

void loop() 
{
  if (count_ready) 
  {
    Serial.print(count_output);
    Serial.print("  ");
    Serial.print(count_output / 1E6);
    Serial.println(" MHz");
    count_ready = 0;
  }
}

analogWriteFrequency(11, 10'000'000); // test jumper 11 to 25
Code:
CPU clock: 600.00 MHz
BUS clock: 150.00 MHz
9999129  10.00 MHz
10000000  10.00 MHz
10000000  10.00 MHz
10000000  10.00 MHz
10000000  10.00 MHz
10000000  10.00 MHz

analogWriteFrequency(11, 12'000'000); // test jumper 11 to 25
Code:
CPU clock: 600.00 MHz
BUS clock: 150.00 MHz
11075439  11.08 MHz
11076923  11.08 MHz
11076923  11.08 MHz
11076923  11.08 MHz
11076923  11.08 MHz

analogWriteFrequency(11, 15'000'000); // test jumper 11 to 25
Code:
CPU clock: 600.00 MHz
BUS clock: 150.00 MHz
8997685  9.00 MHz
9000000  9.00 MHz
9000000  9.00 MHz
9000000  9.00 MHz
 
Last edited:
Increasing the oscillator >10 MHz leads to incorrect counting results.

Maybe GPT1 is running from the 24 MHz clock? Look for the PRECLK_CLK_SEL bit in CCM_CSCMR1, which is documented on page 1059 in the reference manual.

Best to change that bit when none of the GPT or PIT (IntervalTimer) timers are active.
 
Thanks for the reply. I added this block of code. Things get funnier @10MHz.

Code:
  Serial.println(CCM_CSCMR1,BIN);
  CCM_CSCMR1 &= ~CCM_CSCMR1_PERCLK_CLK_SEL;
  Serial.println(CCM_CSCMR1,BIN);

Code:
CPU clock: 600.00 MHz
BUS clock: 150.00 MHz
1100110000100110000000001000000
1100110000100110000000000000000
1600001  1.60 MHz
1600000  1.60 MHz
1600000  1.60 MHz
 
PRECLK_CLK_SEL also changes the time base for IntervalTimer. You should be able to see the lines are now printing much faster than once per second. Of course you're seeing a smaller number if you count clock edges over less time.
 
Also keep in mind analogWrite can only generate frequencies which are an integer division of the peripheral clock. As you use it to generate higher frequencies, remember it will round to the nearest frequency the PWM hardware can actually generate.
 
Mission accomplished. With a higher setting, I get the correct display from an 80 MHz quartz. But I would have preferred that the clock could only be set explicitly for the specific timer and that other peripherals would not be affected. Presumably other libraries etc. are no longer running correctly.

it1.begin(tmr_callback, 9'501'187); // us

CPU clock: 912.00 MHz
BUS clock: 228.00 MHz
80009650 80.01 MHz
80009646 80.01 MHz
80009648 80.01 MHz
 
But I would have preferred that the clock could only be set explicitly for the specific timer and that other peripherals would not be affected.

Oh how nice that would be indeed.

Sadly, we have to just work with the way NXP wired the clock circuitry inside the chip.
 
Yes, the speed drives you crazy. Fortunately, the USB interface is not affected by the high bus clock rate. The question arises as to what can still be used without adjustments. Mainly because the Arduino IDE does a lot behind the scenes.
 
Back
Top