trouble with PLL on the HC12 - CONTINUED

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

trouble with PLL on the HC12 - CONTINUED

elgrip
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 | Threaded
Open this post in threaded view
|

Re: trouble with PLL on the HC12 - CONTINUED

dleatmot

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 [hidden email], "Chris" <mail@...> 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 | Threaded
Open this post in threaded view
|

Re: trouble with PLL on the HC12 - CONTINUED

dleatmot
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 [hidden email], "dleatmot" <rzft50@...> 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 [hidden email], "Chris" <mail@> 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 | Threaded
Open this post in threaded view
|

Re: trouble with PLL on the HC12 - CONTINUED

elgrip


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 [hidden email], "dleatmot" <rzft50@...> 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 [hidden email], "dleatmot" <rzft50@> 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 [hidden email], "Chris" <mail@> 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 | Threaded
Open this post in threaded view
|

Re: Re: trouble with PLL on the HC12 - CONTINUED

Edward Karpicz
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" <[hidden email]>
To: <[hidden email]>
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 [hidden email], "dleatmot" <rzft50@...> 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 [hidden email], "dleatmot" <rzft50@> 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 [hidden email], "Chris" <mail@> 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
>> > >
>> >
>>
>
>
>
> ------------------------------------
>
> Yahoo! Groups Links
>
>
>