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..
--- 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
>