Daniel White

PLL problems, detection and recovery

Discussion created by Daniel White on Aug 9, 2006
Latest reply on Aug 10, 2006 by Alban Rampon
Xtal: 16MHz with PLL set for 40MHz
Compiler: Codewarrior v4.5
We have found that the pll is very sensitive to slight changes in capacitance. Touching the XTAL cap with a scope probe causes the PLL to lose its lock. So, I am implementing some detection and recovery logic. I have enabled the loss of lock interrupt and self clock mode change interrupt. In the lock ISR I just run through the PLL init code again and this seems to work. In the SCM ISR, I thought I should wait in a loop until CRGFLG SCM bit is cleared and flash LEDs to indicate a severe clock problem. When I ground the XTAL, it does seem to run from the self clock because one of my LEDs runs about 1/25th of the normal frequency but the SCM ISR never seems to run.
This is a real-time control system so this clock sensitivity must be handled properly. When I get these ISRs running and can understand what is going on, I will implement some fail-safing in these interrupts.
Bottom line, I really need to make sure that the PLL is robust as possible and recovers when it can and fails safe when it can't. If anyone can provided a recommended setup for this, please help.
My PLL code:
#define PLL_TIMEOUT 50000#define PLL_LOCK_STATUS (CRGFLG_LOCK)#define PLL_CLEAR_FLAGS (CRGFLG = CRGFLG_RTIF_MASK | CRGFLG_PORF_MASK | \CRGFLG_LVRF_MASK | CRGFLG_LOCKIF_MASK | CRGFLG_SCMIF_MASK )/* Initializes the system clock in the CRG module */void Init_pll(void){uWord counter=0;/* Set PLL to give 40MHz from 16MHz Xtal *///Init multSYNR = 4;//Init DivREFDV = 1;//Enable auto tracking mode, turn on pll, clock monitor, self clock modePLLCTL = PLLCTL_AUTO_MASK | PLLCTL_PLLON_MASK | PLLCTL_CME_MASK | PLLCTL_SCME_MASK;//Wait for PLL lockwhile((PLL_LOCK_STATUS == 0) &&(counter < PLL_TIMEOUT)){counter++;}//Clear interrupt flagsPLL_CLEAR_FLAGS;//Enable loss of lock interrupt & self clock mode change interruptCRGINT = CRGINT_LOCKIE_MASK | CRGINT_SCMIE_MASK;if(PLL_LOCK_STATUS){//Enable PLLCLKSEL |= CLKSEL_PLLSEL_MASK; } ECLKCTL_NECLK = FALSE; //turn on ECLK output} /* end Init_pll *//*************************************************************************************/#pragma CODE_SEG __NEAR_SEG NON_BANKED /* these functions have to be allocated in the non banked area */INTERRUPT void PLL_Lock_ISR(void){/* try to restart pll */Init_pll();_asm("bgnd");} /* end CPU12PLLLockISR */INTERRUPT void PLL_SCM_ISR(void){uWord i;/* wait here while in self clock mode */while(CRGFLG_SCM){_asm("bgnd");/* flash both red and green LED to indicate a severe problem */for(i = 0; i < 60000; i++);if(IS_PIN_HIGH( LED_PORT, RED_LED_PIN)){SET_PIN_LOW(LED_PORT, RED_LED_PIN);SET_PIN_LOW(LED_PORT, GREEN_LED_PIN);}else{SET_PIN_HIGH(LED_PORT, RED_LED_PIN);SET_PIN_LOW(LED_PORT, GREEN_LED_PIN);}} /* try to restart pll */Init_pll();} /* end CPU12PLLLockISR */#pragma CODE_SEG DEFAULT /* switch back to default segment */


Message Edited by Alban on 2006-08-10 08:16 AM