Is the processor really running on 84MHz?

How can the Cortex-M3 on the Due run on 84MHz when there's a 12MHz oscillator connected to the MCU?

I've been trying to figure this out for some hours now. :)

84 / 12 is 7. Therefore, if you could generate 7 pulses every time the 12MHz clock ticks then you'd end up with 84 million ticks per second. As luck would have it, there's a way to make this happen: a phase locked loop (PLL). Google it.

Thank you very much! <3

I thought the MAINCK signal is used in the Master Clock Controller. So this would mean that the PLL is configured in the bootloader, right?

And another thing... do you know by chance if I can use the Slow Clock as a PCK[...] output at the same time as the PLLA Clock as the processor clock? Or is it only Main Clock OR Slow Clock?

Hello hirschmensch,

As per datasheet, PCK0, PCK1 and PCK2 output pins can be found chap. 9.3.1 and 9.3.2, although all pins are not broken out, therefore only PCK output frequencies will be available for: PCK0 Pin PA1/Peripheral B PCK1 Pin PA24/Peripheral B

To select a clock for PCK output, see datasheet page 533, chap. 5:

For example, PCK0 selection should sometihing like :

 // For PCK0 output frequency on pin PA1

void setup() {

  PMC->PMC_SCER |= PMC_SCER_PCK0;               // Enable PCK0 clock output

  PIOA-> PIO_ABSR |= PIO_ABSR_P1;                    // PA1 Peripheral B

  PIOA->PIO_PDR |=   PIO_PDR_P1;                     // Disable PIO from controlling PA1

  PMC->PMC_PCK[0] |= PMC_PCK_CSS_SLOW_CLK            // select slow clock  frequency = 32.768 Khz
                                 | PMC_PCK_PRES_CLK_2;             // Divide by 2 slow clock frequency
  
  PMC-> PMC_PCER0 |= PMC_PCER0_PID11 ;               // PIOA  power on


  while (!(PMC->PMC_SR  &&  PMC_SR_PCKRDY0));        // Wait for PCK0 output frequency ready

}


void loop() {

}

I tried to measure the main clock speed. The MCU actually even has a frequency counter and a register to read the main clock frequency! Neat! :) You can look it up in the datasheet at page 531 on the bottom!

Well, I read the register and it gives you the value of how many main clock cycles are counted within 16 slow clock cycles. Sounds not too practical but I guess there's a reason for that.

Slow clock frequency is 32768Hz and the register read 6789. 6789 / 16 = 424,3125 main clock cycles in one slow clock cycle. 424,3125 * 32768 = 13,9MHz

I have a 12MHz crystal connected, obviously. So why is this deviation? Anyone any idea?

Alternatively, please just try running this little script and tell me what it says...

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println(REG_CKGR_MCFR); //Prints the measured main clock cycles in 16 slow clock cycles
  delay(1000);
}

At 84MHz, 2563 main clocks in 1 slow clock, 41016 in 16. 6789 does come to 13.9MHz tho. Now, I think the problem is page 548 of the datasheet, MAINFRDY isn't set (this would add 65536 to the result, you number doesn't reach that so it can't be set), so the result isn't valid.

Oh no, MAINFRDY is set, i have just subtracted this bit from the result. 6789 is the decimal value without the MAINFRDY bit.

This is the my output and how I get the result:

31                                    0
---- ---- ---- ---- ---- ---- ---- ----
                  1 0001 1010 1000 1110
              |---X|XXXX XXXX XXXX XXXX|
             MAINFRDY      MAINF
                          6.798 DEC

weird_dave: At 84MHz, 2563 main clocks in 1 slow clock, 41016 in 16.

See... I don't really believe that your output is 41016. Because the frequency counter counts the Main Clock and not the Master Clock signal. On an Arduino Due board, the Main Clock should be 12MHz because a 12MHz crystal is installed on the board. Or am I completely wrong here?

I didn't actually mean I had a result of 41016, I was suggesting that's what I thought it should be. I wasn't able to run any code at the time, but I shall do so now. I get 72303 - 65536 = 6767. I added the serial print line to some code which does some SPI transfers at 42MHZ and the result dropped to 6750. I think you're right, the result should be 12MHz, judging by the diagram on page 527. It isn't obvious to me which of the clocks are actually in use, I don't trust my ability to read the registers (I'm reading 0 from PMC_MCKR)

I get 72187: 13.65MHz, supposedly.

Hmm. I don't see any code to switch the slow clock to the crystal instead of the internal RC. Even though the crystal is supposed to exist...

The way I read the datasheet, the frequency counter is only activated ONCE, when the main clock is changed. So re-reading the register is pointless - it doesn't update continuously.

Switching the slow clock to the crystal didn't do much (assuming I did it correctly. Which is uncertain.)

I generally see different values each time I reset my Due...

westfw: I get 72187: 13.65MHz, supposedly.

I find this really weird... I found a function called SystemCoreClockUpdate() which reads the current Core Clock and updates all peripherals to this frequency so for instance to have a working serial communication after changing the main clock.

I haven't tried it yet, but if this function exists, there has to be a way to measure the current clock accurately!?

Furthermore, I checked all registered related to the configuration of the core clock and all that happens is this... the main clock input (crystal oscillator) is multiplied by 14 in the PLL, then the PLL clock signal is selected as the core clock and devided by two. If you calculate this backwards (84MHz * 2 / 14 = 12MHz) it seems that a 12MHz crystal oscillator is predicted to receive 84MHz in the end.

I found the function SystemCoreClockUpdate() in system_ARMCM3.c:

void SystemCoreClockUpdate (void)            /* Get Core Clock Frequency      */
{
  SystemCoreClock = __SYSTEM_CLOCK;
}

Also, __SYSTEM_CLOCK is defined here:

#define __SYSTEM_CLOCK    (4*__XTAL)

So it's 4 times __XTAL, which is here:

#define __XTAL            (12000000UL)    /* Oscillator frequency             */

Now... can someone tell me, is (12000000UL) an absolute adress or an offset? of what? and is this an integer or a hex-number?

hirschmensch: Now... can someone tell me, is (12000000UL) an absolute adress or an offset? of what? and is this an integer or a hex-number?

Sorry I'm stupid... this is obviously the crystal frequency hard coded as an integer... :/

There it is… the “real” SystemCoreClockUpdate()

void SystemCoreClockUpdate(void)
{
	/* Determine clock frequency according to clock register values */
	switch (PMC->PMC_MCKR & PMC_MCKR_CSS_Msk) {
	case PMC_MCKR_CSS_SLOW_CLK:	/* Slow clock */
		if (SUPC->SUPC_SR & SUPC_SR_OSCSEL) {
			SystemCoreClock = CHIP_FREQ_XTAL_32K;
		} else {
			SystemCoreClock = CHIP_FREQ_SLCK_RC;
		}
		break;
	case PMC_MCKR_CSS_MAIN_CLK:	/* Main clock */
		if (PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) {
			SystemCoreClock = CHIP_FREQ_XTAL_12M;
		} else {
			SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;

			switch (PMC->CKGR_MOR & CKGR_MOR_MOSCRCF_Msk) {
			case CKGR_MOR_MOSCRCF_4_MHz:
				break;
			case CKGR_MOR_MOSCRCF_8_MHz:
				SystemCoreClock *= 2U;
				break;
			case CKGR_MOR_MOSCRCF_12_MHz:
				SystemCoreClock *= 3U;
				break;
			default:
				break;
			}
		}
		break;
	case PMC_MCKR_CSS_PLLA_CLK:	/* PLLA clock */
	case PMC_MCKR_CSS_UPLL_CLK:	/* UPLL clock */
		if (PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) {
			SystemCoreClock = CHIP_FREQ_XTAL_12M;
		} else {
			SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;

			switch (PMC->CKGR_MOR & CKGR_MOR_MOSCRCF_Msk) {
			case CKGR_MOR_MOSCRCF_4_MHz:
				break;
			case CKGR_MOR_MOSCRCF_8_MHz:
				SystemCoreClock *= 2U;
				break;
			case CKGR_MOR_MOSCRCF_12_MHz:
				SystemCoreClock *= 3U;
				break;
			default:
				break;
			}
		}
		if ((PMC->PMC_MCKR & PMC_MCKR_CSS_Msk) == PMC_MCKR_CSS_PLLA_CLK) {
			SystemCoreClock *= ((((PMC->CKGR_PLLAR) & CKGR_PLLAR_MULA_Msk) >>
				                          CKGR_PLLAR_MULA_Pos) + 1U);
			SystemCoreClock /= ((((PMC->CKGR_PLLAR) & CKGR_PLLAR_DIVA_Msk) >>
				                           CKGR_PLLAR_DIVA_Pos));
		} else {
			SystemCoreClock = SYS_UTMIPLL / 2U;
		}
		break;
	}

	if ((PMC->PMC_MCKR & PMC_MCKR_PRES_Msk) == PMC_MCKR_PRES_CLK_3) {
		SystemCoreClock /= 3U;
	} else {
		SystemCoreClock >>= ((PMC->PMC_MCKR & PMC_MCKR_PRES_Msk) >> PMC_MCKR_PRES_Pos);
	}
}

I don't think that SystemCoreClockUpdate is called from anywhere...

System_calls it. And you can call it manually to "update the processor core frequency".