Looking for some help on a CM4/ATSAMG55: Crashes when PLL is used - Page 1
Forum section: electronics / general

author: XFDDesign
author_rank: Frequent Contributor
timestamp: May 11, 2017, 08:50:51 pm
content: The short problem statement: After some problem solving, I found that my micro is hanging/crashing shortly after the program begins any time I'm using the on-chip PLL as a master clock (which is set to 110MHz). I've gone through the motions to reduce the problem set down to the barest essentials, and am unable to determine what I'm doing wrong or missing to make the device happy to run at speed. I'm looking to see if anyone on here has used the SAM CortexM4 series from Atmel and might be able to lend some insight.-----------------------Long version:After fighting to get the USART setup with the G55 project I've built up, I found that data was being written in a very strange manner to a buffer. It appeared as though the device was handling byte sized buffers as if they were full words. I went through a long process, and found that so long as I set the master clock to be source from the main clock (external crystal at 12.288MHz) the device operated correctly without issueon the same code. My finding was that anytime I was running the device on the PLL, be it from 50MHz to 112MHz, the whole processor would crash and stop responding. Having dealt with the CortexM0 and M3 series devices, this told me that I likely failed to provide a clock resource to a peripheral, or failed to provide it a slow enough clock (relative to Master) that it would still run. After configuring the PMC thoroughly, ensuring that everything which needed a clock resource had one, and going over the datasheet a few times, I began purging large sections of code to try and isolate the source of the problem. I've now boiled my code down to the barest essentials to test the problem, and it appears to be something wrong outside of the peripherals. I found mention that the low-voltage regulator needs to be adjusted for high speed operation. I addressed that. There is nothing left that I can find or think of to cause this problem.In the below example code, set the Master clock to run on the external oscillator (PMC_MCKR=1), and the while loop shifts all the values up one, and increments the value of the last register. Essentially a glorified array of 10 counters. It works at 12.288MHz.Set PMC_MCKR=2 for PLL usage (and I can confirm the PLL is outputting ~110MHz), and the txBufpage1[] array gets sporadically filled with garbage data instead (if you can pause the debugger quickly enough), and after a moment the processor itself just stops responding/crashes.Code:#include "g55_device.h"PIO_Type*pPortA = PORTA;PIO_Type*pPortB = PORTB;FLEXCOM_Type *pFlex0 = FLEXCOM0;SUPC_Type*pSUPC = SUPC;PMC_Type*pPMC = PMC;int main(void){volatile uint32_tpointerValue;volatile uint8_ttxBufpage1;for(unsigned char index=0;index<10;index++)txBufpage1=0;pPMC->PMC_WPMR = (0x504D43 << 8); // disable write protection for the PMCpPMC->PMC_SCER = 0x500;// enable PCK2 and PCK0pPMC->PMC_PCER0 = 0x800;// enable PID11 (PIO A) clockpPMC->PMC_PCK2 = 0x2;// this is a routing of the master clock to an output pin.pPMC->PMC_PCK0 = 0x1;// general 'lower level' clock business.pPMC->CKGR_MCFR = 6110;// let the device know the main clock is about 12.288MHzpSUPC->SUPC_MR= 0xA5804F00; // set the voltage regulator to 'high performance' mode.while(0==(pPMC->PMC_SR & 0x10000)); // wait for oscillator to settle.pPMC->CKGR_MOR = 0x0337000A;pPMC->PMC_MCKR = 1; // use external osc// start experimenting with the PLL....pPMC->CKGR_PLLAR = (3356 <<16) | (0x3F << 8); // start with the thing disabled.pPMC->CKGR_PLLAR = (3356 <<16) | (0x3F << 8) | 1; // start with the thing now enable it.while(0==(pPMC->PMC_SR & 0x2)); // wait for PLL to lock...pPMC->PMC_MCKR = 2; // use PLL =2while(0==(pPMC->PMC_SR & 0x8));// wait for master clock to be ready.while(1){for(uint8_t index=0;index<9;index++)txBufpage1[9-index]=txBufpage1[8-index];txBufpage1++;}/* Replace with your application code */while (1){// okay ... let's try stuffing some data into the serial port.}}

author: ajb
author_rank: Super Contributor
timestamp: May 11, 2017, 10:20:43 pm
content: You'll need to set the number of flash wait states to the correct value before increasing the core clock frequency. Page 1080 of the datasheet, Section 39.9.8 "Embedded Flash Characteristics".

author: XFDDesign
author_rank: Frequent Contributor
timestamp: May 12, 2017, 01:55:36 am
content: Quote from: ajb on May 11, 2017, 10:20:43 pmThis makes sense, but just to validate, this is specifically due to the fact that the program is being read from flash memory, right? I'm asking the CPU to fetch amazeballs fast, and the flash just cannot keep up, therefore it IS still a peripheral problem, just that it's the flash itself. Is that right?

author: ajb
author_rank: Super Contributor
timestamp: May 12, 2017, 02:56:34 am
content: Basically, yes. After the processor requests data from a location in flash it takes a certain amount of time for the flash controller to present that data correctly. If the processor grabs the data presented by the flash controller before that data is valid then it's going to read some sort of junk. If you're lucky this will result in the processor recognizing an invalid instruction or invalid pointer and immediately hardfaulting. If you're not lucky (running at a marginal clock rate) the processor will chug along, but you'll get invalid data stored to some variable somewhere that will cause who knows what sort of havoc later on. Setting the number of wait states properly will ensure that the flash controller will always have enough time to reliably present the correct data before the processor reads it.

author: XFDDesign
author_rank: Frequent Contributor
timestamp: May 12, 2017, 02:28:46 pm
content: Yup, that took care of it. Many thanks!