Hi @kaspencer
@ard_newbie has previously described how to change the main clock frequency here:
In order to change the Due's main clock from 84MHz to say 42MHz, it's necessary to modifiy Phase Locked Loop A's multipler value. This is achieved by setting the MULA bitfield in the PMC->CGKR_PLLAR register with the multiplier set to a value of MULA + 1. (See Power Management Controller (PMC) section 28 of the SAM3X/SAM3A datasheet).
By default the board's 12MHz external crystal is divided by 2 then multiplied up by 14 to achieve 84MHz. In this case the MULA bitfield is set to 13, (since the muliplier value is MULA + 1). This occurs during start-up with the board's "variant.cpp" file calling the SystemInit() function. The SystemInit() function is located in the "system_sam3x.c" file, located (on my machine at least) in the following directory:
C:\Users\Computer\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.12\system\CMSIS\Device\ATMEL\sam3xa\source
Therefore to generate a 42MHz main clock the MULA bifield needs to be be set to 6, since 12MHz/2 * (6 + 1) = 42MHz.
Here's some code that demonstrates setting the clock to 42MHz together with blink and analogWrite() test code to ensure that the microcontroller is working at half speed:
// Change Arduino Due's main clock from 84MHz to 42MHz
void setup()
{
//SerialUSB.begin(115200); // Initialise the native SerialUSB port
//while (!SerialUSB); // Wait for the console to open
PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | // Set CKGR_PLLAR write bit
CKGR_PLLAR_MULA(0x6UL) | // Set MULA to multiply 12MHz/2 = 6MHz clock by 7 = 42MHz
CKGR_PLLAR_PLLACOUNT(0x3fUL) | // Set the PLLA time to LOCK to maximum
CKGR_PLLAR_DIVA(0x1UL); // Bypass the divider
while (!(PMC->PMC_SR & PMC_SR_LOCKA)); // Wait for PLLA to lock
SystemCoreClockUpdate(); // Update the system core clocks
pinMode(LED_BUILTIN, OUTPUT); // Set the built-in LED pin to an OUTPUT
analogWrite(7, 128); // Output analog write - should output PWM at 500Hz rather than the default 1kHz
//SerialUSB.println(F("Serial port active")); // Output text to the console
}
void loop()
{
digitalWrite(LED_BUILTIN, HIGH); // Set the built-in LED output to HIGH
delay(1000); // Wait for 2 seconds (1000ms * 2)
digitalWrite(LED_BUILTIN, LOW); // Clear the built-in LED output to LOW
delay(1000); // Wait for 2 seconds (1000ms * 2)
}