Reply by Edward Karpicz September 30, 20112011-09-30
Chris,

Yes, and sorry, you code isn't setting SYNR/REFDV in the loop. What happened
to me is that probably I was too tired and you statement about inserting
delay loops triggered in my brain the "oh no, it's bad practice all those
best and whistles with add empty loop here, add empty loop there". Yes, it
makes sense to delay to give more chances of success to bad practice of
initializing and switching to PLL clock only ONCE per MCU reset. Good
practice is to rely on the fact that EMI/ESD can unlock PLL at any time,
thus you need to have PLL lock/unlock interrupt to do it reliably, which
would eliminate the need of any delay. If for some reason you can't use
interrupts, then you should be sure what amount of delay is required and how
it depends on PLL filter and oscilator clock. It is unknown, right? So maybe
just try to wait for LOCK, or clear the LOCKIF, init SYNR and REFDV, then
wait for LOCKIF, and then check in your main loop if PLL is still locked,
reswitch to PLL clock when necessary? It would be more reliable even with no
interrupts and no unknown delays. BTW are those 100 cycles specified in
datasheets? If not, and specified only in EB, then why should we rely on it
and keep wasting MCU cycles? Were there no changes in PLL module since EB
saw soon light? Were there no changes in PLL modules on S12C, S12X? Without
specific delays required, PLL code was the same for all S12/S12X until
recent S12XE, S12P etc. That's my IMO.

Best Regards
Edward

----- Original Message -----
From: "Chris"
To: <6...>
Sent: Thursday, September 29, 2011 8:25 PM
Subject: [68HC12] Re: trouble with PLL on the HC12 - CONTINUED
Thanks Guillermo for below code; and Edward for your comments.

I believe that both of you are not correct however, from my experience over
the past weeks in trying to get the PLL mystery solved. And Edward, if you
look at my code you will see that I only set the divider and multiplier once
at the top; they are definitely not in a loop.

It's not a mystery that the PLL works even with bad code - for years I have
been using bad code and it worked just fine! The problems came when I looked
at web examples such as the one below, and tried to assimilate the mask
error information for an earlier mask set as well as the info in Darci's
Motorola Engineering Bulletin EB640 about PLL delays. I then began to see
what I thought were illogical results; I would obtain lock and appear to
have switched to the PLL as a clock source when in fact I had not and was
still on an ECLK of 8MHz (with my 16MHz Xtal), and this performance seemed
to depend on the type of reset signal I was using.

So I communicated with Darci in Freescale about this, firstly in this Forum
but then directly, and it slowly dawned upon me that I had not properly read
and understood his EB640. When he states the reference divider timing is
always more than 100 cycles, it means that neither LOCK nor TRACK nor the
AUTO status signals get updated any faster than that. So there may be a
glitch, or the known register-setting mask bug, that puts the LOCK on. That
signal is not meaningful however until you have looked again, say 200 cycles
later. If you want to be properly thorough about it, and follow the
suggestion of the in-circuit emulator guys on the web, you would check that
LOCK is consistently seen for perhaps 600 or 1000 cycles. Thus the code
below, which jumps out at the first sighting of a LOCK signal, is not good
enough for ensuring reliable operation in a known state.

In addition, since LOCK is not a reliable indicator of lock, (as Motorola
points out, LOCK may never go on even if you are locked, in some cases of
low phase error), I look for the TRACK or the LOCK signals (in fact, TRACK
is equivalent to looking at the AUTO status signal) to tell me whether I am
in lock or not.

So in summary, while code can yield good PLL operation and still disobey the
rules, if you need to be certain of PLL operation you must wait long enough
to obtain valid system responses to any change you make. In the case of PLL
signals such as LOCK and TRACK, this wait time is about 200 cycles. To avoid
thinking you are locked when you have an underdamped PLL system, you must
see several consecutive valid TRACK signals before you can be sure of
proper locking, and so you must wait perhaps 1000 cycles over which time you
see constant verification of lock.

Apparently systems in the industrial/automotive arena all do this correctly;
the web examples out there are not good examples of proper coding,
unfortunately.

--- In 6..., "Guillermo F. Molina" wrote:
>
> Hi Chris,
>
> I've been using this simple code at startup for years to enable PLL for
> a BUSCLK of 24 Mhz (16 Mhz xtal) with no problem at all:
>
> SYNR=2; /* BUSCLK=OSCCLK * (SYNR+1)/(REFDV+1) */
> REFDV=1; /* 16 Mhz * (2+1)/(1+1) = 24 Mhz */
> PLLON=1; /* Enable PLL */
> for (i=0; i< 30000;i++){} /* Delay some time ... (45 ms ) */
> while (LOCK==0) {} /* Wait for PLL Lock condition */
> PLLSEL=1; /* Switch Clock source to PLLCLK */
>
> Best regards,
> Guillermo.
> El 28/09/2011 15:02, Edward Karpicz escribi
> >
> > There's no reason to insert any delay. I believe your problem is that
> > you
> > reinit SYNR and REFDV on each loop iteration. This is wrong, you don't
> > allow
> > PLL to run properly while in initialization loops.
> >
> > Edward
> >
> > ----- Original Message -----
> > From: "Chris" >
> > To: <6...







'






































''



























&WT_TYPE



&WT_VENDOR&WT_FILE_FORMAT&WT_ASSET















































'




































































&











<



'






















&&&&


<





























Reply by Chris September 29, 20112011-09-29
Thanks Guillermo for below code; and Edward for your comments.

I believe that both of you are not correct however, from my experience over the past weeks in trying to get the PLL mystery solved. And Edward, if you look at my code you will see that I only set the divider and multiplier once at the top; they are definitely not in a loop.

It's not a mystery that the PLL works even with bad code - for years I have been using bad code and it worked just fine! The problems came when I looked at web examples such as the one below, and tried to assimilate the mask error information for an earlier mask set as well as the info in Darci's Motorola Engineering Bulletin EB640 about PLL delays. I then began to see what I thought were illogical results; I would obtain lock and appear to have switched to the PLL as a clock source when in fact I had not and was still on an ECLK of 8MHz (with my 16MHz Xtal), and this performance seemed to depend on the type of reset signal I was using.

So I communicated with Darci in Freescale about this, firstly in this Forum but then directly, and it slowly dawned upon me that I had not properly read and understood his EB640. When he states the reference divider timing is always more than 100 cycles, it means that neither LOCK nor TRACK nor the AUTO status signals get updated any faster than that. So there may be a glitch, or the known register-setting mask bug, that puts the LOCK on. That signal is not meaningful however until you have looked again, say 200 cycles later. If you want to be properly thorough about it, and follow the suggestion of the in-circuit emulator guys on the web, you would check that LOCK is consistently seen for perhaps 600 or 1000 cycles. Thus the code below, which jumps out at the first sighting of a LOCK signal, is not good enough for ensuring reliable operation in a known state.

In addition, since LOCK is not a reliable indicator of lock, (as Motorola points out, LOCK may never go on even if you are locked, in some cases of low phase error), I look for the TRACK or the LOCK signals (in fact, TRACK is equivalent to looking at the AUTO status signal) to tell me whether I am in lock or not.

So in summary, while code can yield good PLL operation and still disobey the rules, if you need to be certain of PLL operation you must wait long enough to obtain valid system responses to any change you make. In the case of PLL signals such as LOCK and TRACK, this wait time is about 200 cycles. To avoid thinking you are locked when you have an underdamped PLL system, you must see several consecutive valid TRACK signals before you can be sure of proper locking, and so you must wait perhaps 1000 cycles over which time you see constant verification of lock.

Apparently systems in the industrial/automotive arena all do this correctly; the web examples out there are not good examples of proper coding, unfortunately.

--- In 6..., "Guillermo F. Molina" wrote:
>
> Hi Chris,
>
> I've been using this simple code at startup for years to enable PLL for
> a BUSCLK of 24 Mhz (16 Mhz xtal) with no problem at all:
>
> SYNR=2; /* BUSCLK=OSCCLK * (SYNR+1)/(REFDV+1) */
> REFDV=1; /* 16 Mhz * (2+1)/(1+1) = 24 Mhz */
> PLLON=1; /* Enable PLL */
> for (i=0; i< 30000;i++){} /* Delay some time ... (45 ms ) */
> while (LOCK==0) {} /* Wait for PLL Lock condition */
> PLLSEL=1; /* Switch Clock source to PLLCLK */
>
> Best regards,
> Guillermo.
>
>
> El 28/09/2011 15:02, Edward Karpicz escribi
> >
> > There's no reason to insert any delay. I believe your problem is that you
> > reinit SYNR and REFDV on each loop iteration. This is wrong, you don't
> > allow
> > PLL to run properly while in initialization loops.
> >
> > Edward
> >
> > ----- Original Message -----
> > From: "Chris" >
> > To: <6...







'






































''


























&WT_TYPE



&WT_VENDOR&WT_FILE_FORMAT&WT_ASSET












































'
































































&










<



'




















&&&&


<




























Reply by "Guillermo F. Molina" September 28, 20112011-09-28
Hi Chris,

I've been using this simple code at startup for years to enable PLL for
a BUSCLK of 24 Mhz (16 Mhz xtal) with no problem at all:

SYNR=2; /* BUSCLK=OSCCLK * (SYNR+1)/(REFDV+1) */
REFDV=1; /* 16 Mhz * (2+1)/(1+1) = 24 Mhz */
PLLON=1; /* Enable PLL */
for (i=0; i< 30000;i++){} /* Delay some time ... (45 ms ) */
while (LOCK==0) {} /* Wait for PLL Lock condition */
PLLSEL=1; /* Switch Clock source to PLLCLK */

Best regards,
Guillermo.
El 28/09/2011 15:02, Edward Karpicz escribi
>
> There's no reason to insert any delay. I believe your problem is that you
> reinit SYNR and REFDV on each loop iteration. This is wrong, you don't
> allow
> PLL to run properly while in initialization loops.
>
> Edward
>
> ----- Original Message -----
> From: "Chris" >
> To: <6...







'






































''


























&WT_TYPE



&WT_VENDOR&WT_FILE_FORMAT&WT_ASSET












































'
































































&










<



'




















&&&&


<




























Reply by Edward Karpicz September 28, 20112011-09-28
There's no reason to insert any delay. I believe your problem is that you
reinit SYNR and REFDV on each loop iteration. This is wrong, you don't allow
PLL to run properly while in initialization loops.

Edward

----- Original Message -----
From: "Chris"
To: <6...>
Sent: Wednesday, September 28, 2011 7:11 PM
Subject: [68HC12] Re: trouble with PLL on the HC12 - CONTINUED
> 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
>> > > >
>> > >
>> >
>>
>>
>>
>
Reply by Chris September 28, 20112011-09-28
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
> > > >
> > >
> >
>

Reply by Bruce Embry September 26, 20112011-09-26
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
> > >
>



Reply by Edward Karpicz September 22, 20112011-09-22
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
>> > >
>> >
>>
Reply by Chris September 22, 20112011-09-22
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
> > >
>
Reply by dleatmot September 21, 20112011-09-21
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
>

Reply by dleatmot September 21, 20112011-09-21
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
>