trouble with PLL on the HC12

Started by Chris September 14, 2011
Hello; I am using an ICC12 compiler and NOICE debugger with a USB pod with an HC12 128kB chip running with a 16MHz crystal.

My problem is that when I try to set the PLL up for about 40MHz, the code does not seem to work in the way it should and I can't get a LOCK - or even a TRACK signal.

I have to turn off the PLLSEL bit before trying to set up the mult and divide registers and turning the PLL on, then looking for a LOCK signal; but the manual says that a write to PLLSEL is not possible if the LOCK and TRACK bits are zero.

Does that mean a write 1, or any write? To turn PLLSEL off I need to clear that bit whether I am locked / tracked or not.

In addition, even if I assume I can write a zero to PLLSEL, and even if I have wait loops after setting the mult and divide registers, and then wait in a loop for the LOCK or TRACK to go high, they never do.

I have about 10nF main loop filter with 4.7k in series, and a 1nF bypass loop filter cap. Also my 16MHz oscillator is running nicely. Any tips?

> Hello; I am using an ICC12 compiler and NOICE debugger with a USB pod with
> an HC12 128kB chip running with a 16MHz crystal.
>
> My problem is that when I try to set the PLL up for about 40MHz, the code
> does not seem to work in the way it should and I can't get a LOCK - or
> even a TRACK signal.

No HC12 chip I know can run that fast. Are you talking about S12? Which one?
It must be either bad filter parts, bad connection or something wrong to
VDDPLL. Did you measure VDDPLL voltage?

>
> I have to turn off the PLLSEL bit before trying to set up the mult and
> divide registers and turning the PLL on, then looking for a LOCK signal;
> but the manual says that a write to PLLSEL is not possible if the LOCK and
> TRACK bits are zero.

By default PLLSEL is 0, you don't need to clear it. Writing one to PLLSEL is
ignored while PLL is not yet locked. You can clear this bit at any time.

>
> Does that mean a write 1, or any write? To turn PLLSEL off I need to clear
> that bit whether I am locked / tracked or not.
>
> In addition, even if I assume I can write a zero to PLLSEL, and even if I
> have wait loops after setting the mult and divide registers, and then wait
> in a loop for the LOCK or TRACK to go high, they never do.
>
> I have about 10nF main loop filter with 4.7k in series, and a 1nF bypass
> loop filter cap. Also my 16MHz oscillator is running nicely. Any tips?

Values are fine. It should work. Check if XFC pin is really connected. You
may probe it with scope. You should see DC between VDDPLL and VSSPLL. Also
what are SYNR and REFDV settings? Didn't you set them for 80MHz PLL / 40MHz
bus clock? This would be too much for S12. REFDV should be 3, SYNR - 4.for
40MHz PLL clock.

Edward
>
>
Thanks for your reply Edward. You did hit upon more of the possible things in the hardware but here they were all OK; and it is an HC9S12DG128 chip with mask 1L59W.

Good to know that you can zero the bit at any time; the manual states only that 'writes' are disabled, which I guess means that the manual is incorrect.

I got my system to work with the CLKSEL register already at all-zeroes when entering the routine, but even so I wrote zero to the PLLWAI and the PLLSEL bits; and then it worked!

I have no idea why unless it is a mask bug (Freescale's bug list as of 2011 is at http://www.freescale.com/files/microcontrollers/doc/errata/MSE9S12DT128_1L59W.htm) which I have not heard of.

--- In 6..., "Edward Karpicz" wrote:
> > Hello; I am using an ICC12 compiler and NOICE debugger with a USB pod with
> > an HC12 128kB chip running with a 16MHz crystal.
> >
> > My problem is that when I try to set the PLL up for about 40MHz, the code
> > does not seem to work in the way it should and I can't get a LOCK - or
> > even a TRACK signal.
>
> No HC12 chip I know can run that fast. Are you talking about S12? Which one?
> It must be either bad filter parts, bad connection or something wrong to
> VDDPLL. Did you measure VDDPLL voltage?
>
> >
> > I have to turn off the PLLSEL bit before trying to set up the mult and
> > divide registers and turning the PLL on, then looking for a LOCK signal;
> > but the manual says that a write to PLLSEL is not possible if the LOCK and
> > TRACK bits are zero.
>
> By default PLLSEL is 0, you don't need to clear it. Writing one to PLLSEL is
> ignored while PLL is not yet locked. You can clear this bit at any time.
>
> >
> > Does that mean a write 1, or any write? To turn PLLSEL off I need to clear
> > that bit whether I am locked / tracked or not.
> >
> > In addition, even if I assume I can write a zero to PLLSEL, and even if I
> > have wait loops after setting the mult and divide registers, and then wait
> > in a loop for the LOCK or TRACK to go high, they never do.
> >
> > I have about 10nF main loop filter with 4.7k in series, and a 1nF bypass
> > loop filter cap. Also my 16MHz oscillator is running nicely. Any tips?
>
> Values are fine. It should work. Check if XFC pin is really connected. You
> may probe it with scope. You should see DC between VDDPLL and VSSPLL. Also
> what are SYNR and REFDV settings? Didn't you set them for 80MHz PLL / 40MHz
> bus clock? This would be too much for S12. REFDV should be 3, SYNR - 4.for
> 40MHz PLL clock.
>
> Edward
> >
> >
> >
> >
> >
> >
Hello; Now I think my problem with PLL-setting is clarified and while I have a workaround, why it works escapes me.

In the below code are two delay loops to assure that the Lock and Track bits have time to change and settle, assuring a good lock before making the PLL the system clock source. After telling the PLL to turn on, if I use only the second delay loop it is not enough; but including the first delay loop, it only needs one pass through the loop to assure we have lock after going through the second delay loop. The second loop extends its delay if lock and track are not on, so its delay on its own should all that is needed. What am I missing here? Any help would be appreciated.

Please excuse the lengthy code below; its debug outputs show the clock system status at each point.

void Set_PLL_Clock(uint8_t SYNR_val, uint8_t REFDV_val)
{
uint8_t StatusPLLFlags8; // local variable used for debug readout of Clock status registers
// uint8_t StatusPLLSetup8; // in globals.h
StatusPLLFlags8 = CRGFLG; // CRGFLG is either 5C/1C hex when above statement was executed
// so PwrOnResetFlg is on/off; LOCKhangeInterruptFlag;LOCK and TRACK are set; SCM off so the Xtal is being used.
StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so the PLL is not the clock source.
// make sure PLL is not in use OTHERWISE CAN'T WRITE TO SYNR, OR REFDV, OR PLLON in PLLCTL
ClrBit(CLKSEL, PLLWAI); // if 0, PLL runs during Wait mode; and allows write to AUTO bit
StatusPLLFlags8 = CLKSEL; // for debug
ClrBit(CLKSEL, PLLSEL); // If PLLSEL is set to 0, clock is derived from the OSCCLK
StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so PLL is not the clock source.
StatusPLLFlags8 = CRGFLG; // CRGFLG is 5C/1C hex when above statement was executed so PwrOnResetFlg is on/off,and; LOCKhangeInterruptFlag and LOCK and TRACK are set; SCM is not on so the Xtal is being used.
CRGFLG = 0xFF; // clear all of the flags by writing a 1 to them
StatusPLLFlags8 = CRGFLG; // CRGFLG is 0C hex so TRI PWRON TRACK interrupt flags off; LOCK, TRACK are still set, SCM off
// PLLCLK = 2 * OSCCLK * [(SYNR + 1)/(REFDIV + 1)]
// eg, PLLCLK = 2 * 16MHz * 20 / 16 for PLLCLK = 40MHz
SYNR = SYNR_val; // 17 for 44.3077MHz PLL; initialises LOCK and TRACK flags
REFDV = REFDV_val; // 12 for 44.3077MHz PLL
// #### below PLLCTL = 0b01110000 line moved here from lower down since must turn on the PLL and wait a bit
// before can go into the "LOCK" condition!! AND ... Delay needed for the PLL since
// just after turnon, it maybe thinks that it has a lock while it really does not.
// With the below line here, and with only one test needed of conditions before exit of Loop#1,
// ended up with a good lock at ~22MHz Eclock. Also with below line placed between Loop#1 and Loop#2,
// AND with a breakpoint after the line to cause a delay, got a 22MHz Eclock. HOWEVER, without a breakpoint
// delay, Loop#2 would execute rapidly and exit with the PLL NOT locked and an 8MHz Eclock. Why was the
// Loop#2 delay insufficient to assure good lock, while only one pass through Loop#1, ie, a minimal delay, worked fine?
// Note Loop#2 looks for Track or Lock to be set; Freescale app note informed that Lock bit unreliable for rapid locking w/out overshoot.
PLLCTL = 0b01110000; // PLLCTL: CME=0,PLLON=1,AUTO=1,ACQ=1,xx=0,PRE=0,PCE=0,SCME=0
// LOOP#1; put in a delay; see erratum MUCTS00174 (mask set 0K36N only; typ mask here is 1L59W)
// which kept LOCK signal high after setting above registers, for about 10 cycles.
StatusPLLSetup8 = 0; // initialise the counter for good lock/track reads
do
{
StatusPLLFlags8 = SYNR; // SYNR is 11 hex ie 17
StatusPLLFlags8 = REFDV; // REFDV is 0C hex ie 12
StatusPLLFlags8 = CLKSEL;// CLKSEL is 00 hex so PLL not on;
StatusPLLFlags8 = CRGFLG;// CRGFLG is 1C so LOCK, TRACK are set and LOCK interrupt flag LOCKIF is on
if ((StatusPLLFlags8 & BIT3) == 0) // if LOCK is zero
{
StatusPLLSetup8 = 0x4F; // can now exit this loop; typ. happens at first loop!
}
StatusPLLFlags8 = PLLCTL; // PLLCTL is F1 so ClockMonitorEnable, PLLON, AUTO, ACQ, SelfClockModeEnable on
StatusPLLSetup8 = StatusPLLSetup8 + 1;
CRGFLG = 0; // writes have no effect on this flag register
}
while (StatusPLLSetup8 < 0x50); // delay 16 times times 5; need a really long delay for good LOCK AND TRACK? see exit above; no, we don't.
StatusPLLFlags8 = CRGFLG; // CRGFLG is 5C hex so PwrOnResetFlg, LOCKchangeInterruptFlag, LOCK, TRACK set; SCM off so the Xtal is being used.
// LOOP#2; here is where could have put the PLLON command; but it did not work here; see above.
StatusPLLSetup8 = 0x51; //
do
{
StatusPLLSetup8 = StatusPLLSetup8 + 1;
StatusPLLFlags8 = SYNR; // SYNR is 11 hex
StatusPLLFlags8 = REFDV; // REFDV is 0C hex
StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so PLL is not the clock source.
StatusPLLFlags8 = PLLCTL; // PLLCTL is 70 so SCME is off and top byte is 0x0111 so just as programmed above
StatusPLLFlags8 = CRGFLG;// CRGFLG is 1C so LOCK, TRACK are set and LOCK interrupt flag LOCKIF is on
// require both lock and track to be zero for no-lock condition
if ( ((CRGFLG & TRACK) == 0) && ((CRGFLG & LOCK) == 0) ) StatusPLLSetup8 = 0x51;
}
while (StatusPLLSetup8 < 0x60);// must read "locked" at least 16 consecutive times
SetBit(CLKSEL, PLLSEL);// select PLL clocking when are tracking or locked.
StatusPLLFlags8 = CLKSEL; // CLKSEL is 80 hex so PLL is on; and all of the wait and stop bits off.
StatusPLLFlags8 = PLLCTL; // PLLCTL is 70 so CME is off but PLLON, AUTO, ACQ are on
StatusPLLFlags8 = CRGFLG;
} //end of Set_PLL_Clock

You might want to read a engineering bulletin I did about 7 years ago, EB640, I think that will explain to you what is going on.

Regards,
Darci

--- In 6..., "Chris" wrote:
>
> Hello; Now I think my problem with PLL-setting is clarified and while I have a workaround, why it works escapes me.
>
> In the below code are two delay loops to assure that the Lock and Track bits have time to change and settle, assuring a good lock before making the PLL the system clock source. After telling the PLL to turn on, if I use only the second delay loop it is not enough; but including the first delay loop, it only needs one pass through the loop to assure we have lock after going through the second delay loop. The second loop extends its delay if lock and track are not on, so its delay on its own should all that is needed. What am I missing here? Any help would be appreciated.
>
> Please excuse the lengthy code below; its debug outputs show the clock system status at each point.
>
> void Set_PLL_Clock(uint8_t SYNR_val, uint8_t REFDV_val)
> {
> uint8_t StatusPLLFlags8; // local variable used for debug readout of Clock status registers
> // uint8_t StatusPLLSetup8; // in globals.h
> StatusPLLFlags8 = CRGFLG; // CRGFLG is either 5C/1C hex when above statement was executed
> // so PwrOnResetFlg is on/off; LOCKhangeInterruptFlag;LOCK and TRACK are set; SCM off so the Xtal is being used.
> StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so the PLL is not the clock source.
> // make sure PLL is not in use OTHERWISE CAN'T WRITE TO SYNR, OR REFDV, OR PLLON in PLLCTL
> ClrBit(CLKSEL, PLLWAI); // if 0, PLL runs during Wait mode; and allows write to AUTO bit
> StatusPLLFlags8 = CLKSEL; // for debug
> ClrBit(CLKSEL, PLLSEL); // If PLLSEL is set to 0, clock is derived from the OSCCLK
> StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so PLL is not the clock source.
> StatusPLLFlags8 = CRGFLG; // CRGFLG is 5C/1C hex when above statement was executed so PwrOnResetFlg is on/off,and; LOCKhangeInterruptFlag and LOCK and TRACK are set; SCM is not on so the Xtal is being used.
> CRGFLG = 0xFF; // clear all of the flags by writing a 1 to them
> StatusPLLFlags8 = CRGFLG; // CRGFLG is 0C hex so TRI PWRON TRACK interrupt flags off; LOCK, TRACK are still set, SCM off
> // PLLCLK = 2 * OSCCLK * [(SYNR + 1)/(REFDIV + 1)]
> // eg, PLLCLK = 2 * 16MHz * 20 / 16 for PLLCLK = 40MHz
> SYNR = SYNR_val; // 17 for 44.3077MHz PLL; initialises LOCK and TRACK flags
> REFDV = REFDV_val; // 12 for 44.3077MHz PLL
> // #### below PLLCTL = 0b01110000 line moved here from lower down since must turn on the PLL and wait a bit
> // before can go into the "LOCK" condition!! AND ... Delay needed for the PLL since
> // just after turnon, it maybe thinks that it has a lock while it really does not.
> // With the below line here, and with only one test needed of conditions before exit of Loop#1,
> // ended up with a good lock at ~22MHz Eclock. Also with below line placed between Loop#1 and Loop#2,
> // AND with a breakpoint after the line to cause a delay, got a 22MHz Eclock. HOWEVER, without a breakpoint
> // delay, Loop#2 would execute rapidly and exit with the PLL NOT locked and an 8MHz Eclock. Why was the
> // Loop#2 delay insufficient to assure good lock, while only one pass through Loop#1, ie, a minimal delay, worked fine?
> // Note Loop#2 looks for Track or Lock to be set; Freescale app note informed that Lock bit unreliable for rapid locking w/out overshoot.
> PLLCTL = 0b01110000; // PLLCTL: CME=0,PLLON=1,AUTO=1,ACQ=1,xx=0,PRE=0,PCE=0,SCME=0
> // LOOP#1; put in a delay; see erratum MUCTS00174 (mask set 0K36N only; typ mask here is 1L59W)
> // which kept LOCK signal high after setting above registers, for about 10 cycles.
> StatusPLLSetup8 = 0; // initialise the counter for good lock/track reads
> do
> {
> StatusPLLFlags8 = SYNR; // SYNR is 11 hex ie 17
> StatusPLLFlags8 = REFDV; // REFDV is 0C hex ie 12
> StatusPLLFlags8 = CLKSEL;// CLKSEL is 00 hex so PLL not on;
> StatusPLLFlags8 = CRGFLG;// CRGFLG is 1C so LOCK, TRACK are set and LOCK interrupt flag LOCKIF is on
> if ((StatusPLLFlags8 & BIT3) == 0) // if LOCK is zero
> {
> StatusPLLSetup8 = 0x4F; // can now exit this loop; typ. happens at first loop!
> }
> StatusPLLFlags8 = PLLCTL; // PLLCTL is F1 so ClockMonitorEnable, PLLON, AUTO, ACQ, SelfClockModeEnable on
> StatusPLLSetup8 = StatusPLLSetup8 + 1;
> CRGFLG = 0; // writes have no effect on this flag register
> }
> while (StatusPLLSetup8 < 0x50); // delay 16 times times 5; need a really long delay for good LOCK AND TRACK? see exit above; no, we don't.
> StatusPLLFlags8 = CRGFLG; // CRGFLG is 5C hex so PwrOnResetFlg, LOCKchangeInterruptFlag, LOCK, TRACK set; SCM off so the Xtal is being used.
> // LOOP#2; here is where could have put the PLLON command; but it did not work here; see above.
> StatusPLLSetup8 = 0x51; //
> do
> {
> StatusPLLSetup8 = StatusPLLSetup8 + 1;
> StatusPLLFlags8 = SYNR; // SYNR is 11 hex
> StatusPLLFlags8 = REFDV; // REFDV is 0C hex
> StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so PLL is not the clock source.
> StatusPLLFlags8 = PLLCTL; // PLLCTL is 70 so SCME is off and top byte is 0x0111 so just as programmed above
> StatusPLLFlags8 = CRGFLG;// CRGFLG is 1C so LOCK, TRACK are set and LOCK interrupt flag LOCKIF is on
> // require both lock and track to be zero for no-lock condition
> if ( ((CRGFLG & TRACK) == 0) && ((CRGFLG & LOCK) == 0) ) StatusPLLSetup8 = 0x51;
> }
> while (StatusPLLSetup8 < 0x60);// must read "locked" at least 16 consecutive times
> SetBit(CLKSEL, PLLSEL);// select PLL clocking when are tracking or locked.
> StatusPLLFlags8 = CLKSEL; // CLKSEL is 80 hex so PLL is on; and all of the wait and stop bits off.
> StatusPLLFlags8 = PLLCTL; // PLLCTL is 70 so CME is off but PLLON, AUTO, ACQ are on
> StatusPLLFlags8 = CRGFLG;
> } //end of Set_PLL_Clock
>

sorry I forgot to give a link for those who hate our search engine..

http://cache.freescale.com/files/microcontrollers/doc/eng_bulletin/EB640.pdf?fpsp=1&WT_TYPE=Engineering Bulletins&WT_VENDOR=FREESCALE&WT_FILE_FORMAT=pdf&WT_ASSET=Documentation

--- In 6..., "dleatmot" wrote:
> You might want to read a engineering bulletin I did about 7 years ago, EB640, I think that will explain to you what is going on.
>
> Regards,
> Darci
>
> --- In 6..., "Chris" wrote:
> >
> > Hello; Now I think my problem with PLL-setting is clarified and while I have a workaround, why it works escapes me.
> >
> > In the below code are two delay loops to assure that the Lock and Track bits have time to change and settle, assuring a good lock before making the PLL the system clock source. After telling the PLL to turn on, if I use only the second delay loop it is not enough; but including the first delay loop, it only needs one pass through the loop to assure we have lock after going through the second delay loop. The second loop extends its delay if lock and track are not on, so its delay on its own should all that is needed. What am I missing here? Any help would be appreciated.
> >
> > Please excuse the lengthy code below; its debug outputs show the clock system status at each point.
> >
> > void Set_PLL_Clock(uint8_t SYNR_val, uint8_t REFDV_val)
> > {
> > uint8_t StatusPLLFlags8; // local variable used for debug readout of Clock status registers
> > // uint8_t StatusPLLSetup8; // in globals.h
> > StatusPLLFlags8 = CRGFLG; // CRGFLG is either 5C/1C hex when above statement was executed
> > // so PwrOnResetFlg is on/off; LOCKhangeInterruptFlag;LOCK and TRACK are set; SCM off so the Xtal is being used.
> > StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so the PLL is not the clock source.
> > // make sure PLL is not in use OTHERWISE CAN'T WRITE TO SYNR, OR REFDV, OR PLLON in PLLCTL
> > ClrBit(CLKSEL, PLLWAI); // if 0, PLL runs during Wait mode; and allows write to AUTO bit
> > StatusPLLFlags8 = CLKSEL; // for debug
> > ClrBit(CLKSEL, PLLSEL); // If PLLSEL is set to 0, clock is derived from the OSCCLK
> > StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so PLL is not the clock source.
> > StatusPLLFlags8 = CRGFLG; // CRGFLG is 5C/1C hex when above statement was executed so PwrOnResetFlg is on/off,and; LOCKhangeInterruptFlag and LOCK and TRACK are set; SCM is not on so the Xtal is being used.
> > CRGFLG = 0xFF; // clear all of the flags by writing a 1 to them
> > StatusPLLFlags8 = CRGFLG; // CRGFLG is 0C hex so TRI PWRON TRACK interrupt flags off; LOCK, TRACK are still set, SCM off
> > // PLLCLK = 2 * OSCCLK * [(SYNR + 1)/(REFDIV + 1)]
> > // eg, PLLCLK = 2 * 16MHz * 20 / 16 for PLLCLK = 40MHz
> > SYNR = SYNR_val; // 17 for 44.3077MHz PLL; initialises LOCK and TRACK flags
> > REFDV = REFDV_val; // 12 for 44.3077MHz PLL
> > // #### below PLLCTL = 0b01110000 line moved here from lower down since must turn on the PLL and wait a bit
> > // before can go into the "LOCK" condition!! AND ... Delay needed for the PLL since
> > // just after turnon, it maybe thinks that it has a lock while it really does not.
> > // With the below line here, and with only one test needed of conditions before exit of Loop#1,
> > // ended up with a good lock at ~22MHz Eclock. Also with below line placed between Loop#1 and Loop#2,
> > // AND with a breakpoint after the line to cause a delay, got a 22MHz Eclock. HOWEVER, without a breakpoint
> > // delay, Loop#2 would execute rapidly and exit with the PLL NOT locked and an 8MHz Eclock. Why was the
> > // Loop#2 delay insufficient to assure good lock, while only one pass through Loop#1, ie, a minimal delay, worked fine?
> > // Note Loop#2 looks for Track or Lock to be set; Freescale app note informed that Lock bit unreliable for rapid locking w/out overshoot.
> > PLLCTL = 0b01110000; // PLLCTL: CME=0,PLLON=1,AUTO=1,ACQ=1,xx=0,PRE=0,PCE=0,SCME=0
> > // LOOP#1; put in a delay; see erratum MUCTS00174 (mask set 0K36N only; typ mask here is 1L59W)
> > // which kept LOCK signal high after setting above registers, for about 10 cycles.
> > StatusPLLSetup8 = 0; // initialise the counter for good lock/track reads
> > do
> > {
> > StatusPLLFlags8 = SYNR; // SYNR is 11 hex ie 17
> > StatusPLLFlags8 = REFDV; // REFDV is 0C hex ie 12
> > StatusPLLFlags8 = CLKSEL;// CLKSEL is 00 hex so PLL not on;
> > StatusPLLFlags8 = CRGFLG;// CRGFLG is 1C so LOCK, TRACK are set and LOCK interrupt flag LOCKIF is on
> > if ((StatusPLLFlags8 & BIT3) == 0) // if LOCK is zero
> > {
> > StatusPLLSetup8 = 0x4F; // can now exit this loop; typ. happens at first loop!
> > }
> > StatusPLLFlags8 = PLLCTL; // PLLCTL is F1 so ClockMonitorEnable, PLLON, AUTO, ACQ, SelfClockModeEnable on
> > StatusPLLSetup8 = StatusPLLSetup8 + 1;
> > CRGFLG = 0; // writes have no effect on this flag register
> > }
> > while (StatusPLLSetup8 < 0x50); // delay 16 times times 5; need a really long delay for good LOCK AND TRACK? see exit above; no, we don't.
> > StatusPLLFlags8 = CRGFLG; // CRGFLG is 5C hex so PwrOnResetFlg, LOCKchangeInterruptFlag, LOCK, TRACK set; SCM off so the Xtal is being used.
> > // LOOP#2; here is where could have put the PLLON command; but it did not work here; see above.
> > StatusPLLSetup8 = 0x51; //
> > do
> > {
> > StatusPLLSetup8 = StatusPLLSetup8 + 1;
> > StatusPLLFlags8 = SYNR; // SYNR is 11 hex
> > StatusPLLFlags8 = REFDV; // REFDV is 0C hex
> > StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so PLL is not the clock source.
> > StatusPLLFlags8 = PLLCTL; // PLLCTL is 70 so SCME is off and top byte is 0x0111 so just as programmed above
> > StatusPLLFlags8 = CRGFLG;// CRGFLG is 1C so LOCK, TRACK are set and LOCK interrupt flag LOCKIF is on
> > // require both lock and track to be zero for no-lock condition
> > if ( ((CRGFLG & TRACK) == 0) && ((CRGFLG & LOCK) == 0) ) StatusPLLSetup8 = 0x51;
> > }
> > while (StatusPLLSetup8 < 0x60);// must read "locked" at least 16 consecutive times
> > SetBit(CLKSEL, PLLSEL);// select PLL clocking when are tracking or locked.
> > StatusPLLFlags8 = CLKSEL; // CLKSEL is 80 hex so PLL is on; and all of the wait and stop bits off.
> > StatusPLLFlags8 = PLLCTL; // PLLCTL is 70 so CME is off but PLLON, AUTO, ACQ are on
> > StatusPLLFlags8 = CRGFLG;
> > } //end of Set_PLL_Clock
>

Thanks for the reference Darci.

Your EB640 was in fact my 'inspiration' for checking either for TRACK or LOCK, rather than just LOCK, for being within range. Is that appropriate for covering the case of not seeing a LOCK signal?

In addition, I guess you mean my troubles have been caused by not waiting 127 clock cycles in my delay LOOP#1, right? The implication being that my first delay loop should be much longer to assure there has been time to get meaningful signal output.

Also, since LOCK and TRACK would only be updated once per many cycles, my LOOP#2 repeated checking for these signals should have been slowed down to allow say 300 cycles between each check.

Are these concepts correct?

--- In 6..., "dleatmot" wrote:
>
> sorry I forgot to give a link for those who hate our search engine..
>
> http://cache.freescale.com/files/microcontrollers/doc/eng_bulletin/EB640.pdf?fpsp=1&WT_TYPE=Engineering Bulletins&WT_VENDOR=FREESCALE&WT_FILE_FORMAT=pdf&WT_ASSET=Documentation
>
> --- In 6..., "dleatmot" wrote:
> >
> >
> > You might want to read a engineering bulletin I did about 7 years ago, EB640, I think that will explain to you what is going on.
> >
> > Regards,
> > Darci
> >
> > --- In 6..., "Chris" wrote:
> > >
> > > Hello; Now I think my problem with PLL-setting is clarified and while I have a workaround, why it works escapes me.
> > >
> > > In the below code are two delay loops to assure that the Lock and Track bits have time to change and settle, assuring a good lock before making the PLL the system clock source. After telling the PLL to turn on, if I use only the second delay loop it is not enough; but including the first delay loop, it only needs one pass through the loop to assure we have lock after going through the second delay loop. The second loop extends its delay if lock and track are not on, so its delay on its own should all that is needed. What am I missing here? Any help would be appreciated.
> > >
> > > Please excuse the lengthy code below; its debug outputs show the clock system status at each point.
> > >
> > > void Set_PLL_Clock(uint8_t SYNR_val, uint8_t REFDV_val)
> > > {
> > > uint8_t StatusPLLFlags8; // local variable used for debug readout of Clock status registers
> > > // uint8_t StatusPLLSetup8; // in globals.h
> > > StatusPLLFlags8 = CRGFLG; // CRGFLG is either 5C/1C hex when above statement was executed
> > > // so PwrOnResetFlg is on/off; LOCKhangeInterruptFlag;LOCK and TRACK are set; SCM off so the Xtal is being used.
> > > StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so the PLL is not the clock source.
> > > // make sure PLL is not in use OTHERWISE CAN'T WRITE TO SYNR, OR REFDV, OR PLLON in PLLCTL
> > > ClrBit(CLKSEL, PLLWAI); // if 0, PLL runs during Wait mode; and allows write to AUTO bit
> > > StatusPLLFlags8 = CLKSEL; // for debug
> > > ClrBit(CLKSEL, PLLSEL); // If PLLSEL is set to 0, clock is derived from the OSCCLK
> > > StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so PLL is not the clock source.
> > > StatusPLLFlags8 = CRGFLG; // CRGFLG is 5C/1C hex when above statement was executed so PwrOnResetFlg is on/off,and; LOCKhangeInterruptFlag and LOCK and TRACK are set; SCM is not on so the Xtal is being used.
> > > CRGFLG = 0xFF; // clear all of the flags by writing a 1 to them
> > > StatusPLLFlags8 = CRGFLG; // CRGFLG is 0C hex so TRI PWRON TRACK interrupt flags off; LOCK, TRACK are still set, SCM off
> > > // PLLCLK = 2 * OSCCLK * [(SYNR + 1)/(REFDIV + 1)]
> > > // eg, PLLCLK = 2 * 16MHz * 20 / 16 for PLLCLK = 40MHz
> > > SYNR = SYNR_val; // 17 for 44.3077MHz PLL; initialises LOCK and TRACK flags
> > > REFDV = REFDV_val; // 12 for 44.3077MHz PLL
> > > // #### below PLLCTL = 0b01110000 line moved here from lower down since must turn on the PLL and wait a bit
> > > // before can go into the "LOCK" condition!! AND ... Delay needed for the PLL since
> > > // just after turnon, it maybe thinks that it has a lock while it really does not.
> > > // With the below line here, and with only one test needed of conditions before exit of Loop#1,
> > > // ended up with a good lock at ~22MHz Eclock. Also with below line placed between Loop#1 and Loop#2,
> > > // AND with a breakpoint after the line to cause a delay, got a 22MHz Eclock. HOWEVER, without a breakpoint
> > > // delay, Loop#2 would execute rapidly and exit with the PLL NOT locked and an 8MHz Eclock. Why was the
> > > // Loop#2 delay insufficient to assure good lock, while only one pass through Loop#1, ie, a minimal delay, worked fine?
> > > // Note Loop#2 looks for Track or Lock to be set; Freescale app note informed that Lock bit unreliable for rapid locking w/out overshoot.
> > > PLLCTL = 0b01110000; // PLLCTL: CME=0,PLLON=1,AUTO=1,ACQ=1,xx=0,PRE=0,PCE=0,SCME=0
> > > // LOOP#1; put in a delay; see erratum MUCTS00174 (mask set 0K36N only; typ mask here is 1L59W)
> > > // which kept LOCK signal high after setting above registers, for about 10 cycles.
> > > StatusPLLSetup8 = 0; // initialise the counter for good lock/track reads
> > > do
> > > {
> > > StatusPLLFlags8 = SYNR; // SYNR is 11 hex ie 17
> > > StatusPLLFlags8 = REFDV; // REFDV is 0C hex ie 12
> > > StatusPLLFlags8 = CLKSEL;// CLKSEL is 00 hex so PLL not on;
> > > StatusPLLFlags8 = CRGFLG;// CRGFLG is 1C so LOCK, TRACK are set and LOCK interrupt flag LOCKIF is on
> > > if ((StatusPLLFlags8 & BIT3) == 0) // if LOCK is zero
> > > {
> > > StatusPLLSetup8 = 0x4F; // can now exit this loop; typ. happens at first loop!
> > > }
> > > StatusPLLFlags8 = PLLCTL; // PLLCTL is F1 so ClockMonitorEnable, PLLON, AUTO, ACQ, SelfClockModeEnable on
> > > StatusPLLSetup8 = StatusPLLSetup8 + 1;
> > > CRGFLG = 0; // writes have no effect on this flag register
> > > }
> > > while (StatusPLLSetup8 < 0x50); // delay 16 times times 5; need a really long delay for good LOCK AND TRACK? see exit above; no, we don't.
> > > StatusPLLFlags8 = CRGFLG; // CRGFLG is 5C hex so PwrOnResetFlg, LOCKchangeInterruptFlag, LOCK, TRACK set; SCM off so the Xtal is being used.
> > > // LOOP#2; here is where could have put the PLLON command; but it did not work here; see above.
> > > StatusPLLSetup8 = 0x51; //
> > > do
> > > {
> > > StatusPLLSetup8 = StatusPLLSetup8 + 1;
> > > StatusPLLFlags8 = SYNR; // SYNR is 11 hex
> > > StatusPLLFlags8 = REFDV; // REFDV is 0C hex
> > > StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so PLL is not the clock source.
> > > StatusPLLFlags8 = PLLCTL; // PLLCTL is 70 so SCME is off and top byte is 0x0111 so just as programmed above
> > > StatusPLLFlags8 = CRGFLG;// CRGFLG is 1C so LOCK, TRACK are set and LOCK interrupt flag LOCKIF is on
> > > // require both lock and track to be zero for no-lock condition
> > > if ( ((CRGFLG & TRACK) == 0) && ((CRGFLG & LOCK) == 0) ) StatusPLLSetup8 = 0x51;
> > > }
> > > while (StatusPLLSetup8 < 0x60);// must read "locked" at least 16 consecutive times
> > > SetBit(CLKSEL, PLLSEL);// select PLL clocking when are tracking or locked.
> > > StatusPLLFlags8 = CLKSEL; // CLKSEL is 80 hex so PLL is on; and all of the wait and stop bits off.
> > > StatusPLLFlags8 = PLLCTL; // PLLCTL is 70 so CME is off but PLLON, AUTO, ACQ are on
> > > StatusPLLFlags8 = CRGFLG;
> > > } //end of Set_PLL_Clock
> > >
>
Why are you writing to REFDV and SYNR in the loop? Docs say that write to
these registers initializes lock and and track detector bits. It is not
surprising that you have prroblems with lock. Code should be pretty simple.
Init REFDV and SYNR once, then wait for lock. Or clear lock on/off interrupt
flag, init REFDV and SYNR, then wait for lock interrupt flag.

Also, what about loosing lock due EMI. Wouldn't it be better to create lock
interrupt and switch to PLL clock there? At start up you would need to init
only REFDV and SYNR, also enable change of lock interrupt. In ISR handler
just set PLLSEL (since setting it is ignored while not locked).

Edward
----- Original Message -----
From: "Chris"
To: <6...>
Sent: Thursday, September 22, 2011 8:14 PM
Subject: [68HC12] Re: trouble with PLL on the HC12 - CONTINUED
> Thanks for the reference Darci.
>
> Your EB640 was in fact my 'inspiration' for checking either for TRACK or
> LOCK, rather than just LOCK, for being within range. Is that appropriate
> for covering the case of not seeing a LOCK signal?
>
> In addition, I guess you mean my troubles have been caused by not waiting
> 127 clock cycles in my delay LOOP#1, right? The implication being that my
> first delay loop should be much longer to assure there has been time to
> get meaningful signal output.
>
> Also, since LOCK and TRACK would only be updated once per many cycles, my
> LOOP#2 repeated checking for these signals should have been slowed down to
> allow say 300 cycles between each check.
>
> Are these concepts correct?
>
> --- In 6..., "dleatmot" wrote:
>>
>> sorry I forgot to give a link for those who hate our search engine..
>>
>> http://cache.freescale.com/files/microcontrollers/doc/eng_bulletin/EB640.pdf?fpsp=1&WT_TYPE=Engineering
>> Bulletins&WT_VENDOR=FREESCALE&WT_FILE_FORMAT=pdf&WT_ASSET=Documentation
>>
>> --- In 6..., "dleatmot" wrote:
>> >
>> >
>> > You might want to read a engineering bulletin I did about 7 years ago,
>> > EB640, I think that will explain to you what is going on.
>> >
>> > Regards,
>> > Darci
>> >
>> > --- In 6..., "Chris" wrote:
>> > >
>> > > Hello; Now I think my problem with PLL-setting is clarified and while
>> > > I have a workaround, why it works escapes me.
>> > >
>> > > In the below code are two delay loops to assure that the Lock and
>> > > Track bits have time to change and settle, assuring a good lock
>> > > before making the PLL the system clock source. After telling the PLL
>> > > to turn on, if I use only the second delay loop it is not enough; but
>> > > including the first delay loop, it only needs one pass through the
>> > > loop to assure we have lock after going through the second delay
>> > > loop. The second loop extends its delay if lock and track are not on,
>> > > so its delay on its own should all that is needed. What am I missing
>> > > here? Any help would be appreciated.
>> > >
>> > > Please excuse the lengthy code below; its debug outputs show the
>> > > clock system status at each point.
>> > >
>> > > void Set_PLL_Clock(uint8_t SYNR_val, uint8_t REFDV_val)
>> > > {
>> > > uint8_t StatusPLLFlags8; // local variable used for debug readout
>> > > of Clock status registers
>> > > // uint8_t StatusPLLSetup8; // in globals.h
>> > > StatusPLLFlags8 = CRGFLG; // CRGFLG is either 5C/1C hex when above
>> > > statement was executed
>> > > // so PwrOnResetFlg is on/off; LOCKhangeInterruptFlag;LOCK and TRACK
>> > > are set; SCM off so the Xtal is being used.
>> > > StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so the PLL is not the
>> > > clock source.
>> > > // make sure PLL is not in use OTHERWISE CAN'T WRITE TO SYNR, OR
>> > > REFDV, OR PLLON in PLLCTL
>> > > ClrBit(CLKSEL, PLLWAI); // if 0, PLL runs during Wait mode; and
>> > > allows write to AUTO bit
>> > > StatusPLLFlags8 = CLKSEL; // for debug
>> > > ClrBit(CLKSEL, PLLSEL); // If PLLSEL is set to 0, clock is derived
>> > > from the OSCCLK
>> > > StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so PLL is not the
>> > > clock source.
>> > > StatusPLLFlags8 = CRGFLG; // CRGFLG is 5C/1C hex when above
>> > > statement was executed so PwrOnResetFlg is on/off,and;
>> > > LOCKhangeInterruptFlag and LOCK and TRACK are set; SCM is not on so
>> > > the Xtal is being used.
>> > > CRGFLG = 0xFF; // clear all of the flags by writing a 1 to them
>> > > StatusPLLFlags8 = CRGFLG; // CRGFLG is 0C hex so TRI PWRON TRACK
>> > > interrupt flags off; LOCK, TRACK are still set, SCM off
>> > > // PLLCLK = 2 * OSCCLK * [(SYNR + 1)/(REFDIV + 1)]
>> > > // eg, PLLCLK = 2 * 16MHz * 20 / 16 for PLLCLK = 40MHz
>> > > SYNR = SYNR_val; // 17 for 44.3077MHz PLL;
>> > > initialises LOCK and TRACK flags
>> > > REFDV = REFDV_val; // 12 for 44.3077MHz PLL
>> > > // #### below PLLCTL = 0b01110000 line moved here from lower down
>> > > since must turn on the PLL and wait a bit
>> > > // before can go into the "LOCK" condition!! AND ... Delay needed for
>> > > the PLL since
>> > > // just after turnon, it maybe thinks that it has a lock while it
>> > > really does not.
>> > > // With the below line here, and with only one test needed of
>> > > conditions before exit of Loop#1,
>> > > // ended up with a good lock at ~22MHz Eclock. Also with below line
>> > > placed between Loop#1 and Loop#2,
>> > > // AND with a breakpoint after the line to cause a delay, got a 22MHz
>> > > Eclock. HOWEVER, without a breakpoint
>> > > // delay, Loop#2 would execute rapidly and exit with the PLL NOT
>> > > locked and an 8MHz Eclock. Why was the
>> > > // Loop#2 delay insufficient to assure good lock, while only one pass
>> > > through Loop#1, ie, a minimal delay, worked fine?
>> > > // Note Loop#2 looks for Track or Lock to be set; Freescale app note
>> > > informed that Lock bit unreliable for rapid locking w/out overshoot.
>> > > PLLCTL = 0b01110000; // PLLCTL:
>> > > CME=0,PLLON=1,AUTO=1,ACQ=1,xx=0,PRE=0,PCE=0,SCME=0
>> > > // LOOP#1; put in a delay; see erratum MUCTS00174 (mask set 0K36N
>> > > only; typ mask here is 1L59W)
>> > > // which kept LOCK signal high after setting above registers, for
>> > > about 10 cycles.
>> > > StatusPLLSetup8 = 0; // initialise the counter for good lock/track
>> > > reads
>> > > do
>> > > {
>> > > StatusPLLFlags8 = SYNR; // SYNR is 11 hex ie 17
>> > > StatusPLLFlags8 = REFDV; // REFDV is 0C hex ie 12
>> > > StatusPLLFlags8 = CLKSEL;// CLKSEL is 00 hex so PLL not on;
>> > > StatusPLLFlags8 = CRGFLG;// CRGFLG is 1C so LOCK, TRACK are set and
>> > > LOCK interrupt flag LOCKIF is on
>> > > if ((StatusPLLFlags8 & BIT3) == 0) // if LOCK is zero
>> > > {
>> > > StatusPLLSetup8 = 0x4F; // can now exit this loop; typ. happens at
>> > > first loop!
>> > > }
>> > > StatusPLLFlags8 = PLLCTL; // PLLCTL is F1 so ClockMonitorEnable,
>> > > PLLON, AUTO, ACQ, SelfClockModeEnable on
>> > > StatusPLLSetup8 = StatusPLLSetup8 + 1;
>> > > CRGFLG = 0; // writes have no effect on this flag register
>> > > }
>> > > while (StatusPLLSetup8 < 0x50); // delay 16 times times 5; need a
>> > > really long delay for good LOCK AND TRACK? see exit above; no, we
>> > > don't.
>> > > StatusPLLFlags8 = CRGFLG; // CRGFLG is 5C hex so PwrOnResetFlg,
>> > > LOCKchangeInterruptFlag, LOCK, TRACK set; SCM off so the Xtal is
>> > > being used.
>> > > // LOOP#2; here is where could have put the PLLON command; but it did
>> > > not work here; see above.
>> > > StatusPLLSetup8 = 0x51; //
>> > > do
>> > > {
>> > > StatusPLLSetup8 = StatusPLLSetup8 + 1;
>> > > StatusPLLFlags8 = SYNR; // SYNR is 11 hex
>> > > StatusPLLFlags8 = REFDV; // REFDV is 0C hex
>> > > StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so PLL is not the
>> > > clock source.
>> > > StatusPLLFlags8 = PLLCTL; // PLLCTL is 70 so SCME is off and top
>> > > byte is 0x0111 so just as programmed above
>> > > StatusPLLFlags8 = CRGFLG;// CRGFLG is 1C so LOCK, TRACK are set and
>> > > LOCK interrupt flag LOCKIF is on
>> > > // require both lock and track to be zero for no-lock condition
>> > > if ( ((CRGFLG & TRACK) == 0) && ((CRGFLG & LOCK) == 0) )
>> > > StatusPLLSetup8 = 0x51;
>> > > }
>> > > while (StatusPLLSetup8 < 0x60);// must read "locked" at least 16
>> > > consecutive times
>> > > SetBit(CLKSEL, PLLSEL);// select PLL clocking when are tracking or
>> > > locked.
>> > > StatusPLLFlags8 = CLKSEL; // CLKSEL is 80 hex so PLL is on; and all
>> > > of the wait and stop bits off.
>> > > StatusPLLFlags8 = PLLCTL; // PLLCTL is 70 so CME is off but PLLON,
>> > > AUTO, ACQ are on
>> > > StatusPLLFlags8 = CRGFLG;
>> > > } //end of Set_PLL_Clock
>> > >
>> >
>>
Hi All,
I have always used Lock Interrupt to switch over to using the PLL for the Bus Clock. Using the Lock interrupt is preferred and allow the MCU to process more startup code while waiting for the PLL to initialize. Within the Lock Interrupt routine I check the Track bit before switching the Bus Clock over to the PLL. I have never had an instance where the PLL failed to initialized.

Bruce

From: Chris
Sent: Thursday, September 22, 2011 1:14 PM
To: 6...
Subject: [68HC12] Re: trouble with PLL on the HC12 - CONTINUED

Thanks for the reference Darci.

Your EB640 was in fact my 'inspiration' for checking either for TRACK or LOCK, rather than just LOCK, for being within range. Is that appropriate for covering the case of not seeing a LOCK signal?

In addition, I guess you mean my troubles have been caused by not waiting 127 clock cycles in my delay LOOP#1, right? The implication being that my first delay loop should be much longer to assure there has been time to get meaningful signal output.

Also, since LOCK and TRACK would only be updated once per many cycles, my LOOP#2 repeated checking for these signals should have been slowed down to allow say 300 cycles between each check.

Are these concepts correct?

--- In mailto:68HC12%40yahoogroups.com, "dleatmot" wrote:
>
> sorry I forgot to give a link for those who hate our search engine..
>
> http://cache.freescale.com/files/microcontrollers/doc/eng_bulletin/EB640.pdf?fpsp=1&WT_TYPE=Engineering Bulletins&WT_VENDOR=FREESCALE&WT_FILE_FORMAT=pdf&WT_ASSET=Documentation
>
> --- In mailto:68HC12%40yahoogroups.com, "dleatmot" wrote:
> >
> >
> > You might want to read a engineering bulletin I did about 7 years ago, EB640, I think that will explain to you what is going on.
> >
> > Regards,
> > Darci
> >
> > --- In mailto:68HC12%40yahoogroups.com, "Chris" wrote:
> > >
> > > Hello; Now I think my problem with PLL-setting is clarified and while I have a workaround, why it works escapes me.
> > >
> > > In the below code are two delay loops to assure that the Lock and Track bits have time to change and settle, assuring a good lock before making the PLL the system clock source. After telling the PLL to turn on, if I use only the second delay loop it is not enough; but including the first delay loop, it only needs one pass through the loop to assure we have lock after going through the second delay loop. The second loop extends its delay if lock and track are not on, so its delay on its own should all that is needed. What am I missing here? Any help would be appreciated.
> > >
> > > Please excuse the lengthy code below; its debug outputs show the clock system status at each point.
> > >
> > > void Set_PLL_Clock(uint8_t SYNR_val, uint8_t REFDV_val)
> > > {
> > > uint8_t StatusPLLFlags8; // local variable used for debug readout of Clock status registers
> > > // uint8_t StatusPLLSetup8; // in globals.h
> > > StatusPLLFlags8 = CRGFLG; // CRGFLG is either 5C/1C hex when above statement was executed
> > > // so PwrOnResetFlg is on/off; LOCKhangeInterruptFlag;LOCK and TRACK are set; SCM off so the Xtal is being used.
> > > StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so the PLL is not the clock source.
> > > // make sure PLL is not in use OTHERWISE CAN'T WRITE TO SYNR, OR REFDV, OR PLLON in PLLCTL
> > > ClrBit(CLKSEL, PLLWAI); // if 0, PLL runs during Wait mode; and allows write to AUTO bit
> > > StatusPLLFlags8 = CLKSEL; // for debug
> > > ClrBit(CLKSEL, PLLSEL); // If PLLSEL is set to 0, clock is derived from the OSCCLK
> > > StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so PLL is not the clock source.
> > > StatusPLLFlags8 = CRGFLG; // CRGFLG is 5C/1C hex when above statement was executed so PwrOnResetFlg is on/off,and; LOCKhangeInterruptFlag and LOCK and TRACK are set; SCM is not on so the Xtal is being used.
> > > CRGFLG = 0xFF; // clear all of the flags by writing a 1 to them
> > > StatusPLLFlags8 = CRGFLG; // CRGFLG is 0C hex so TRI PWRON TRACK interrupt flags off; LOCK, TRACK are still set, SCM off
> > > // PLLCLK = 2 * OSCCLK * [(SYNR + 1)/(REFDIV + 1)]
> > > // eg, PLLCLK = 2 * 16MHz * 20 / 16 for PLLCLK = 40MHz
> > > SYNR = SYNR_val; // 17 for 44.3077MHz PLL; initialises LOCK and TRACK flags
> > > REFDV = REFDV_val; // 12 for 44.3077MHz PLL
> > > // #### below PLLCTL = 0b01110000 line moved here from lower down since must turn on the PLL and wait a bit
> > > // before can go into the "LOCK" condition!! AND ... Delay needed for the PLL since
> > > // just after turnon, it maybe thinks that it has a lock while it really does not.
> > > // With the below line here, and with only one test needed of conditions before exit of Loop#1,
> > > // ended up with a good lock at ~22MHz Eclock. Also with below line placed between Loop#1 and Loop#2,
> > > // AND with a breakpoint after the line to cause a delay, got a 22MHz Eclock. HOWEVER, without a breakpoint
> > > // delay, Loop#2 would execute rapidly and exit with the PLL NOT locked and an 8MHz Eclock. Why was the
> > > // Loop#2 delay insufficient to assure good lock, while only one pass through Loop#1, ie, a minimal delay, worked fine?
> > > // Note Loop#2 looks for Track or Lock to be set; Freescale app note informed that Lock bit unreliable for rapid locking w/out overshoot.
> > > PLLCTL = 0b01110000; // PLLCTL: CME=0,PLLON=1,AUTO=1,ACQ=1,xx=0,PRE=0,PCE=0,SCME=0
> > > // LOOP#1; put in a delay; see erratum MUCTS00174 (mask set 0K36N only; typ mask here is 1L59W)
> > > // which kept LOCK signal high after setting above registers, for about 10 cycles.
> > > StatusPLLSetup8 = 0; // initialise the counter for good lock/track reads
> > > do
> > > {
> > > StatusPLLFlags8 = SYNR; // SYNR is 11 hex ie 17
> > > StatusPLLFlags8 = REFDV; // REFDV is 0C hex ie 12
> > > StatusPLLFlags8 = CLKSEL;// CLKSEL is 00 hex so PLL not on;
> > > StatusPLLFlags8 = CRGFLG;// CRGFLG is 1C so LOCK, TRACK are set and LOCK interrupt flag LOCKIF is on
> > > if ((StatusPLLFlags8 & BIT3) == 0) // if LOCK is zero
> > > {
> > > StatusPLLSetup8 = 0x4F; // can now exit this loop; typ. happens at first loop!
> > > }
> > > StatusPLLFlags8 = PLLCTL; // PLLCTL is F1 so ClockMonitorEnable, PLLON, AUTO, ACQ, SelfClockModeEnable on
> > > StatusPLLSetup8 = StatusPLLSetup8 + 1;
> > > CRGFLG = 0; // writes have no effect on this flag register
> > > }
> > > while (StatusPLLSetup8 < 0x50); // delay 16 times times 5; need a really long delay for good LOCK AND TRACK? see exit above; no, we don't.
> > > StatusPLLFlags8 = CRGFLG; // CRGFLG is 5C hex so PwrOnResetFlg, LOCKchangeInterruptFlag, LOCK, TRACK set; SCM off so the Xtal is being used.
> > > // LOOP#2; here is where could have put the PLLON command; but it did not work here; see above.
> > > StatusPLLSetup8 = 0x51; //
> > > do
> > > {
> > > StatusPLLSetup8 = StatusPLLSetup8 + 1;
> > > StatusPLLFlags8 = SYNR; // SYNR is 11 hex
> > > StatusPLLFlags8 = REFDV; // REFDV is 0C hex
> > > StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so PLL is not the clock source.
> > > StatusPLLFlags8 = PLLCTL; // PLLCTL is 70 so SCME is off and top byte is 0x0111 so just as programmed above
> > > StatusPLLFlags8 = CRGFLG;// CRGFLG is 1C so LOCK, TRACK are set and LOCK interrupt flag LOCKIF is on
> > > // require both lock and track to be zero for no-lock condition
> > > if ( ((CRGFLG & TRACK) == 0) && ((CRGFLG & LOCK) == 0) ) StatusPLLSetup8 = 0x51;
> > > }
> > > while (StatusPLLSetup8 < 0x60);// must read "locked" at least 16 consecutive times
> > > SetBit(CLKSEL, PLLSEL);// select PLL clocking when are tracking or locked.
> > > StatusPLLFlags8 = CLKSEL; // CLKSEL is 80 hex so PLL is on; and all of the wait and stop bits off.
> > > StatusPLLFlags8 = PLLCTL; // PLLCTL is 70 so CME is off but PLLON, AUTO, ACQ are on
> > > StatusPLLFlags8 = CRGFLG;
> > > } //end of Set_PLL_Clock
> > >
>



Thanks to all for your comments.

My PLL is now working well - and I am certain that it is locked properly ... I had to use Darci's advice and delay for about 600 clock cycles for each of my delay loops to assure correct data. This meant larger loop values in the original code I posted. None of the suggested code snippets out there on the web do it right! They all have about 5 clock delays before scooting off in the assumption that the register status data being read is correct.

As Bruce mentions below the use of interrupts rather than delay loops would be a better approach again; as long as sufficient time is forced between permitted interrupt events.

--- In 6..., "Bruce Embry" wrote:
>
> Hi All,
> I have always used Lock Interrupt to switch over to using the PLL for the Bus Clock. Using the Lock interrupt is preferred and allow the MCU to process more startup code while waiting for the PLL to initialize. Within the Lock Interrupt routine I check the Track bit before switching the Bus Clock over to the PLL. I have never had an instance where the PLL failed to initialized.
>
> Bruce
>
> From: Chris
> Sent: Thursday, September 22, 2011 1:14 PM
> To: 6...
> Subject: [68HC12] Re: trouble with PLL on the HC12 - CONTINUED
>
>
> Thanks for the reference Darci.
>
> Your EB640 was in fact my 'inspiration' for checking either for TRACK or LOCK, rather than just LOCK, for being within range. Is that appropriate for covering the case of not seeing a LOCK signal?
>
> In addition, I guess you mean my troubles have been caused by not waiting 127 clock cycles in my delay LOOP#1, right? The implication being that my first delay loop should be much longer to assure there has been time to get meaningful signal output.
>
> Also, since LOCK and TRACK would only be updated once per many cycles, my LOOP#2 repeated checking for these signals should have been slowed down to allow say 300 cycles between each check.
>
> Are these concepts correct?
>
> --- In mailto:68HC12%40yahoogroups.com, "dleatmot" wrote:
> >
> > sorry I forgot to give a link for those who hate our search engine..
> >
> > http://cache.freescale.com/files/microcontrollers/doc/eng_bulletin/EB640.pdf?fpsp=1&WT_TYPE=Engineering Bulletins&WT_VENDOR=FREESCALE&WT_FILE_FORMAT=pdf&WT_ASSET=Documentation
> >
> > --- In mailto:68HC12%40yahoogroups.com, "dleatmot" wrote:
> > >
> > >
> > > You might want to read a engineering bulletin I did about 7 years ago, EB640, I think that will explain to you what is going on.
> > >
> > > Regards,
> > > Darci
> > >
> > > --- In mailto:68HC12%40yahoogroups.com, "Chris" wrote:
> > > >
> > > > Hello; Now I think my problem with PLL-setting is clarified and while I have a workaround, why it works escapes me.
> > > >
> > > > In the below code are two delay loops to assure that the Lock and Track bits have time to change and settle, assuring a good lock before making the PLL the system clock source. After telling the PLL to turn on, if I use only the second delay loop it is not enough; but including the first delay loop, it only needs one pass through the loop to assure we have lock after going through the second delay loop. The second loop extends its delay if lock and track are not on, so its delay on its own should all that is needed. What am I missing here? Any help would be appreciated.
> > > >
> > > > Please excuse the lengthy code below; its debug outputs show the clock system status at each point.
> > > >
> > > > void Set_PLL_Clock(uint8_t SYNR_val, uint8_t REFDV_val)
> > > > {
> > > > uint8_t StatusPLLFlags8; // local variable used for debug readout of Clock status registers
> > > > // uint8_t StatusPLLSetup8; // in globals.h
> > > > StatusPLLFlags8 = CRGFLG; // CRGFLG is either 5C/1C hex when above statement was executed
> > > > // so PwrOnResetFlg is on/off; LOCKhangeInterruptFlag;LOCK and TRACK are set; SCM off so the Xtal is being used.
> > > > StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so the PLL is not the clock source.
> > > > // make sure PLL is not in use OTHERWISE CAN'T WRITE TO SYNR, OR REFDV, OR PLLON in PLLCTL
> > > > ClrBit(CLKSEL, PLLWAI); // if 0, PLL runs during Wait mode; and allows write to AUTO bit
> > > > StatusPLLFlags8 = CLKSEL; // for debug
> > > > ClrBit(CLKSEL, PLLSEL); // If PLLSEL is set to 0, clock is derived from the OSCCLK
> > > > StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so PLL is not the clock source.
> > > > StatusPLLFlags8 = CRGFLG; // CRGFLG is 5C/1C hex when above statement was executed so PwrOnResetFlg is on/off,and; LOCKhangeInterruptFlag and LOCK and TRACK are set; SCM is not on so the Xtal is being used.
> > > > CRGFLG = 0xFF; // clear all of the flags by writing a 1 to them
> > > > StatusPLLFlags8 = CRGFLG; // CRGFLG is 0C hex so TRI PWRON TRACK interrupt flags off; LOCK, TRACK are still set, SCM off
> > > > // PLLCLK = 2 * OSCCLK * [(SYNR + 1)/(REFDIV + 1)]
> > > > // eg, PLLCLK = 2 * 16MHz * 20 / 16 for PLLCLK = 40MHz
> > > > SYNR = SYNR_val; // 17 for 44.3077MHz PLL; initialises LOCK and TRACK flags
> > > > REFDV = REFDV_val; // 12 for 44.3077MHz PLL
> > > > // #### below PLLCTL = 0b01110000 line moved here from lower down since must turn on the PLL and wait a bit
> > > > // before can go into the "LOCK" condition!! AND ... Delay needed for the PLL since
> > > > // just after turnon, it maybe thinks that it has a lock while it really does not.
> > > > // With the below line here, and with only one test needed of conditions before exit of Loop#1,
> > > > // ended up with a good lock at ~22MHz Eclock. Also with below line placed between Loop#1 and Loop#2,
> > > > // AND with a breakpoint after the line to cause a delay, got a 22MHz Eclock. HOWEVER, without a breakpoint
> > > > // delay, Loop#2 would execute rapidly and exit with the PLL NOT locked and an 8MHz Eclock. Why was the
> > > > // Loop#2 delay insufficient to assure good lock, while only one pass through Loop#1, ie, a minimal delay, worked fine?
> > > > // Note Loop#2 looks for Track or Lock to be set; Freescale app note informed that Lock bit unreliable for rapid locking w/out overshoot.
> > > > PLLCTL = 0b01110000; // PLLCTL: CME=0,PLLON=1,AUTO=1,ACQ=1,xx=0,PRE=0,PCE=0,SCME=0
> > > > // LOOP#1; put in a delay; see erratum MUCTS00174 (mask set 0K36N only; typ mask here is 1L59W)
> > > > // which kept LOCK signal high after setting above registers, for about 10 cycles.
> > > > StatusPLLSetup8 = 0; // initialise the counter for good lock/track reads
> > > > do
> > > > {
> > > > StatusPLLFlags8 = SYNR; // SYNR is 11 hex ie 17
> > > > StatusPLLFlags8 = REFDV; // REFDV is 0C hex ie 12
> > > > StatusPLLFlags8 = CLKSEL;// CLKSEL is 00 hex so PLL not on;
> > > > StatusPLLFlags8 = CRGFLG;// CRGFLG is 1C so LOCK, TRACK are set and LOCK interrupt flag LOCKIF is on
> > > > if ((StatusPLLFlags8 & BIT3) == 0) // if LOCK is zero
> > > > {
> > > > StatusPLLSetup8 = 0x4F; // can now exit this loop; typ. happens at first loop!
> > > > }
> > > > StatusPLLFlags8 = PLLCTL; // PLLCTL is F1 so ClockMonitorEnable, PLLON, AUTO, ACQ, SelfClockModeEnable on
> > > > StatusPLLSetup8 = StatusPLLSetup8 + 1;
> > > > CRGFLG = 0; // writes have no effect on this flag register
> > > > }
> > > > while (StatusPLLSetup8 < 0x50); // delay 16 times times 5; need a really long delay for good LOCK AND TRACK? see exit above; no, we don't.
> > > > StatusPLLFlags8 = CRGFLG; // CRGFLG is 5C hex so PwrOnResetFlg, LOCKchangeInterruptFlag, LOCK, TRACK set; SCM off so the Xtal is being used.
> > > > // LOOP#2; here is where could have put the PLLON command; but it did not work here; see above.
> > > > StatusPLLSetup8 = 0x51; //
> > > > do
> > > > {
> > > > StatusPLLSetup8 = StatusPLLSetup8 + 1;
> > > > StatusPLLFlags8 = SYNR; // SYNR is 11 hex
> > > > StatusPLLFlags8 = REFDV; // REFDV is 0C hex
> > > > StatusPLLFlags8 = CLKSEL; // CLKSEL is 00 hex so PLL is not the clock source.
> > > > StatusPLLFlags8 = PLLCTL; // PLLCTL is 70 so SCME is off and top byte is 0x0111 so just as programmed above
> > > > StatusPLLFlags8 = CRGFLG;// CRGFLG is 1C so LOCK, TRACK are set and LOCK interrupt flag LOCKIF is on
> > > > // require both lock and track to be zero for no-lock condition
> > > > if ( ((CRGFLG & TRACK) == 0) && ((CRGFLG & LOCK) == 0) ) StatusPLLSetup8 = 0x51;
> > > > }
> > > > while (StatusPLLSetup8 < 0x60);// must read "locked" at least 16 consecutive times
> > > > SetBit(CLKSEL, PLLSEL);// select PLL clocking when are tracking or locked.
> > > > StatusPLLFlags8 = CLKSEL; // CLKSEL is 80 hex so PLL is on; and all of the wait and stop bits off.
> > > > StatusPLLFlags8 = PLLCTL; // PLLCTL is 70 so CME is off but PLLON, AUTO, ACQ are on
> > > > StatusPLLFlags8 = CRGFLG;
> > > > } //end of Set_PLL_Clock
> > > >
> > >
> >
>