Other Parts Discussed in Thread: MSP430F5529
Dear MSP430 Gurus,
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.
10. Numerous experiments show that the MSP is falling back to using the DCO. Control register flags are set to the values we picked. Fault flags in debug show for XT1 and DCO, but no fault flag for XT2.
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?
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:
//******************************************************************************
// MSP430f5529 Genie Firmware r3.0
//
// Description;
//
// C. Wildey
// MRRA Inc.
// March 3, 2012
// Built with CCS core edition version 4.2.5.00005
//******************************************************************************
#include
"msp430f5529.h"
void
SetVCoreUp(unsigned intlevel);
volatile
unsigned int i;
unsigned
int level1 = 1;
unsigned
int level2 = 2;
unsigned
int level3 = 3;
//#include <stdio.h>
int
main(void)
{
WDTCTL = WDTPW + WDTHOLD;
// Stop watchdog timer
// Loop until XT1,XT2 & DCO stabilizes - in this case loop until XT2 settles
SetVCoreUp(level1);
SetVCoreUp(level2);
SetVCoreUp(level3);
__bis_SR_register(SCG0);
__bis_SR_register(SCG1);
// disable DCO and FLL
// UCSCTL1 |= DCORSEL_4;
P5SEL |= BIT2+BIT3;
// Port select XT2
UCSCTL6 |= XT2BYPASS;
UCSCTL3 = SELREF_5;
P5SEL &= ~BIT1;
// P5.1 set as I/O
P5DIR |= BIT1;
// P5.1 as output (LED1)
P5REN &= ~BIT1;
// Disable pullup/pulldown resistor
UCSCTL5 = 0x0000;
// divide by 1
UCSCTL6 |= XT1OFF;
UCSCTL6 &= ~XT2OFF;
UCSCTL4 = SELA_5 + SELS_5 + SELM_5;
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);
//Set up for external osc on xt2
P2DIR |= BIT2;
// SMCLK set out to pins
P2SEL |= BIT2;
P7DIR |= BIT7;
// MCLK set out to pins
P7SEL |= BIT7;
TBCCTL0 = CCIE;
// TBCCR0 interrupt enabled
TBCCR0 = 50000;
// counts to 50000
TBCTL = TBSSEL_2 +MC_1 + TBCLR;
__bis_SR_register(GIE);
while(1);
}
// Timer B0 interrupt service routine
#pragma
vector=TIMERB0_VECTOR
__interrupt
void TIMERB0_ISR (void)
{
P5OUT = 0x00;;
P5OUT = 0x02;
P5OUT = 0x00;;
P5OUT = 0x02;
}
void
SetVCoreUp(unsigned intlevel)
{
// 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;
}