Hello!
I’ve had good success using the SPI and CPU configuration code provided by Kjarvel (repository here); however, I noticed that in order for his SPI code to work, the CPU must be initialized to 320MHz. At other frequencies (e.g. 16MHz, 64MHz, 160MHz), it appears that the handshake pin is never set high when it comes time to read it, and the code stalls while waiting for it.
The reason I ask is since I’d like to keep the clock running a little less intensely (e.g. around 64MHz or lower) if I can, as the CPU runs pretty hot at 320MHz. I’ve gone into the cpu.c
file and modified the PLL configuration to bring the clock frequency to 64MHz, and made sure all references to the frequency in uart.c
and spi.c
were matched. Here’s the code I’m using to bring the frequency to 64MHz:
void cpu_clock_init(void)
{
uint32_t cfg_temp = 0;
/* There is a 16 MHz crystal oscillator HFXOSC on the board */
cfg_temp |= BITS(PLLREFSEL_I, 1); // Drive PLL from 16 MHz HFXOSC.
cfg_temp |= BITS(PLLR_I, 1U); // Divide ratio.
// R="1U" is treated as a divide ratio of 2.
// This gives 16MHz / 2 = 8MHz.
// This is within range for refr.
cfg_temp |= BITS(PLLF_I, 31U); // Multiply ratio.
// F="31U" gives a multiply ratio of 2 * ("31U" + 1) = 64.
// This gives 8MHz * 64 = 512MHz.
// This is within range for vco.
cfg_temp |= BITS(PLLQ_I, 3U); // Divide again.
// Q="3U" gives a division ratio of 8.
// This gives 512MHz / 8 = 64MHz.
// This is within range for pllout.
PLLCFG = cfg_temp;
delay(1000);
while ( PLLCFG & BITS(PLLLOCK_I, 1) == 0) {} // Wait until PLL locks
PLLCFG |= BITS(PLLSEL_I, 1); // Let PLL drive hfclk
}
I confirmed that I was getting 64MHz with a quick GPIO test. UART appears to work as intended with the CPU frequency at 64MHz, since output is legible. I also scoped GPIO pin 5 and confirmed that the SPI_SCK
signal was running at 80kHz as defined (and I was able to tweak this to 40kHz and 60kHz successfully as well, not that I care to change it unless it’s necessary).
However, in no configuration at lower speeds has the handshake pin cooperated as expected. As far as I can tell on the scope, the handshake pin is never up in time for a transaction, and only sometimes appears to come up for a few microseconds, but always goes low before the pin is checked.
Here’s a healthy SPI transaction (at 320MHz with 80kHz SCK – ignore the 50kHz on screen, it’s 80 when zoomed in), where the handshake pin is up until the command is sent over and only then goes low briefly before coming back up:
At 64MHz and 80kHz SCK, it looks like the handshake pin stays low until midway through the transaction, comes up briefly, and then goes low before the end of the transaction:
I’ve tried searching for the reason behind this, but I haven’t found any reasoning as to why the behavior of the handshake pin would change due to a change in CPU frequency. Interestingly, I’ve noticed that all implementations of SPI that I’ve found set the CPU frequency to 320MHz – I can’t tell if this is due to requirement or personal preference on the parts of the developers. Does anyone happen to know if there’s some piece of documentation around CPU frequency and the ability to properly communicate over SPI?
Thank you!