EmbeddedRelated.com
Forums

MSP430 External Clock Problem

Started by Ctoad March 28, 2012
Our app needs low jitter and low temp drift in timing so we are using an external clock source. The MSP430 keeps detecting osc fault condition and switching back to the default internal source. This is my first MSP430 project, so I'm hoping that I'm making some simple mistake which the group can point out. Some specifics are:

Clock is Connor Winfield model D75A at 20 MHz. We buffer it through a 74LVC04 before it goes to the MSP430.

I'm using the MSP4305529. VCC = 3.5 V. Using the FET-430UIF and ccs v 4.2.5.0005 on a macbook pro 2011 running parallels desktop emulating Win XP 64 bit.

The code listed below ramps up vcore to level 3, sets XT2 to bypass, outputs MCLK and SMCLK to port pins for monitoring, sets a timer interrupt to provide a heartbeat signal to show the code is running, and has an ISR for osc fault condition where it sets the ck source back to XT2 bypass. The debug version of the code shows it spends all of it's time in the osc ISR waiting for the fault flag to stay clear.

Things I've tried:
1. Running ccs on a real Windows XP pro machine with identical results.
2. Running the code with the internal osc selected to confirm proper operation of the timer ISR with the heartbeat signal.
3. Running a release version of the code with the FET430 removed from the circuit - the power supply connection to it is noisy.
4. Adding 10 uF tant, 5 uF poly and .1 uF ceramic to power supply.
5. Dead bugging a schmitt trig buffer (74LVC1G17) on top of the MSP at XT2 input to better buffer the ck source (and bypassing this buffer power using a 1 uF and .1 uF ceramic caps).
6. Different external power supply.
7. New FET430 (to get rid of power noise - didn't help).
8. .47 uF ceramic on vcore pin. Confirmed vcore using voltmeter and scope.
9. Triple checking the JTAG interface (SLAU138L fig3.2).

The ext ck signal, even after buffering, does not look as good as I'd like, but it is not bad. There are over/undershoots of about 600 mV lasting for about 8 ns, but they are rounded and there is no ringing. The MSP MCLK output when running off of internal osc shows the same level and duration of over/undershoot, but with some ringing - likely due to unterminated pin on MCLK output.

I've read that the MSP430 is very quick to call osc fault on an external source, but this seems ridiculous. I have to be doing something simple and wrong in the code. Any suggestions will be much appreciated.

Code:

#include "msp430f5529.h"

void SetVCoreUp(unsigned int level);

volatile unsigned int i;
unsigned int level1 = 1;
unsigned int level2 = 2;
unsigned int level3 = 3;
//#include
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

SetVCoreUp(level1);
SetVCoreUp(level2);
SetVCoreUp(level3);

P5SEL |= BIT2+BIT3; // Port select XT2
UCSCTL6 |= XT2BYPASS;

UCSCTL6 &= ~XT2OFF; //enable xt2
UCSCTL6 &= SELREF_5;

SFRIE1 |= OFIE; // enables oscillator fault interrupt

UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT2
//UCSCTL5 &= ~(DIVM_0+DIVM_1+DIVM_2); // set MCLK divider to 1 for 20MHz

//Show clocks on output pins
P2DIR |= BIT2; // SMCLK set out to pins
P2SEL |= BIT2;
P7DIR |= BIT7; // MCLK set out to pins
P7SEL |= BIT7;

P5SEL &= ~BIT1; // P5.1 set as I/O
P5DIR |= BIT1; // P5.1 as output (LED1)
P5REN &= ~BIT1; // Disable pullup/pulldown resistor

__bis_SR_register(GIE);

UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT2

TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
TBCCR0 = 50000; // counts to 50000
TBCTL = TBSSEL_2 +MC_1 + TBCLR; // System heartbeat output in ISR.

while(1);

}

// Timer B0 interrupt service routine
#pragma vector=TIMERB0_VECTOR
__interrupt void TIMERB0_ISR (void)
{
P5OUT = 0x00; // heartbeat output on P5.1
P5OUT = 0x02;
P5OUT = 0x00;
P5OUT = 0x02;
}

#pragma vector=UNMI_VECTOR
__interrupt void UNMI_ISR (void) // On osc fault, put it back to XT2
{
do {
P5SEL |= BIT2+BIT3; // Port select XT2
UCSCTL6 |= XT2BYPASS;

UCSCTL6 &= ~XT2OFF; //enable xt2
UCSCTL6 &= SELREF_5;

UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
// Clear XT2,XT1,DCO fault flags
SFRIFG1 &= ~OFIFG; // Clear fault flags
// for (i = 0xFFF;i>0;i--); // Delay

}
while (SFRIFG1&OFIFG); // Test oscillator fault flag

SFRIE1 |= OFIE; // enables oscillator fault interrupt
}

void SetVCoreUp(unsigned int level)
{
// Open PMM registers for write
PMMCTL0_H = PMMPW_H;
// Set SVS/SVM high side new level
SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
// Set SVM low side to new level
SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
// Wait till SVM is settled
while ((PMMIFG & SVSMLDLYIFG) == 0);
// Clear already set flags
PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
// Set VCore to new level
PMMCTL0_L = PMMCOREV0 * level;
// Wait till new level reached
if ((PMMIFG & SVMLIFG))
while ((PMMIFG & SVMLVLRIFG) == 0);
// Set SVS/SVM low side to new level
SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
// Lock PMM registers for write access
PMMCTL0_H = 0x00;
}

Beginning Microcontrollers with the MSP430

More Info:

Examination of UCSCTL7 in debug shows the fault flags set for XT1LFOFFG and DCOFFG and clear for XT2OFFG, so XT1 and DCO seem to be the osc faults holding the MSP in the osc fault ISR. This is with the instruction UCSCTL6 |= XT1OFF; in the config code. Maybe we're doing something wrong in config of DCO, but we've turned off XT1. How can it be holding the chip in fault condition if it is turned off?

--- In m..., "Ctoad" wrote:
>
> Our app needs low jitter and low temp drift in timing so we are using an external clock source. The MSP430 keeps detecting osc fault condition and switching back to the default internal source. This is my first MSP430 project, so I'm hoping that I'm making some simple mistake which the group can point out. Some specifics are:
>
> Clock is Connor Winfield model D75A at 20 MHz. We buffer it through a 74LVC04 before it goes to the MSP430.
>
> I'm using the MSP4305529. VCC = 3.5 V. Using the FET-430UIF and ccs v 4.2.5.0005 on a macbook pro 2011 running parallels desktop emulating Win XP 64 bit.
>
> The code listed below ramps up vcore to level 3, sets XT2 to bypass, outputs MCLK and SMCLK to port pins for monitoring, sets a timer interrupt to provide a heartbeat signal to show the code is running, and has an ISR for osc fault condition where it sets the ck source back to XT2 bypass. The debug version of the code shows it spends all of it's time in the osc ISR waiting for the fault flag to stay clear.
>
> Things I've tried:
> 1. Running ccs on a real Windows XP pro machine with identical results.
> 2. Running the code with the internal osc selected to confirm proper operation of the timer ISR with the heartbeat signal.
> 3. Running a release version of the code with the FET430 removed from the circuit - the power supply connection to it is noisy.
> 4. Adding 10 uF tant, 5 uF poly and .1 uF ceramic to power supply.
> 5. Dead bugging a schmitt trig buffer (74LVC1G17) on top of the MSP at XT2 input to better buffer the ck source (and bypassing this buffer power using a 1 uF and .1 uF ceramic caps).
> 6. Different external power supply.
> 7. New FET430 (to get rid of power noise - didn't help).
> 8. .47 uF ceramic on vcore pin. Confirmed vcore using voltmeter and scope.
> 9. Triple checking the JTAG interface (SLAU138L fig3.2).
>
> The ext ck signal, even after buffering, does not look as good as I'd like, but it is not bad. There are over/undershoots of about 600 mV lasting for about 8 ns, but they are rounded and there is no ringing. The MSP MCLK output when running off of internal osc shows the same level and duration of over/undershoot, but with some ringing - likely due to unterminated pin on MCLK output.
>
> I've read that the MSP430 is very quick to call osc fault on an external source, but this seems ridiculous. I have to be doing something simple and wrong in the code. Any suggestions will be much appreciated.
>
> Code:
>
> #include "msp430f5529.h"
>
> void SetVCoreUp(unsigned int level);
>
> volatile unsigned int i;
> unsigned int level1 = 1;
> unsigned int level2 = 2;
> unsigned int level3 = 3;
> //#include
> int main(void)
> {
> WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
>
> SetVCoreUp(level1);
> SetVCoreUp(level2);
> SetVCoreUp(level3);
>
> P5SEL |= BIT2+BIT3; // Port select XT2
> UCSCTL6 |= XT2BYPASS;
>
> UCSCTL6 &= ~XT2OFF; //enable xt2
> UCSCTL6 &= SELREF_5;
>
> SFRIE1 |= OFIE; // enables oscillator fault interrupt
>
> UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT2
> //UCSCTL5 &= ~(DIVM_0+DIVM_1+DIVM_2); // set MCLK divider to 1 for 20MHz
>
> //Show clocks on output pins
> P2DIR |= BIT2; // SMCLK set out to pins
> P2SEL |= BIT2;
> P7DIR |= BIT7; // MCLK set out to pins
> P7SEL |= BIT7;
>
> P5SEL &= ~BIT1; // P5.1 set as I/O
> P5DIR |= BIT1; // P5.1 as output (LED1)
> P5REN &= ~BIT1; // Disable pullup/pulldown resistor
>
>
>
>
> __bis_SR_register(GIE);
>
>
> UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT2
>
> TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
> TBCCR0 = 50000; // counts to 50000
> TBCTL = TBSSEL_2 +MC_1 + TBCLR; // System heartbeat output in ISR.
>
> while(1);
>
> }
>
> // Timer B0 interrupt service routine
> #pragma vector=TIMERB0_VECTOR
> __interrupt void TIMERB0_ISR (void)
> {
> P5OUT = 0x00; // heartbeat output on P5.1
> P5OUT = 0x02;
> P5OUT = 0x00;
> P5OUT = 0x02;
> }
>
> #pragma vector=UNMI_VECTOR
> __interrupt void UNMI_ISR (void) // On osc fault, put it back to XT2
> {
> do {
> P5SEL |= BIT2+BIT3; // Port select XT2
> UCSCTL6 |= XT2BYPASS;
>
> UCSCTL6 &= ~XT2OFF; //enable xt2
> UCSCTL6 &= SELREF_5;
>
>
> UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
> // Clear XT2,XT1,DCO fault flags
> SFRIFG1 &= ~OFIFG; // Clear fault flags
> // for (i = 0xFFF;i>0;i--); // Delay
>
> }
> while (SFRIFG1&OFIFG); // Test oscillator fault flag
>
> SFRIE1 |= OFIE; // enables oscillator fault interrupt
> }
>
> void SetVCoreUp(unsigned int level)
> {
> // Open PMM registers for write
> PMMCTL0_H = PMMPW_H;
> // Set SVS/SVM high side new level
> SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
> // Set SVM low side to new level
> SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
> // Wait till SVM is settled
> while ((PMMIFG & SVSMLDLYIFG) == 0);
> // Clear already set flags
> PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
> // Set VCore to new level
> PMMCTL0_L = PMMCOREV0 * level;
> // Wait till new level reached
> if ((PMMIFG & SVMLIFG))
> while ((PMMIFG & SVMLVLRIFG) == 0);
> // Set SVS/SVM low side to new level
> SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
> // Lock PMM registers for write access
> PMMCTL0_H = 0x00;
> }
>

And more info:

We tried cutting it down to the simplest code possible. It works, MCLK = 20 MHz from the external clock. We then added a simple timer int and ISR and it is back to broken with MCLK coming from DCO. Code pasted below. Am really pulling hair out on this one and don't have that much left. Any suggestions very welcome.

Code that works:
#include "msp430f5529.h"

void SetVCoreUp(unsigned int level);

volatile unsigned int i;
unsigned int level1 = 1;
unsigned int level2 = 2;
unsigned int level3 = 3;
//#include
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

SetVCoreUp(level1);
SetVCoreUp(level2);
SetVCoreUp(level3);

P2DIR |= BIT2; // SMCLK set out to pins
P2SEL |= BIT2;
P7DIR |= BIT7; // MCLK set out to pins
P7SEL |= BIT7;

P5SEL |= BIT2+BIT3; // Port select XT2
UCSCTL6 |= XT2BYPASS;
//UCSCTL6 &= ~XT2OFF;
//UCSCTL6 |= XT1OFF;

do {

//UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
UCSCTL7 &= ~(XT2OFFG);
// Clear XT2,XT1,DCO fault flags
//SFRIFG1 &= ~OFIFG; // Clear fault flags

__delay_cycles(10000);

//}while (SFRIFG1&OFIFG); // Test oscillator fault flag
}while (UCSCTL7&XT2OFFG);

UCSCTL5 = 0x0000; // divide by 1
UCSCTL4 = SELA_5 + SELS_5 + SELM_5;

while(1);

}

void SetVCoreUp(unsigned int level)
{
// Open PMM registers for write
PMMCTL0_H = PMMPW_H;
// Set SVS/SVM high side new level
SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
// Set SVM low side to new level
SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
// Wait till SVM is settled
while ((PMMIFG & SVSMLDLYIFG) == 0);
// Clear already set flags
PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
// Set VCore to new level
PMMCTL0_L = PMMCOREV0 * level;
// Wait till new level reached
if ((PMMIFG & SVMLIFG))
while ((PMMIFG & SVMLVLRIFG) == 0);
// Set SVS/SVM low side to new level
SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
// Lock PMM registers for write access
PMMCTL0_H = 0x00;
}
Code that does not work: (i.e. falls back to DCO)
#include "msp430f5529.h"

void SetVCoreUp(unsigned int level);

volatile unsigned int i;
unsigned int level1 = 1;
unsigned int level2 = 2;
unsigned int level3 = 3;
//#include
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

SetVCoreUp(level1);
SetVCoreUp(level2);
SetVCoreUp(level3);

P2DIR |= BIT2; // SMCLK set out to pins
P2SEL |= BIT2;
P7DIR |= BIT7; // MCLK set out to pins
P7SEL |= BIT7;

P5SEL &= ~BIT1; // P5.1 set as I/O
P5DIR |= BIT1; // P5.1 as output (LED1)
P5REN &= ~BIT1; // Disable pullup/pulldown resistor

P5SEL |= BIT2+BIT3; // Port select XT2
UCSCTL6 |= XT2BYPASS;
//UCSCTL6 &= ~XT2OFF;
//UCSCTL6 |= XT1OFF;

do {
UCSCTL7 &= ~(XT2OFFG); // Clear XT2,XT1,DCO fault flags
__delay_cycles(10000);

}while (UCSCTL7&XT2OFFG);

UCSCTL5 = 0x0000; // divide by 1
UCSCTL4 = SELA_5 + SELS_5 + SELM_5;

TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
TBCCR0 = 50000; // counts to 50000
TBCTL = TBSSEL_2 +MC_1 + TBCLR;

__bis_SR_register(GIE);
while(1);

}
#pragma vector=TIMERB0_VECTOR
__interrupt void TIMERB0_ISR (void)
{
P5OUT = 0x00;
P5OUT = 0x02;
}
void SetVCoreUp(unsigned int level)
{
// Open PMM registers for write
PMMCTL0_H = PMMPW_H;
// Set SVS/SVM high side new level
SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
// Set SVM low side to new level
SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
// Wait till SVM is settled
while ((PMMIFG & SVSMLDLYIFG) == 0);
// Clear already set flags
PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
// Set VCore to new level
PMMCTL0_L = PMMCOREV0 * level;
// Wait till new level reached
if ((PMMIFG & SVMLIFG))
while ((PMMIFG & SVMLVLRIFG) == 0);
// Set SVS/SVM low side to new level
SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
// Lock PMM registers for write access
PMMCTL0_H = 0x00;
}
--- In m..., "Ctoad" wrote:
>
> More Info:
>
> Examination of UCSCTL7 in debug shows the fault flags set for XT1LFOFFG and DCOFFG and clear for XT2OFFG, so XT1 and DCO seem to be the osc faults holding the MSP in the osc fault ISR. This is with the instruction UCSCTL6 |= XT1OFF; in the config code. Maybe we're doing something wrong in config of DCO, but we've turned off XT1. How can it be holding the chip in fault condition if it is turned off?
>
> --- In m..., "Ctoad" wrote:
> >
> > Our app needs low jitter and low temp drift in timing so we are using an external clock source. The MSP430 keeps detecting osc fault condition and switching back to the default internal source. This is my first MSP430 project, so I'm hoping that I'm making some simple mistake which the group can point out. Some specifics are:
> >
> > Clock is Connor Winfield model D75A at 20 MHz. We buffer it through a 74LVC04 before it goes to the MSP430.
> >
> > I'm using the MSP4305529. VCC = 3.5 V. Using the FET-430UIF and ccs v 4.2.5.0005 on a macbook pro 2011 running parallels desktop emulating Win XP 64 bit.
> >
> > The code listed below ramps up vcore to level 3, sets XT2 to bypass, outputs MCLK and SMCLK to port pins for monitoring, sets a timer interrupt to provide a heartbeat signal to show the code is running, and has an ISR for osc fault condition where it sets the ck source back to XT2 bypass. The debug version of the code shows it spends all of it's time in the osc ISR waiting for the fault flag to stay clear.
> >
> > Things I've tried:
> > 1. Running ccs on a real Windows XP pro machine with identical results.
> > 2. Running the code with the internal osc selected to confirm proper operation of the timer ISR with the heartbeat signal.
> > 3. Running a release version of the code with the FET430 removed from the circuit - the power supply connection to it is noisy.
> > 4. Adding 10 uF tant, 5 uF poly and .1 uF ceramic to power supply.
> > 5. Dead bugging a schmitt trig buffer (74LVC1G17) on top of the MSP at XT2 input to better buffer the ck source (and bypassing this buffer power using a 1 uF and .1 uF ceramic caps).
> > 6. Different external power supply.
> > 7. New FET430 (to get rid of power noise - didn't help).
> > 8. .47 uF ceramic on vcore pin. Confirmed vcore using voltmeter and scope.
> > 9. Triple checking the JTAG interface (SLAU138L fig3.2).
> >
> > The ext ck signal, even after buffering, does not look as good as I'd like, but it is not bad. There are over/undershoots of about 600 mV lasting for about 8 ns, but they are rounded and there is no ringing. The MSP MCLK output when running off of internal osc shows the same level and duration of over/undershoot, but with some ringing - likely due to unterminated pin on MCLK output.
> >
> > I've read that the MSP430 is very quick to call osc fault on an external source, but this seems ridiculous. I have to be doing something simple and wrong in the code. Any suggestions will be much appreciated.
> >
> > Code:
> >
> > #include "msp430f5529.h"
> >
> > void SetVCoreUp(unsigned int level);
> >
> > volatile unsigned int i;
> > unsigned int level1 = 1;
> > unsigned int level2 = 2;
> > unsigned int level3 = 3;
> > //#include
> > int main(void)
> > {
> > WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
> >
> > SetVCoreUp(level1);
> > SetVCoreUp(level2);
> > SetVCoreUp(level3);
> >
> > P5SEL |= BIT2+BIT3; // Port select XT2
> > UCSCTL6 |= XT2BYPASS;
> >
> > UCSCTL6 &= ~XT2OFF; //enable xt2
> > UCSCTL6 &= SELREF_5;
> >
> > SFRIE1 |= OFIE; // enables oscillator fault interrupt
> >
> > UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT2
> > //UCSCTL5 &= ~(DIVM_0+DIVM_1+DIVM_2); // set MCLK divider to 1 for 20MHz
> >
> > //Show clocks on output pins
> > P2DIR |= BIT2; // SMCLK set out to pins
> > P2SEL |= BIT2;
> > P7DIR |= BIT7; // MCLK set out to pins
> > P7SEL |= BIT7;
> >
> > P5SEL &= ~BIT1; // P5.1 set as I/O
> > P5DIR |= BIT1; // P5.1 as output (LED1)
> > P5REN &= ~BIT1; // Disable pullup/pulldown resistor
> >
> >
> >
> >
> > __bis_SR_register(GIE);
> >
> >
> > UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT2
> >
> > TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
> > TBCCR0 = 50000; // counts to 50000
> > TBCTL = TBSSEL_2 +MC_1 + TBCLR; // System heartbeat output in ISR.
> >
> > while(1);
> >
> > }
> >
> > // Timer B0 interrupt service routine
> > #pragma vector=TIMERB0_VECTOR
> > __interrupt void TIMERB0_ISR (void)
> > {
> > P5OUT = 0x00; // heartbeat output on P5.1
> > P5OUT = 0x02;
> > P5OUT = 0x00;
> > P5OUT = 0x02;
> > }
> >
> > #pragma vector=UNMI_VECTOR
> > __interrupt void UNMI_ISR (void) // On osc fault, put it back to XT2
> > {
> > do {
> > P5SEL |= BIT2+BIT3; // Port select XT2
> > UCSCTL6 |= XT2BYPASS;
> >
> > UCSCTL6 &= ~XT2OFF; //enable xt2
> > UCSCTL6 &= SELREF_5;
> >
> >
> > UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
> > // Clear XT2,XT1,DCO fault flags
> > SFRIFG1 &= ~OFIFG; // Clear fault flags
> > // for (i = 0xFFF;i>0;i--); // Delay
> >
> > }
> > while (SFRIFG1&OFIFG); // Test oscillator fault flag
> >
> > SFRIE1 |= OFIE; // enables oscillator fault interrupt
> > }
> >
> > void SetVCoreUp(unsigned int level)
> > {
> > // Open PMM registers for write
> > PMMCTL0_H = PMMPW_H;
> > // Set SVS/SVM high side new level
> > SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
> > // Set SVM low side to new level
> > SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
> > // Wait till SVM is settled
> > while ((PMMIFG & SVSMLDLYIFG) == 0);
> > // Clear already set flags
> > PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
> > // Set VCore to new level
> > PMMCTL0_L = PMMCOREV0 * level;
> > // Wait till new level reached
> > if ((PMMIFG & SVMLIFG))
> > while ((PMMIFG & SVMLVLRIFG) == 0);
> > // Set SVS/SVM low side to new level
> > SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
> > // Lock PMM registers for write access
> > PMMCTL0_H = 0x00;
> > }
>

Change the order of these lines:

TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
TBCCR0 = 50000; // counts to 50000
TBCTL = TBSSEL_2 +MC_1 + TBCLR;

to

TBCCR0 = 50000; // counts to 50000
TBCTL = TBSSEL_2 +MC_1 + TBCLR;
TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
----- Original Message -----
From: Ctoad
To: m...
Sent: Thursday, March 29, 2012 14:36
Subject: [msp430] Re: MSP430 External Clock Problem

And more info:

We tried cutting it down to the simplest code possible. It works, MCLK = 20 MHz from the external clock. We then added a simple timer int and ISR and it is back to broken with MCLK coming from DCO. Code pasted below. Am really pulling hair out on this one and don't have that much left. Any suggestions very welcome.

Code that works:
#include "msp430f5529.h"

void SetVCoreUp(unsigned int level);

volatile unsigned int i;
unsigned int level1 = 1;
unsigned int level2 = 2;
unsigned int level3 = 3;
//#include
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

SetVCoreUp(level1);
SetVCoreUp(level2);
SetVCoreUp(level3);

P2DIR |= BIT2; // SMCLK set out to pins
P2SEL |= BIT2;
P7DIR |= BIT7; // MCLK set out to pins
P7SEL |= BIT7;
P5SEL |= BIT2+BIT3; // Port select XT2
UCSCTL6 |= XT2BYPASS;
//UCSCTL6 &= ~XT2OFF;
//UCSCTL6 |= XT1OFF;

do {

//UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
UCSCTL7 &= ~(XT2OFFG);
// Clear XT2,XT1,DCO fault flags
//SFRIFG1 &= ~OFIFG; // Clear fault flags

__delay_cycles(10000);

//}while (SFRIFG1&OFIFG); // Test oscillator fault flag
}while (UCSCTL7&XT2OFFG);

UCSCTL5 = 0x0000; // divide by 1
UCSCTL4 = SELA_5 + SELS_5 + SELM_5;

while(1);

}

void SetVCoreUp(unsigned int level)
{
// Open PMM registers for write
PMMCTL0_H = PMMPW_H;
// Set SVS/SVM high side new level
SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
// Set SVM low side to new level
SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
// Wait till SVM is settled
while ((PMMIFG & SVSMLDLYIFG) == 0);
// Clear already set flags
PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
// Set VCore to new level
PMMCTL0_L = PMMCOREV0 * level;
// Wait till new level reached
if ((PMMIFG & SVMLIFG))
while ((PMMIFG & SVMLVLRIFG) == 0);
// Set SVS/SVM low side to new level
SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
// Lock PMM registers for write access
PMMCTL0_H = 0x00;
}

Code that does not work: (i.e. falls back to DCO)
#include "msp430f5529.h"

void SetVCoreUp(unsigned int level);

volatile unsigned int i;
unsigned int level1 = 1;
unsigned int level2 = 2;
unsigned int level3 = 3;
//#include
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

SetVCoreUp(level1);
SetVCoreUp(level2);
SetVCoreUp(level3);

P2DIR |= BIT2; // SMCLK set out to pins
P2SEL |= BIT2;
P7DIR |= BIT7; // MCLK set out to pins
P7SEL |= BIT7;

P5SEL &= ~BIT1; // P5.1 set as I/O
P5DIR |= BIT1; // P5.1 as output (LED1)
P5REN &= ~BIT1; // Disable pullup/pulldown resistor

P5SEL |= BIT2+BIT3; // Port select XT2
UCSCTL6 |= XT2BYPASS;
//UCSCTL6 &= ~XT2OFF;
//UCSCTL6 |= XT1OFF;

do {
UCSCTL7 &= ~(XT2OFFG); // Clear XT2,XT1,DCO fault flags
__delay_cycles(10000);

}while (UCSCTL7&XT2OFFG);

UCSCTL5 = 0x0000; // divide by 1
UCSCTL4 = SELA_5 + SELS_5 + SELM_5;

TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
TBCCR0 = 50000; // counts to 50000
TBCTL = TBSSEL_2 +MC_1 + TBCLR;

__bis_SR_register(GIE);
while(1);

}
#pragma vector=TIMERB0_VECTOR
__interrupt void TIMERB0_ISR (void)
{
P5OUT = 0x00;
P5OUT = 0x02;
}
void SetVCoreUp(unsigned int level)
{
// Open PMM registers for write
PMMCTL0_H = PMMPW_H;
// Set SVS/SVM high side new level
SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
// Set SVM low side to new level
SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
// Wait till SVM is settled
while ((PMMIFG & SVSMLDLYIFG) == 0);
// Clear already set flags
PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
// Set VCore to new level
PMMCTL0_L = PMMCOREV0 * level;
// Wait till new level reached
if ((PMMIFG & SVMLIFG))
while ((PMMIFG & SVMLVLRIFG) == 0);
// Set SVS/SVM low side to new level
SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
// Lock PMM registers for write access
PMMCTL0_H = 0x00;
}

--- In m..., "Ctoad" wrote:
>
>
>
> More Info:
>
> Examination of UCSCTL7 in debug shows the fault flags set for XT1LFOFFG and DCOFFG and clear for XT2OFFG, so XT1 and DCO seem to be the osc faults holding the MSP in the osc fault ISR. This is with the instruction UCSCTL6 |= XT1OFF; in the config code. Maybe we're doing something wrong in config of DCO, but we've turned off XT1. How can it be holding the chip in fault condition if it is turned off?
>
> --- In m..., "Ctoad" wrote:
> >
> > Our app needs low jitter and low temp drift in timing so we are using an external clock source. The MSP430 keeps detecting osc fault condition and switching back to the default internal source. This is my first MSP430 project, so I'm hoping that I'm making some simple mistake which the group can point out. Some specifics are:
> >
> > Clock is Connor Winfield model D75A at 20 MHz. We buffer it through a 74LVC04 before it goes to the MSP430.
> >
> > I'm using the MSP4305529. VCC = 3.5 V. Using the FET-430UIF and ccs v 4.2.5.0005 on a macbook pro 2011 running parallels desktop emulating Win XP 64 bit.
> >
> > The code listed below ramps up vcore to level 3, sets XT2 to bypass, outputs MCLK and SMCLK to port pins for monitoring, sets a timer interrupt to provide a heartbeat signal to show the code is running, and has an ISR for osc fault condition where it sets the ck source back to XT2 bypass. The debug version of the code shows it spends all of it's time in the osc ISR waiting for the fault flag to stay clear.
> >
> > Things I've tried:
> > 1. Running ccs on a real Windows XP pro machine with identical results.
> > 2. Running the code with the internal osc selected to confirm proper operation of the timer ISR with the heartbeat signal.
> > 3. Running a release version of the code with the FET430 removed from the circuit - the power supply connection to it is noisy.
> > 4. Adding 10 uF tant, 5 uF poly and .1 uF ceramic to power supply.
> > 5. Dead bugging a schmitt trig buffer (74LVC1G17) on top of the MSP at XT2 input to better buffer the ck source (and bypassing this buffer power using a 1 uF and .1 uF ceramic caps).
> > 6. Different external power supply.
> > 7. New FET430 (to get rid of power noise - didn't help).
> > 8. .47 uF ceramic on vcore pin. Confirmed vcore using voltmeter and scope.
> > 9. Triple checking the JTAG interface (SLAU138L fig3.2).
> >
> > The ext ck signal, even after buffering, does not look as good as I'd like, but it is not bad. There are over/undershoots of about 600 mV lasting for about 8 ns, but they are rounded and there is no ringing. The MSP MCLK output when running off of internal osc shows the same level and duration of over/undershoot, but with some ringing - likely due to unterminated pin on MCLK output.
> >
> > I've read that the MSP430 is very quick to call osc fault on an external source, but this seems ridiculous. I have to be doing something simple and wrong in the code. Any suggestions will be much appreciated.
> >
> > Code:
> >
> > #include "msp430f5529.h"
> >
> > void SetVCoreUp(unsigned int level);
> >
> > volatile unsigned int i;
> > unsigned int level1 = 1;
> > unsigned int level2 = 2;
> > unsigned int level3 = 3;
> > //#include
> > int main(void)
> > {
> > WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
> >
> > SetVCoreUp(level1);
> > SetVCoreUp(level2);
> > SetVCoreUp(level3);
> >
> > P5SEL |= BIT2+BIT3; // Port select XT2
> > UCSCTL6 |= XT2BYPASS;
> >
> > UCSCTL6 &= ~XT2OFF; //enable xt2
> > UCSCTL6 &= SELREF_5;
> >
> > SFRIE1 |= OFIE; // enables oscillator fault interrupt
> >
> > UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT2
> > //UCSCTL5 &= ~(DIVM_0+DIVM_1+DIVM_2); // set MCLK divider to 1 for 20MHz
> >
> > //Show clocks on output pins
> > P2DIR |= BIT2; // SMCLK set out to pins
> > P2SEL |= BIT2;
> > P7DIR |= BIT7; // MCLK set out to pins
> > P7SEL |= BIT7;
> >
> > P5SEL &= ~BIT1; // P5.1 set as I/O
> > P5DIR |= BIT1; // P5.1 as output (LED1)
> > P5REN &= ~BIT1; // Disable pullup/pulldown resistor
> >
> >
> >
> >
> > __bis_SR_register(GIE);
> >
> >
> > UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT2
> >
> > TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
> > TBCCR0 = 50000; // counts to 50000
> > TBCTL = TBSSEL_2 +MC_1 + TBCLR; // System heartbeat output in ISR.
> >
> > while(1);
> >
> > }
> >
> > // Timer B0 interrupt service routine
> > #pragma vector=TIMERB0_VECTOR
> > __interrupt void TIMERB0_ISR (void)
> > {
> > P5OUT = 0x00; // heartbeat output on P5.1
> > P5OUT = 0x02;
> > P5OUT = 0x00;
> > P5OUT = 0x02;
> > }
> >
> > #pragma vector=UNMI_VECTOR
> > __interrupt void UNMI_ISR (void) // On osc fault, put it back to XT2
> > {
> > do {
> > P5SEL |= BIT2+BIT3; // Port select XT2
> > UCSCTL6 |= XT2BYPASS;
> >
> > UCSCTL6 &= ~XT2OFF; //enable xt2
> > UCSCTL6 &= SELREF_5;
> >
> >
> > UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
> > // Clear XT2,XT1,DCO fault flags
> > SFRIFG1 &= ~OFIFG; // Clear fault flags
> > // for (i = 0xFFF;i>0;i--); // Delay
> >
> > }
> > while (SFRIFG1&OFIFG); // Test oscillator fault flag
> >
> > SFRIE1 |= OFIE; // enables oscillator fault interrupt
> > }
> >
> > void SetVCoreUp(unsigned int level)
> > {
> > // Open PMM registers for write
> > PMMCTL0_H = PMMPW_H;
> > // Set SVS/SVM high side new level
> > SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
> > // Set SVM low side to new level
> > SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
> > // Wait till SVM is settled
> > while ((PMMIFG & SVSMLDLYIFG) == 0);
> > // Clear already set flags
> > PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
> > // Set VCore to new level
> > PMMCTL0_L = PMMCOREV0 * level;
> > // Wait till new level reached
> > if ((PMMIFG & SVMLIFG))
> > while ((PMMIFG & SVMLVLRIFG) == 0);
> > // Set SVS/SVM low side to new level
> > SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
> > // Lock PMM registers for write access
> > PMMCTL0_H = 0x00;
> > }
> >
>



One more line added and reordered again:

Change the order of these lines:

TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
TBCCR0 = 50000; // counts to 50000
TBCTL = TBSSEL_2 +MC_1 + TBCLR;

to

TBCTL = TBSSEL_2 +MC_1 + TBCLR;
TBCCTL0 &= ~(CCIE | CCIFG); // Clear any Timer B0 pending interrupt
TBCCR0 = 50000; // counts to 50000
TBCCTL0 = CCIE; // TBCCR0 interrupt enabled

----- Original Message -----
From: Ctoad
To: m...
Sent: Thursday, March 29, 2012 14:36
Subject: [msp430] Re: MSP430 External Clock Problem

And more info:

We tried cutting it down to the simplest code possible. It works, MCLK = 20 MHz from the external clock. We then added a simple timer int and ISR and it is back to broken with MCLK coming from DCO. Code pasted below. Am really pulling hair out on this one and don't have that much left. Any suggestions very welcome.

Code that works:
#include "msp430f5529.h"

void SetVCoreUp(unsigned int level);

volatile unsigned int i;
unsigned int level1 = 1;
unsigned int level2 = 2;
unsigned int level3 = 3;
//#include
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

SetVCoreUp(level1);
SetVCoreUp(level2);
SetVCoreUp(level3);

P2DIR |= BIT2; // SMCLK set out to pins
P2SEL |= BIT2;
P7DIR |= BIT7; // MCLK set out to pins
P7SEL |= BIT7;
P5SEL |= BIT2+BIT3; // Port select XT2
UCSCTL6 |= XT2BYPASS;
//UCSCTL6 &= ~XT2OFF;
//UCSCTL6 |= XT1OFF;

do {

//UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
UCSCTL7 &= ~(XT2OFFG);
// Clear XT2,XT1,DCO fault flags
//SFRIFG1 &= ~OFIFG; // Clear fault flags

__delay_cycles(10000);

//}while (SFRIFG1&OFIFG); // Test oscillator fault flag
}while (UCSCTL7&XT2OFFG);

UCSCTL5 = 0x0000; // divide by 1
UCSCTL4 = SELA_5 + SELS_5 + SELM_5;

while(1);

}

void SetVCoreUp(unsigned int level)
{
// Open PMM registers for write
PMMCTL0_H = PMMPW_H;
// Set SVS/SVM high side new level
SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
// Set SVM low side to new level
SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
// Wait till SVM is settled
while ((PMMIFG & SVSMLDLYIFG) == 0);
// Clear already set flags
PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
// Set VCore to new level
PMMCTL0_L = PMMCOREV0 * level;
// Wait till new level reached
if ((PMMIFG & SVMLIFG))
while ((PMMIFG & SVMLVLRIFG) == 0);
// Set SVS/SVM low side to new level
SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
// Lock PMM registers for write access
PMMCTL0_H = 0x00;
}

Code that does not work: (i.e. falls back to DCO)
#include "msp430f5529.h"

void SetVCoreUp(unsigned int level);

volatile unsigned int i;
unsigned int level1 = 1;
unsigned int level2 = 2;
unsigned int level3 = 3;
//#include
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

SetVCoreUp(level1);
SetVCoreUp(level2);
SetVCoreUp(level3);

P2DIR |= BIT2; // SMCLK set out to pins
P2SEL |= BIT2;
P7DIR |= BIT7; // MCLK set out to pins
P7SEL |= BIT7;

P5SEL &= ~BIT1; // P5.1 set as I/O
P5DIR |= BIT1; // P5.1 as output (LED1)
P5REN &= ~BIT1; // Disable pullup/pulldown resistor

P5SEL |= BIT2+BIT3; // Port select XT2
UCSCTL6 |= XT2BYPASS;
//UCSCTL6 &= ~XT2OFF;
//UCSCTL6 |= XT1OFF;

do {
UCSCTL7 &= ~(XT2OFFG); // Clear XT2,XT1,DCO fault flags
__delay_cycles(10000);

}while (UCSCTL7&XT2OFFG);

UCSCTL5 = 0x0000; // divide by 1
UCSCTL4 = SELA_5 + SELS_5 + SELM_5;

TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
TBCCR0 = 50000; // counts to 50000
TBCTL = TBSSEL_2 +MC_1 + TBCLR;

__bis_SR_register(GIE);
while(1);

}
#pragma vector=TIMERB0_VECTOR
__interrupt void TIMERB0_ISR (void)
{
P5OUT = 0x00;
P5OUT = 0x02;
}
void SetVCoreUp(unsigned int level)
{
// Open PMM registers for write
PMMCTL0_H = PMMPW_H;
// Set SVS/SVM high side new level
SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
// Set SVM low side to new level
SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
// Wait till SVM is settled
while ((PMMIFG & SVSMLDLYIFG) == 0);
// Clear already set flags
PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
// Set VCore to new level
PMMCTL0_L = PMMCOREV0 * level;
// Wait till new level reached
if ((PMMIFG & SVMLIFG))
while ((PMMIFG & SVMLVLRIFG) == 0);
// Set SVS/SVM low side to new level
SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
// Lock PMM registers for write access
PMMCTL0_H = 0x00;
}

--- In m..., "Ctoad" wrote:
>
>
>
> More Info:
>
> Examination of UCSCTL7 in debug shows the fault flags set for XT1LFOFFG and DCOFFG and clear for XT2OFFG, so XT1 and DCO seem to be the osc faults holding the MSP in the osc fault ISR. This is with the instruction UCSCTL6 |= XT1OFF; in the config code. Maybe we're doing something wrong in config of DCO, but we've turned off XT1. How can it be holding the chip in fault condition if it is turned off?
>
> --- In m..., "Ctoad" wrote:
> >
> > Our app needs low jitter and low temp drift in timing so we are using an external clock source. The MSP430 keeps detecting osc fault condition and switching back to the default internal source. This is my first MSP430 project, so I'm hoping that I'm making some simple mistake which the group can point out. Some specifics are:
> >
> > Clock is Connor Winfield model D75A at 20 MHz. We buffer it through a 74LVC04 before it goes to the MSP430.
> >
> > I'm using the MSP4305529. VCC = 3.5 V. Using the FET-430UIF and ccs v 4.2.5.0005 on a macbook pro 2011 running parallels desktop emulating Win XP 64 bit.
> >
> > The code listed below ramps up vcore to level 3, sets XT2 to bypass, outputs MCLK and SMCLK to port pins for monitoring, sets a timer interrupt to provide a heartbeat signal to show the code is running, and has an ISR for osc fault condition where it sets the ck source back to XT2 bypass. The debug version of the code shows it spends all of it's time in the osc ISR waiting for the fault flag to stay clear.
> >
> > Things I've tried:
> > 1. Running ccs on a real Windows XP pro machine with identical results.
> > 2. Running the code with the internal osc selected to confirm proper operation of the timer ISR with the heartbeat signal.
> > 3. Running a release version of the code with the FET430 removed from the circuit - the power supply connection to it is noisy.
> > 4. Adding 10 uF tant, 5 uF poly and .1 uF ceramic to power supply.
> > 5. Dead bugging a schmitt trig buffer (74LVC1G17) on top of the MSP at XT2 input to better buffer the ck source (and bypassing this buffer power using a 1 uF and .1 uF ceramic caps).
> > 6. Different external power supply.
> > 7. New FET430 (to get rid of power noise - didn't help).
> > 8. .47 uF ceramic on vcore pin. Confirmed vcore using voltmeter and scope.
> > 9. Triple checking the JTAG interface (SLAU138L fig3.2).
> >
> > The ext ck signal, even after buffering, does not look as good as I'd like, but it is not bad. There are over/undershoots of about 600 mV lasting for about 8 ns, but they are rounded and there is no ringing. The MSP MCLK output when running off of internal osc shows the same level and duration of over/undershoot, but with some ringing - likely due to unterminated pin on MCLK output.
> >
> > I've read that the MSP430 is very quick to call osc fault on an external source, but this seems ridiculous. I have to be doing something simple and wrong in the code. Any suggestions will be much appreciated.
> >
> > Code:
> >
> > #include "msp430f5529.h"
> >
> > void SetVCoreUp(unsigned int level);
> >
> > volatile unsigned int i;
> > unsigned int level1 = 1;
> > unsigned int level2 = 2;
> > unsigned int level3 = 3;
> > //#include
> > int main(void)
> > {
> > WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
> >
> > SetVCoreUp(level1);
> > SetVCoreUp(level2);
> > SetVCoreUp(level3);
> >
> > P5SEL |= BIT2+BIT3; // Port select XT2
> > UCSCTL6 |= XT2BYPASS;
> >
> > UCSCTL6 &= ~XT2OFF; //enable xt2
> > UCSCTL6 &= SELREF_5;
> >
> > SFRIE1 |= OFIE; // enables oscillator fault interrupt
> >
> > UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT2
> > //UCSCTL5 &= ~(DIVM_0+DIVM_1+DIVM_2); // set MCLK divider to 1 for 20MHz
> >
> > //Show clocks on output pins
> > P2DIR |= BIT2; // SMCLK set out to pins
> > P2SEL |= BIT2;
> > P7DIR |= BIT7; // MCLK set out to pins
> > P7SEL |= BIT7;
> >
> > P5SEL &= ~BIT1; // P5.1 set as I/O
> > P5DIR |= BIT1; // P5.1 as output (LED1)
> > P5REN &= ~BIT1; // Disable pullup/pulldown resistor
> >
> >
> >
> >
> > __bis_SR_register(GIE);
> >
> >
> > UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT2
> >
> > TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
> > TBCCR0 = 50000; // counts to 50000
> > TBCTL = TBSSEL_2 +MC_1 + TBCLR; // System heartbeat output in ISR.
> >
> > while(1);
> >
> > }
> >
> > // Timer B0 interrupt service routine
> > #pragma vector=TIMERB0_VECTOR
> > __interrupt void TIMERB0_ISR (void)
> > {
> > P5OUT = 0x00; // heartbeat output on P5.1
> > P5OUT = 0x02;
> > P5OUT = 0x00;
> > P5OUT = 0x02;
> > }
> >
> > #pragma vector=UNMI_VECTOR
> > __interrupt void UNMI_ISR (void) // On osc fault, put it back to XT2
> > {
> > do {
> > P5SEL |= BIT2+BIT3; // Port select XT2
> > UCSCTL6 |= XT2BYPASS;
> >
> > UCSCTL6 &= ~XT2OFF; //enable xt2
> > UCSCTL6 &= SELREF_5;
> >
> >
> > UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
> > // Clear XT2,XT1,DCO fault flags
> > SFRIFG1 &= ~OFIFG; // Clear fault flags
> > // for (i = 0xFFF;i>0;i--); // Delay
> >
> > }
> > while (SFRIFG1&OFIFG); // Test oscillator fault flag
> >
> > SFRIE1 |= OFIE; // enables oscillator fault interrupt
> > }
> >
> > void SetVCoreUp(unsigned int level)
> > {
> > // Open PMM registers for write
> > PMMCTL0_H = PMMPW_H;
> > // Set SVS/SVM high side new level
> > SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
> > // Set SVM low side to new level
> > SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
> > // Wait till SVM is settled
> > while ((PMMIFG & SVSMLDLYIFG) == 0);
> > // Clear already set flags
> > PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
> > // Set VCore to new level
> > PMMCTL0_L = PMMCOREV0 * level;
> > // Wait till new level reached
> > if ((PMMIFG & SVMLIFG))
> > while ((PMMIFG & SVMLVLRIFG) == 0);
> > // Set SVS/SVM low side to new level
> > SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
> > // Lock PMM registers for write access
> > PMMCTL0_H = 0x00;
> > }
> >
>



Thanks Steve. Sometimes the simple problems are the hardest to find. For posterity, the working code for MSP430F5520 using external clock source on XT2:

#include "msp430f5529.h"

void SetVCoreUp(unsigned int level);

volatile unsigned int i;
unsigned int level1 = 1;
unsigned int level2 = 2;
unsigned int level3 = 3;
//#include
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

SetVCoreUp(level1);
SetVCoreUp(level2);
SetVCoreUp(level3);

P2DIR |= BIT2; // SMCLK set out to pins
P2SEL |= BIT2;
P7DIR |= BIT7; // MCLK set out to pins
P7SEL |= BIT7;

P5SEL |= BIT7; // P5.7 set as I/O
P5DIR |= BIT7; // P5.7 as output (PWM)
//P5REN &= ~BIT1; // Disable pullup/pulldown resistor

P5SEL |= BIT2+BIT3; // Port select XT2
UCSCTL6 |= XT2BYPASS;
UCSCTL6 &= ~XT2OFF; //enables xt2
//UCSCTL6 |= XT1OFF;

do {
UCSCTL7 &= ~(XT2OFFG); // Clear XT2,XT1,DCO fault flags
__delay_cycles(10000);

}while (UCSCTL7&XT2OFFG);

UCSCTL5 = 0x0000; // divide by 1
UCSCTL4 = SELA_5 + SELS_5 + SELM_5;

TBCCR0 = 4000; //PWM period
TBCCTL1 = OUTMOD_7; //reset/set
TBCCR1 = 2000; //50% duty cycle
TBCTL = TBSSEL_2 +MC_1;

__bis_SR_register(GIE);

while(1);

}

void SetVCoreUp(unsigned int level)
{
// Open PMM registers for write
PMMCTL0_H = PMMPW_H;
// Set SVS/SVM high side new level
SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
// Set SVM low side to new level
SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
// Wait till SVM is settled
while ((PMMIFG & SVSMLDLYIFG) == 0);
// Clear already set flags
PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
// Set VCore to new level
PMMCTL0_L = PMMCOREV0 * level;
// Wait till new level reached
if ((PMMIFG & SVMLIFG))
while ((PMMIFG & SVMLVLRIFG) == 0);
// Set SVS/SVM low side to new level
SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
// Lock PMM registers for write access
PMMCTL0_H = 0x00;
}
--- In m..., "Steve Mayfield" wrote:
>
> One more line added and reordered again:
>
> Change the order of these lines:
>
> TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
> TBCCR0 = 50000; // counts to 50000
> TBCTL = TBSSEL_2 +MC_1 + TBCLR;
>
> to
>
> TBCTL = TBSSEL_2 +MC_1 + TBCLR;
> TBCCTL0 &= ~(CCIE | CCIFG); // Clear any Timer B0 pending interrupt
> TBCCR0 = 50000; // counts to 50000
> TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
> ----- Original Message -----
> From: Ctoad
> To: m...
> Sent: Thursday, March 29, 2012 14:36
> Subject: [msp430] Re: MSP430 External Clock Problem
>
> And more info:
>
> We tried cutting it down to the simplest code possible. It works, MCLK = 20 MHz from the external clock. We then added a simple timer int and ISR and it is back to broken with MCLK coming from DCO. Code pasted below. Am really pulling hair out on this one and don't have that much left. Any suggestions very welcome.
>
> Code that works:
> #include "msp430f5529.h"
>
> void SetVCoreUp(unsigned int level);
>
> volatile unsigned int i;
> unsigned int level1 = 1;
> unsigned int level2 = 2;
> unsigned int level3 = 3;
> //#include
> int main(void)
> {
> WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
>
> SetVCoreUp(level1);
> SetVCoreUp(level2);
> SetVCoreUp(level3);
>
> P2DIR |= BIT2; // SMCLK set out to pins
> P2SEL |= BIT2;
> P7DIR |= BIT7; // MCLK set out to pins
> P7SEL |= BIT7;
> P5SEL |= BIT2+BIT3; // Port select XT2
> UCSCTL6 |= XT2BYPASS;
> //UCSCTL6 &= ~XT2OFF;
> //UCSCTL6 |= XT1OFF;
>
> do {
>
> //UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
> UCSCTL7 &= ~(XT2OFFG);
> // Clear XT2,XT1,DCO fault flags
> //SFRIFG1 &= ~OFIFG; // Clear fault flags
>
> __delay_cycles(10000);
>
> //}while (SFRIFG1&OFIFG); // Test oscillator fault flag
> }while (UCSCTL7&XT2OFFG);
>
> UCSCTL5 = 0x0000; // divide by 1
> UCSCTL4 = SELA_5 + SELS_5 + SELM_5;
>
> while(1);
>
> }
>
> void SetVCoreUp(unsigned int level)
> {
> // Open PMM registers for write
> PMMCTL0_H = PMMPW_H;
> // Set SVS/SVM high side new level
> SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
> // Set SVM low side to new level
> SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
> // Wait till SVM is settled
> while ((PMMIFG & SVSMLDLYIFG) == 0);
> // Clear already set flags
> PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
> // Set VCore to new level
> PMMCTL0_L = PMMCOREV0 * level;
> // Wait till new level reached
> if ((PMMIFG & SVMLIFG))
> while ((PMMIFG & SVMLVLRIFG) == 0);
> // Set SVS/SVM low side to new level
> SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
> // Lock PMM registers for write access
> PMMCTL0_H = 0x00;
> }
>
> Code that does not work: (i.e. falls back to DCO)
> #include "msp430f5529.h"
>
> void SetVCoreUp(unsigned int level);
>
> volatile unsigned int i;
> unsigned int level1 = 1;
> unsigned int level2 = 2;
> unsigned int level3 = 3;
> //#include
> int main(void)
> {
> WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
>
> SetVCoreUp(level1);
> SetVCoreUp(level2);
> SetVCoreUp(level3);
>
> P2DIR |= BIT2; // SMCLK set out to pins
> P2SEL |= BIT2;
> P7DIR |= BIT7; // MCLK set out to pins
> P7SEL |= BIT7;
>
> P5SEL &= ~BIT1; // P5.1 set as I/O
> P5DIR |= BIT1; // P5.1 as output (LED1)
> P5REN &= ~BIT1; // Disable pullup/pulldown resistor
>
> P5SEL |= BIT2+BIT3; // Port select XT2
> UCSCTL6 |= XT2BYPASS;
> //UCSCTL6 &= ~XT2OFF;
> //UCSCTL6 |= XT1OFF;
>
> do {
> UCSCTL7 &= ~(XT2OFFG); // Clear XT2,XT1,DCO fault flags
> __delay_cycles(10000);
>
> }while (UCSCTL7&XT2OFFG);
>
> UCSCTL5 = 0x0000; // divide by 1
> UCSCTL4 = SELA_5 + SELS_5 + SELM_5;
>
> TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
> TBCCR0 = 50000; // counts to 50000
> TBCTL = TBSSEL_2 +MC_1 + TBCLR;
>
> __bis_SR_register(GIE);
> while(1);
>
> }
> #pragma vector=TIMERB0_VECTOR
> __interrupt void TIMERB0_ISR (void)
> {
> P5OUT = 0x00;
> P5OUT = 0x02;
> }
> void SetVCoreUp(unsigned int level)
> {
> // Open PMM registers for write
> PMMCTL0_H = PMMPW_H;
> // Set SVS/SVM high side new level
> SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
> // Set SVM low side to new level
> SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
> // Wait till SVM is settled
> while ((PMMIFG & SVSMLDLYIFG) == 0);
> // Clear already set flags
> PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
> // Set VCore to new level
> PMMCTL0_L = PMMCOREV0 * level;
> // Wait till new level reached
> if ((PMMIFG & SVMLIFG))
> while ((PMMIFG & SVMLVLRIFG) == 0);
> // Set SVS/SVM low side to new level
> SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
> // Lock PMM registers for write access
> PMMCTL0_H = 0x00;
> }
>
> --- In m..., "Ctoad" wrote:
> >
> >
> >
> > More Info:
> >
> > Examination of UCSCTL7 in debug shows the fault flags set for XT1LFOFFG and DCOFFG and clear for XT2OFFG, so XT1 and DCO seem to be the osc faults holding the MSP in the osc fault ISR. This is with the instruction UCSCTL6 |= XT1OFF; in the config code. Maybe we're doing something wrong in config of DCO, but we've turned off XT1. How can it be holding the chip in fault condition if it is turned off?
> >
> > --- In m..., "Ctoad" wrote:
> > >
> > > Our app needs low jitter and low temp drift in timing so we are using an external clock source. The MSP430 keeps detecting osc fault condition and switching back to the default internal source. This is my first MSP430 project, so I'm hoping that I'm making some simple mistake which the group can point out. Some specifics are:
> > >
> > > Clock is Connor Winfield model D75A at 20 MHz. We buffer it through a 74LVC04 before it goes to the MSP430.
> > >
> > > I'm using the MSP4305529. VCC = 3.5 V. Using the FET-430UIF and ccs v 4.2.5.0005 on a macbook pro 2011 running parallels desktop emulating Win XP 64 bit.
> > >
> > > The code listed below ramps up vcore to level 3, sets XT2 to bypass, outputs MCLK and SMCLK to port pins for monitoring, sets a timer interrupt to provide a heartbeat signal to show the code is running, and has an ISR for osc fault condition where it sets the ck source back to XT2 bypass. The debug version of the code shows it spends all of it's time in the osc ISR waiting for the fault flag to stay clear.
> > >
> > > Things I've tried:
> > > 1. Running ccs on a real Windows XP pro machine with identical results.
> > > 2. Running the code with the internal osc selected to confirm proper operation of the timer ISR with the heartbeat signal.
> > > 3. Running a release version of the code with the FET430 removed from the circuit - the power supply connection to it is noisy.
> > > 4. Adding 10 uF tant, 5 uF poly and .1 uF ceramic to power supply.
> > > 5. Dead bugging a schmitt trig buffer (74LVC1G17) on top of the MSP at XT2 input to better buffer the ck source (and bypassing this buffer power using a 1 uF and .1 uF ceramic caps).
> > > 6. Different external power supply.
> > > 7. New FET430 (to get rid of power noise - didn't help).
> > > 8. .47 uF ceramic on vcore pin. Confirmed vcore using voltmeter and scope.
> > > 9. Triple checking the JTAG interface (SLAU138L fig3.2).
> > >
> > > The ext ck signal, even after buffering, does not look as good as I'd like, but it is not bad. There are over/undershoots of about 600 mV lasting for about 8 ns, but they are rounded and there is no ringing. The MSP MCLK output when running off of internal osc shows the same level and duration of over/undershoot, but with some ringing - likely due to unterminated pin on MCLK output.
> > >
> > > I've read that the MSP430 is very quick to call osc fault on an external source, but this seems ridiculous. I have to be doing something simple and wrong in the code. Any suggestions will be much appreciated.
> > >
> > > Code:
> > >
> > > #include "msp430f5529.h"
> > >
> > > void SetVCoreUp(unsigned int level);
> > >
> > > volatile unsigned int i;
> > > unsigned int level1 = 1;
> > > unsigned int level2 = 2;
> > > unsigned int level3 = 3;
> > > //#include
> > > int main(void)
> > > {
> > > WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
> > >
> > > SetVCoreUp(level1);
> > > SetVCoreUp(level2);
> > > SetVCoreUp(level3);
> > >
> > > P5SEL |= BIT2+BIT3; // Port select XT2
> > > UCSCTL6 |= XT2BYPASS;
> > >
> > > UCSCTL6 &= ~XT2OFF; //enable xt2
> > > UCSCTL6 &= SELREF_5;
> > >
> > > SFRIE1 |= OFIE; // enables oscillator fault interrupt
> > >
> > > UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT2
> > > //UCSCTL5 &= ~(DIVM_0+DIVM_1+DIVM_2); // set MCLK divider to 1 for 20MHz
> > >
> > > //Show clocks on output pins
> > > P2DIR |= BIT2; // SMCLK set out to pins
> > > P2SEL |= BIT2;
> > > P7DIR |= BIT7; // MCLK set out to pins
> > > P7SEL |= BIT7;
> > >
> > > P5SEL &= ~BIT1; // P5.1 set as I/O
> > > P5DIR |= BIT1; // P5.1 as output (LED1)
> > > P5REN &= ~BIT1; // Disable pullup/pulldown resistor
> > >
> > >
> > >
> > >
> > > __bis_SR_register(GIE);
> > >
> > >
> > > UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT2
> > >
> > > TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
> > > TBCCR0 = 50000; // counts to 50000
> > > TBCTL = TBSSEL_2 +MC_1 + TBCLR; // System heartbeat output in ISR.
> > >
> > > while(1);
> > >
> > > }
> > >
> > > // Timer B0 interrupt service routine
> > > #pragma vector=TIMERB0_VECTOR
> > > __interrupt void TIMERB0_ISR (void)
> > > {
> > > P5OUT = 0x00; // heartbeat output on P5.1
> > > P5OUT = 0x02;
> > > P5OUT = 0x00;
> > > P5OUT = 0x02;
> > > }
> > >
> > > #pragma vector=UNMI_VECTOR
> > > __interrupt void UNMI_ISR (void) // On osc fault, put it back to XT2
> > > {
> > > do {
> > > P5SEL |= BIT2+BIT3; // Port select XT2
> > > UCSCTL6 |= XT2BYPASS;
> > >
> > > UCSCTL6 &= ~XT2OFF; //enable xt2
> > > UCSCTL6 &= SELREF_5;
> > >
> > >
> > > UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
> > > // Clear XT2,XT1,DCO fault flags
> > > SFRIFG1 &= ~OFIFG; // Clear fault flags
> > > // for (i = 0xFFF;i>0;i--); // Delay
> > >
> > > }
> > > while (SFRIFG1&OFIFG); // Test oscillator fault flag
> > >
> > > SFRIE1 |= OFIE; // enables oscillator fault interrupt
> > > }
> > >
> > > void SetVCoreUp(unsigned int level)
> > > {
> > > // Open PMM registers for write
> > > PMMCTL0_H = PMMPW_H;
> > > // Set SVS/SVM high side new level
> > > SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
> > > // Set SVM low side to new level
> > > SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
> > > // Wait till SVM is settled
> > > while ((PMMIFG & SVSMLDLYIFG) == 0);
> > > // Clear already set flags
> > > PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
> > > // Set VCore to new level
> > > PMMCTL0_L = PMMCOREV0 * level;
> > > // Wait till new level reached
> > > if ((PMMIFG & SVMLIFG))
> > > while ((PMMIFG & SVMLVLRIFG) == 0);
> > > // Set SVS/SVM low side to new level
> > > SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
> > > // Lock PMM registers for write access
> > > PMMCTL0_H = 0x00;
> > > }
> > >
> >
>
>
>

Unfortunately, the problem persists with flaky operation. Sometimes works and starts with external ck and sometimes defaults to internal, and sometimes rapidly switches between the two. It seems like a noise problem, but on a 2 x 4 inch board we've got 133 uF of distributed tants, 50 uF of distributed ceramics, .1 uF bypasses on each chip, and also just dead bugged 22 uF ceramics on the power of the MSP430, the ck buffer and the ext ck chip. Tried switching to different external PS.

Eventually found the fault. Replaced with dsPIC33FJ128GP708A, an now the system operates completely stable and precise using the external ck chip. Problem solved.
--- In m..., "Ctoad" wrote:
>
> Thanks Steve. Sometimes the simple problems are the hardest to find. For posterity, the working code for MSP430F5520 using external clock source on XT2:
>
> #include "msp430f5529.h"
>
> void SetVCoreUp(unsigned int level);
>
> volatile unsigned int i;
> unsigned int level1 = 1;
> unsigned int level2 = 2;
> unsigned int level3 = 3;
> //#include
> int main(void)
> {
> WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
>
> SetVCoreUp(level1);
> SetVCoreUp(level2);
> SetVCoreUp(level3);
>
> P2DIR |= BIT2; // SMCLK set out to pins
> P2SEL |= BIT2;
> P7DIR |= BIT7; // MCLK set out to pins
> P7SEL |= BIT7;
>
> P5SEL |= BIT7; // P5.7 set as I/O
> P5DIR |= BIT7; // P5.7 as output (PWM)
> //P5REN &= ~BIT1; // Disable pullup/pulldown resistor
>
> P5SEL |= BIT2+BIT3; // Port select XT2
> UCSCTL6 |= XT2BYPASS;
> UCSCTL6 &= ~XT2OFF; //enables xt2
> //UCSCTL6 |= XT1OFF;
>
> do {
> UCSCTL7 &= ~(XT2OFFG); // Clear XT2,XT1,DCO fault flags
> __delay_cycles(10000);
>
> }while (UCSCTL7&XT2OFFG);
>
>
> UCSCTL5 = 0x0000; // divide by 1
> UCSCTL4 = SELA_5 + SELS_5 + SELM_5;
>
> TBCCR0 = 4000; //PWM period
> TBCCTL1 = OUTMOD_7; //reset/set
> TBCCR1 = 2000; //50% duty cycle
> TBCTL = TBSSEL_2 +MC_1;
>
> __bis_SR_register(GIE);
>
> while(1);
>
> }
>
> void SetVCoreUp(unsigned int level)
> {
> // Open PMM registers for write
> PMMCTL0_H = PMMPW_H;
> // Set SVS/SVM high side new level
> SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
> // Set SVM low side to new level
> SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
> // Wait till SVM is settled
> while ((PMMIFG & SVSMLDLYIFG) == 0);
> // Clear already set flags
> PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
> // Set VCore to new level
> PMMCTL0_L = PMMCOREV0 * level;
> // Wait till new level reached
> if ((PMMIFG & SVMLIFG))
> while ((PMMIFG & SVMLVLRIFG) == 0);
> // Set SVS/SVM low side to new level
> SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
> // Lock PMM registers for write access
> PMMCTL0_H = 0x00;
> }
> --- In m..., "Steve Mayfield" wrote:
> >
> > One more line added and reordered again:
> >
> > Change the order of these lines:
> >
> > TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
> > TBCCR0 = 50000; // counts to 50000
> > TBCTL = TBSSEL_2 +MC_1 + TBCLR;
> >
> > to
> >
> > TBCTL = TBSSEL_2 +MC_1 + TBCLR;
> > TBCCTL0 &= ~(CCIE | CCIFG); // Clear any Timer B0 pending interrupt
> > TBCCR0 = 50000; // counts to 50000
> > TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
> >
> >
> >
> >
> > ----- Original Message -----
> > From: Ctoad
> > To: m...
> > Sent: Thursday, March 29, 2012 14:36
> > Subject: [msp430] Re: MSP430 External Clock Problem
> >
> >
> >
> > And more info:
> >
> > We tried cutting it down to the simplest code possible. It works, MCLK = 20 MHz from the external clock. We then added a simple timer int and ISR and it is back to broken with MCLK coming from DCO. Code pasted below. Am really pulling hair out on this one and don't have that much left. Any suggestions very welcome.
> >
> > Code that works:
> > #include "msp430f5529.h"
> >
> > void SetVCoreUp(unsigned int level);
> >
> > volatile unsigned int i;
> > unsigned int level1 = 1;
> > unsigned int level2 = 2;
> > unsigned int level3 = 3;
> > //#include
> > int main(void)
> > {
> > WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
> >
> > SetVCoreUp(level1);
> > SetVCoreUp(level2);
> > SetVCoreUp(level3);
> >
> > P2DIR |= BIT2; // SMCLK set out to pins
> > P2SEL |= BIT2;
> > P7DIR |= BIT7; // MCLK set out to pins
> > P7SEL |= BIT7;
> >
> >
> > P5SEL |= BIT2+BIT3; // Port select XT2
> > UCSCTL6 |= XT2BYPASS;
> > //UCSCTL6 &= ~XT2OFF;
> > //UCSCTL6 |= XT1OFF;
> >
> > do {
> >
> > //UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
> > UCSCTL7 &= ~(XT2OFFG);
> > // Clear XT2,XT1,DCO fault flags
> > //SFRIFG1 &= ~OFIFG; // Clear fault flags
> >
> > __delay_cycles(10000);
> >
> > //}while (SFRIFG1&OFIFG); // Test oscillator fault flag
> > }while (UCSCTL7&XT2OFFG);
> >
> > UCSCTL5 = 0x0000; // divide by 1
> > UCSCTL4 = SELA_5 + SELS_5 + SELM_5;
> >
> > while(1);
> >
> > }
> >
> > void SetVCoreUp(unsigned int level)
> > {
> > // Open PMM registers for write
> > PMMCTL0_H = PMMPW_H;
> > // Set SVS/SVM high side new level
> > SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
> > // Set SVM low side to new level
> > SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
> > // Wait till SVM is settled
> > while ((PMMIFG & SVSMLDLYIFG) == 0);
> > // Clear already set flags
> > PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
> > // Set VCore to new level
> > PMMCTL0_L = PMMCOREV0 * level;
> > // Wait till new level reached
> > if ((PMMIFG & SVMLIFG))
> > while ((PMMIFG & SVMLVLRIFG) == 0);
> > // Set SVS/SVM low side to new level
> > SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
> > // Lock PMM registers for write access
> > PMMCTL0_H = 0x00;
> > }
> >
> > Code that does not work: (i.e. falls back to DCO)
> > #include "msp430f5529.h"
> >
> > void SetVCoreUp(unsigned int level);
> >
> > volatile unsigned int i;
> > unsigned int level1 = 1;
> > unsigned int level2 = 2;
> > unsigned int level3 = 3;
> > //#include
> > int main(void)
> > {
> > WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
> >
> > SetVCoreUp(level1);
> > SetVCoreUp(level2);
> > SetVCoreUp(level3);
> >
> > P2DIR |= BIT2; // SMCLK set out to pins
> > P2SEL |= BIT2;
> > P7DIR |= BIT7; // MCLK set out to pins
> > P7SEL |= BIT7;
> >
> > P5SEL &= ~BIT1; // P5.1 set as I/O
> > P5DIR |= BIT1; // P5.1 as output (LED1)
> > P5REN &= ~BIT1; // Disable pullup/pulldown resistor
> >
> > P5SEL |= BIT2+BIT3; // Port select XT2
> > UCSCTL6 |= XT2BYPASS;
> > //UCSCTL6 &= ~XT2OFF;
> > //UCSCTL6 |= XT1OFF;
> >
> > do {
> > UCSCTL7 &= ~(XT2OFFG); // Clear XT2,XT1,DCO fault flags
> > __delay_cycles(10000);
> >
> > }while (UCSCTL7&XT2OFFG);
> >
> > UCSCTL5 = 0x0000; // divide by 1
> > UCSCTL4 = SELA_5 + SELS_5 + SELM_5;
> >
> > TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
> > TBCCR0 = 50000; // counts to 50000
> > TBCTL = TBSSEL_2 +MC_1 + TBCLR;
> >
> > __bis_SR_register(GIE);
> > while(1);
> >
> > }
> > #pragma vector=TIMERB0_VECTOR
> > __interrupt void TIMERB0_ISR (void)
> > {
> > P5OUT = 0x00;
> > P5OUT = 0x02;
> > }
> > void SetVCoreUp(unsigned int level)
> > {
> > // Open PMM registers for write
> > PMMCTL0_H = PMMPW_H;
> > // Set SVS/SVM high side new level
> > SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
> > // Set SVM low side to new level
> > SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
> > // Wait till SVM is settled
> > while ((PMMIFG & SVSMLDLYIFG) == 0);
> > // Clear already set flags
> > PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
> > // Set VCore to new level
> > PMMCTL0_L = PMMCOREV0 * level;
> > // Wait till new level reached
> > if ((PMMIFG & SVMLIFG))
> > while ((PMMIFG & SVMLVLRIFG) == 0);
> > // Set SVS/SVM low side to new level
> > SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
> > // Lock PMM registers for write access
> > PMMCTL0_H = 0x00;
> > }
> >
> > --- In m..., "Ctoad" wrote:
> > >
> > >
> > >
> > > More Info:
> > >
> > > Examination of UCSCTL7 in debug shows the fault flags set for XT1LFOFFG and DCOFFG and clear for XT2OFFG, so XT1 and DCO seem to be the osc faults holding the MSP in the osc fault ISR. This is with the instruction UCSCTL6 |= XT1OFF; in the config code. Maybe we're doing something wrong in config of DCO, but we've turned off XT1. How can it be holding the chip in fault condition if it is turned off?
> > >
> > > --- In m..., "Ctoad" wrote:
> > > >
> > > > Our app needs low jitter and low temp drift in timing so we are using an external clock source. The MSP430 keeps detecting osc fault condition and switching back to the default internal source. This is my first MSP430 project, so I'm hoping that I'm making some simple mistake which the group can point out. Some specifics are:
> > > >
> > > > Clock is Connor Winfield model D75A at 20 MHz. We buffer it through a 74LVC04 before it goes to the MSP430.
> > > >
> > > > I'm using the MSP4305529. VCC = 3.5 V. Using the FET-430UIF and ccs v 4.2.5.0005 on a macbook pro 2011 running parallels desktop emulating Win XP 64 bit.
> > > >
> > > > The code listed below ramps up vcore to level 3, sets XT2 to bypass, outputs MCLK and SMCLK to port pins for monitoring, sets a timer interrupt to provide a heartbeat signal to show the code is running, and has an ISR for osc fault condition where it sets the ck source back to XT2 bypass. The debug version of the code shows it spends all of it's time in the osc ISR waiting for the fault flag to stay clear.
> > > >
> > > > Things I've tried:
> > > > 1. Running ccs on a real Windows XP pro machine with identical results.
> > > > 2. Running the code with the internal osc selected to confirm proper operation of the timer ISR with the heartbeat signal.
> > > > 3. Running a release version of the code with the FET430 removed from the circuit - the power supply connection to it is noisy.
> > > > 4. Adding 10 uF tant, 5 uF poly and .1 uF ceramic to power supply.
> > > > 5. Dead bugging a schmitt trig buffer (74LVC1G17) on top of the MSP at XT2 input to better buffer the ck source (and bypassing this buffer power using a 1 uF and .1 uF ceramic caps).
> > > > 6. Different external power supply.
> > > > 7. New FET430 (to get rid of power noise - didn't help).
> > > > 8. .47 uF ceramic on vcore pin. Confirmed vcore using voltmeter and scope.
> > > > 9. Triple checking the JTAG interface (SLAU138L fig3.2).
> > > >
> > > > The ext ck signal, even after buffering, does not look as good as I'd like, but it is not bad. There are over/undershoots of about 600 mV lasting for about 8 ns, but they are rounded and there is no ringing. The MSP MCLK output when running off of internal osc shows the same level and duration of over/undershoot, but with some ringing - likely due to unterminated pin on MCLK output.
> > > >
> > > > I've read that the MSP430 is very quick to call osc fault on an external source, but this seems ridiculous. I have to be doing something simple and wrong in the code. Any suggestions will be much appreciated.
> > > >
> > > > Code:
> > > >
> > > > #include "msp430f5529.h"
> > > >
> > > > void SetVCoreUp(unsigned int level);
> > > >
> > > > volatile unsigned int i;
> > > > unsigned int level1 = 1;
> > > > unsigned int level2 = 2;
> > > > unsigned int level3 = 3;
> > > > //#include
> > > > int main(void)
> > > > {
> > > > WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
> > > >
> > > > SetVCoreUp(level1);
> > > > SetVCoreUp(level2);
> > > > SetVCoreUp(level3);
> > > >
> > > > P5SEL |= BIT2+BIT3; // Port select XT2
> > > > UCSCTL6 |= XT2BYPASS;
> > > >
> > > > UCSCTL6 &= ~XT2OFF; //enable xt2
> > > > UCSCTL6 &= SELREF_5;
> > > >
> > > > SFRIE1 |= OFIE; // enables oscillator fault interrupt
> > > >
> > > > UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT2
> > > > //UCSCTL5 &= ~(DIVM_0+DIVM_1+DIVM_2); // set MCLK divider to 1 for 20MHz
> > > >
> > > > //Show clocks on output pins
> > > > P2DIR |= BIT2; // SMCLK set out to pins
> > > > P2SEL |= BIT2;
> > > > P7DIR |= BIT7; // MCLK set out to pins
> > > > P7SEL |= BIT7;
> > > >
> > > > P5SEL &= ~BIT1; // P5.1 set as I/O
> > > > P5DIR |= BIT1; // P5.1 as output (LED1)
> > > > P5REN &= ~BIT1; // Disable pullup/pulldown resistor
> > > >
> > > >
> > > >
> > > >
> > > > __bis_SR_register(GIE);
> > > >
> > > >
> > > > UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT2
> > > >
> > > > TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
> > > > TBCCR0 = 50000; // counts to 50000
> > > > TBCTL = TBSSEL_2 +MC_1 + TBCLR; // System heartbeat output in ISR.
> > > >
> > > > while(1);
> > > >
> > > > }
> > > >
> > > > // Timer B0 interrupt service routine
> > > > #pragma vector=TIMERB0_VECTOR
> > > > __interrupt void TIMERB0_ISR (void)
> > > > {
> > > > P5OUT = 0x00; // heartbeat output on P5.1
> > > > P5OUT = 0x02;
> > > > P5OUT = 0x00;
> > > > P5OUT = 0x02;
> > > > }
> > > >
> > > > #pragma vector=UNMI_VECTOR
> > > > __interrupt void UNMI_ISR (void) // On osc fault, put it back to XT2
> > > > {
> > > > do {
> > > > P5SEL |= BIT2+BIT3; // Port select XT2
> > > > UCSCTL6 |= XT2BYPASS;
> > > >
> > > > UCSCTL6 &= ~XT2OFF; //enable xt2
> > > > UCSCTL6 &= SELREF_5;
> > > >
> > > >
> > > > UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
> > > > // Clear XT2,XT1,DCO fault flags
> > > > SFRIFG1 &= ~OFIFG; // Clear fault flags
> > > > // for (i = 0xFFF;i>0;i--); // Delay
> > > >
> > > > }
> > > > while (SFRIFG1&OFIFG); // Test oscillator fault flag
> > > >
> > > > SFRIE1 |= OFIE; // enables oscillator fault interrupt
> > > > }
> > > >
> > > > void SetVCoreUp(unsigned int level)
> > > > {
> > > > // Open PMM registers for write
> > > > PMMCTL0_H = PMMPW_H;
> > > > // Set SVS/SVM high side new level
> > > > SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
> > > > // Set SVM low side to new level
> > > > SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
> > > > // Wait till SVM is settled
> > > > while ((PMMIFG & SVSMLDLYIFG) == 0);
> > > > // Clear already set flags
> > > > PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
> > > > // Set VCore to new level
> > > > PMMCTL0_L = PMMCOREV0 * level;
> > > > // Wait till new level reached
> > > > if ((PMMIFG & SVMLIFG))
> > > > while ((PMMIFG & SVMLVLRIFG) == 0);
> > > > // Set SVS/SVM low side to new level
> > > > SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
> > > > // Lock PMM registers for write access
> > > > PMMCTL0_H = 0x00;
> > > > }
> > > >
> > >
> >
> >
> >
> >
> >
> >
>