This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430FR2311: Strange Behavior with Debugger, ADC10 reading and LPM0

Part Number: MSP430FR2311

Hello,

Sorry for the horrible title of this thread, but it is hard to describe the problem.  I've seen some strange behavior.  Sometimes when I run my code the debugger always seems to stop on one of the "__bis_SR_register(LPM0_bits + GIE);" in one of the ADC reading calls.  If it hit play it will just loop through the code once more and stop again.  I have no breakpoints set.  The strange part is if I remove one of the adc reading calls it goes away (e.g adc0_sample()).  I dug into this further and started toggling P2.3 when the CPU is awake and notice when it does this strange behavior that GPIO P2.3 will be high all time time which somewhat implies the CPU never goes back to sleep.  I even detach the debugger and see the same behavior.   Like I said before if I remove one of the adc reading calls, it goes away.  So then I added more code in each of the adc_sample() calls that sets the P2.3 low before it goes to sleep waiting for the ADC conversion to finish.  After the conversion is finished I set P2.3 high again.  Once I did this the problem went away again.  I see what I would expect.  P2.3 high for short time and then sleep.  It does this three times and then stays high for a longer interval to process everything else and then finally goes back to sleep for a longer interval until the next RTC interrupt kicks off the next cycle through the while(1).

So I'm really confused if I have a race condition of some sort or if I have an implementation bug.  Below I've attached the general idea of my code. It is worth noting I'm running the highest level of optimization for size in the compiler.

#include "driverlib.h"
#include <msp430.h>

/*
 * main.c
 */
int main(void) {
    //Stop WDT
    WDT_A_hold(WDT_A_BASE);
    initClockTo16MHz();
    initUART();

/* Initialize peripherals */
    initGPIO();
    initRTC();

    __delay_cycles(10000);

    EUSCI_A_UART_enable(EUSCI_A0_BASE);

    while(1){
	
		//woken by RTC interrrupt

        P2OUT |= BIT3;  //check CPU usage

    	adc1Sample();
    	adc1_reading = ADC_Conversion_Result;

        adc0Sample();
        adc0_reading = ADC_Conversion_Result;

        tempSample();
		temperature_reading = ADC_Conversion_Result;

		do_other_processing();

    	P2OUT &= ~BIT3;  // check cpu usage

        __bis_SR_register(LPM0_bits + GIE);  // change to LPM0

	}

}

void enable_ADC10(uint8_t adc_channel){
	//Initialize the ADC Module
	/*
	 * Base Address for the ADC Module
	 * Use internal ADC bit as sample/hold signal to start conversion
	 * USE MODOSC 5MHZ Digital Oscillator as clock source
	 * Use default clock divider of 1
	 */
	ADC_init(ADC_BASE, ADC_SAMPLEHOLDSOURCE_SC, ADC_CLOCKSOURCE_ADCOSC, ADC_CLOCKDIVIDER_1);


	ADC_enable(ADC_BASE);

	ADC_setupSamplingTimer(ADC_BASE, ADC_CYCLEHOLD_1024_CYCLES, ADC_MULTIPLESAMPLESDISABLE);

	if(adc_channel == ADCINCH_12)
	{
	    ADC_configureMemory(ADC_BASE, adc_channel, ADC_VREFPOS_INT, ADC_VREFNEG_AVSS);
	}
	else
	{
	    ADC_configureMemory(ADC_BASE, adc_channel, ADC_VREFPOS_AVCC, ADC_VREFNEG_AVSS);  
	}

	ADC_clearInterrupt(ADC_BASE, ADC_COMPLETED_INTERRUPT);

	//Enable the Memory Buffer Interrupt
	ADC_enableInterrupt(ADC_BASE, ADC_COMPLETED_INTERRUPT);
}

void disable_ADC10(void){
	ADC_disableConversions(ADC_BASE,0);
	ADC_disable(ADC_BASE);
}

void adc1Sample(void)
{
    enable_ADC10(ADCINCH_1);

    __delay_cycles(15);

    //Enable and Start the conversion
    //in Single-Channel, Single Conversion Mode
    ADC_startConversion(ADC_BASE, ADC_SINGLECHANNEL);
    //LPM0, ADC conversion complete will force exit
    __bis_SR_register(LPM0_bits + GIE);

    disable_ADC10();
}

void adc0Sample(void)
{
    enable_ADC10(ADCINCH_0);  // should be 0

    __delay_cycles(15);

    //Enable and Start the conversion
    //in Single-Channel, Single Conversion Mode
    ADC_startConversion(ADC_BASE, ADC_SINGLECHANNEL);
	//LPM0, ADC conversion complete will force exit
    __bis_SR_register(LPM0_bits + GIE);

    disable_ADC10();
}

void tempSample(void)
{
    enable_ADC10(ADCINCH_12);

    __delay_cycles(15);

    //Enable and Start the conversion
    //in Single-Channel, Single Conversion Mode
    ADC_startConversion(ADC_BASE, ADC_SINGLECHANNEL);

	//LPM0, ADC conversion complete will force exit
    __bis_SR_register(LPM0_bits + GIE);

    disable_ADC10();
}

void initGPIO(void){

    P1DIR |= 0b01000000; 

    P2DIR |= 0b00001111;  // P0-P3 all outputs
    P2OUT = 0x00;

    PMM_enableTempSensor();  // enable temperature sensor
    PMM_enableInternalReference();

    P1SEL1 |= GPIO_PIN6;    // PWM mode

    P1SEL1 &= ~(BIT7);                 // USCI_A0 UART operation TX only
    P1SEL0 |= BIT7;

    // I2C pins
    P1SEL0 |= BIT2 | BIT3;
    P1SEL1 &= ~(BIT2 | BIT3);

    //ADC Pins
    P1SEL0 |= BIT0 | BIT1;
    P1SEL1 |= BIT0 | BIT1;
    /*
     * Disable the GPIO power-on default high-impedance mode to activate
     * previously configured port settings
     */
    PMM_unlockLPM5();
}

// ADC interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=ADC_VECTOR
__interrupt void ADC_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ADC_VECTOR))) ADC_ISR (void)
#else
#error Compiler not supported!
#endif
{
    ADC_Conversion_Result = ADCMEM0;  // AP

	__bic_SR_register_on_exit(LPM0_bits);              // Exits LPM0
}

void initClockTo16MHz()
{
    // Configure one FRAM waitstate as required by the device datasheet for MCLK
    // operation beyond 8MHz _before_ configuring the clock system.
    FRCTL0 = FRCTLPW | NWAITS_1;

    __bis_SR_register(SCG0);    // disable FLL
    CSCTL8 |= MODOSCREQEN;      
    CSCTL3 |= SELREF__REFOCLK;  // Set REFO as FLL reference source
    CSCTL0 = 0;                 // clear DCO and MOD registers
    CSCTL1 &= ~(DCORSEL_7);     // Clear DCO frequency select bits first
    CSCTL1 |= DCORSEL_5;        // Set DCO = 16MHz
    CSCTL2 = FLLD_0 + 487;      // set to fDCOCLKDIV = (FLLN + 1)*(fFLLREFCLK/n)
                                //                   = (487 + 1)*(32.768 kHz/1)
                                //                   = 16 MHz

    __delay_cycles(3);
    __bic_SR_register(SCG0);                        // enable FLL
    while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1));      // FLL locked

    CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK;
}


// RTC interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=RTC_VECTOR
__interrupt void RTC_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(RTC_VECTOR))) RTC_ISR (void)
#else
#error Compiler not supported!
#endif
{
    __bic_SR_register_on_exit(LPM0_bits);              // Sleep Timer Exits LPM0

   switch(__even_in_range(RTCIV,RTCIV_RTCIF))

   {
       case  RTCIV_NONE:   break;          // No interrupt
       case  RTCIV_RTCIF:                  // RTC Overflow
           break;
       default: break;
   }
}

void initRTC()
{
    RTCMOD = 16-1;  // setup for 256Hz
    SYSCFG2 |= RTCCKSEL;                    // Select ACLK as RTC clock
    RTCCTL = RTCSS_1 | RTCSR | RTCPS__16 | RTCIE;
}


  • I don't see this behavior on my Launchpad. I dummied initUART and do_other_processing, and built with "-O4 --opt_for_speed=0". My scope says the full cycle takes 0.68ms out of a 7.8ms cycle, which is roughly what the code says. I didn't see any false breakpoints in the debugger.

    What does do_other_processing() do? Is anything connected to the pins? (I have pretty much the minimum.)

  • Main loops at 128Hz.  I get 3 pulses 10uS wide for when the CPU runs before each ADC reading with a sleep time of 214us between each reading.  Do other stuff takes about 66uS.  Do other stuff just processes the ADC readings and makes some decisions based on what is going on.  I also sometimes add some basic dbug messages that come out the UART.  Like I said the behavior is very strange and it seems like it is code dependent.

    Is there anything I'm doing wrong from an interrupt standpoint.  I guess my assumptions are that I wake up form the RTC interrupt, then start an ADC reading and go to sleep, adc conversion complete wakes cpu back up and cpu picks up where it left off in the adc conversion routine and then proceeds to the next conversion in main.  Once the last conversion is complete it finishes up processing and then proceeds to go to sleep and wait for the next RTC interrupt.

  • Fair enough. But if, based on what you've posted, I can't replicate your symptom, that suggests that the problem is elsewhere. (code? Project? environment?)

    Unsolicited (and maybe irrelevant):

    The first thing that caught my eye is that you have two (anonymous) wakeup sources. If you always meet all of your deadlines, this can work out -- and does in the code you posted. But if you miss one it's easy to get out-of-synch in the wakeups (since wakeups don't latch). 66us is of course well within your deadline, but introducing e.g. UART messages is a good way to throw things off if you're not very careful.

    Another thing to keep in mind is that some MCU clocks don't stop immediately, or even continue to run while you're at a breakpoint, so the breakpoint itself can throw the sequencing off. 

  • So are you suggesting I set a unique flag each time I go to sleep so I now the wake up source and then only run the appropriate sections in main based on that flag?

  • I think it would be a good idea, though I can't say that it will fix your symptom. Your descriptions do sound reminiscent of the kinds of things you'd see if the wakeups were muddled. Here's a more in-depth discussion:

    https://e2e.ti.com/support/microcontrollers/msp430/f/166/p/820313/3034992

    As posted, your code (presuming the two missing functions are empty) runs deterministically, and well within its deadlines. It also (pardon the expression) doesn't do much. Given the unknowns, I suspected that there was code hidden (I2C? PWM? UART ISR?) which was large enough to nudge this simple reliable loop until it fell over.

  • The interesting thing is that there is more than enough processing time.  For example, if I removed the 2nd ADC reading and did nothing else the problem would go away and watching CPU usage would say that there is more than enough time to complete everything.  Then I add back in the 2nd ADC reading and all of a sudden the CPU appears busy all the time and the debugger keeps stopping at the CPU wakeup.

  • This would be consistent with a missing/extra wakeup (deadline), since removing one of the ADC calls removes about 200us from the loop.

    It seems as though whatever it is, it's outside what you've posted, so all I can do is guess.

  • Bruce McKenney47378 said:

    This would be consistent with a missing/extra wakeup (deadline), since removing one of the ADC calls removes about 200us from the loop.

    Yes I would agree with this statement normally, but when I add extra UART messages to do_other_processing() things start to work again with all 3 ADC readings and there is still tons of CPU available according to the usage LED.  That is why this so bizarre to me.

  • Hi Andrew

    Have you solve this issue? Or any update about it?

    Best regards

    Gary

  • Gary,

    No I haven't "solved" it.  I've worked around it by just adding or changing code.  When it does work properly, all the code runs in plenty of time to complete before the next wake cycle.  When it doesn't, the CPU never goes to sleep.

  • At some level, that's how Static Scheduling is done. (Back in the Ancient Days we counted a lot of CPU clocks.)

    I think as long as you have multiple anonymous wakeup sources (does the UART do a wakeup?) you're probably stuck with Static Scheduling, since you need to always know which interrupt will go off next. I was suggesting that by identifying the wakeups you might make things more robust -- "Gelatinous Real Time" as it were.

    I don't know how many times I've found myself writing a trivial little trace facility -- write an "I got <here>" byte into a circular buffer -- to figure out an unexpected sequence. Maybe something like that would help?

  • The only wakeup sources are the RTC, and the three ADC reads.  I2C does not wakeup, it just completes the interrupt and should go back to sleep since I don't do a "__bic_SR_register_on_exit(LPM0_bits);  " in the interrupt.  I rely on the RTC interrupt to act on the I2C commands.  The dbug UART only transmits and just does polling.

  • Bruce,

    Do you feel like this would work OK?  I added an interrupt_id flag.

    #include "driverlib.h"
    #include <msp430.h>
    
    unsigned int interrupt_id = 0;
    /*
     * main.c
     */
    int main(void) {
        //Stop WDT
        WDT_A_hold(WDT_A_BASE);
        initClockTo16MHz();
        initUART();
    
    /* Initialize peripherals */
        initGPIO();
        initRTC();
    
        __delay_cycles(10000);
    
        EUSCI_A_UART_enable(EUSCI_A0_BASE);
    
        while(1){
    	
    		//woken by RTC interrrupt
    
            P2OUT |= BIT3;  //check CPU usage
    
    		if(interrupt_id == 0)
    		{
    		
    			adc1Sample();
    			adc1_reading = ADC_Conversion_Result;
    		}
    
    		if(interrupt_id == 1)
    		{
    			adc0Sample();
    			adc0_reading = ADC_Conversion_Result;
    		}
    			
    
    		if(interrupt_id == 2)
    		{
    			tempSample();
    			temperature_reading = ADC_Conversion_Result;
    		}
    
    		if(interrupt_id == 3)
    		{
    		
    			do_other_processing();
    		}
    
        	P2OUT &= ~BIT3;  // check cpu usage
    
            __bis_SR_register(LPM0_bits + GIE);  // change to LPM0
    
    	}
    
    }
    
    void enable_ADC10(uint8_t adc_channel){
    	//Initialize the ADC Module
    	/*
    	 * Base Address for the ADC Module
    	 * Use internal ADC bit as sample/hold signal to start conversion
    	 * USE MODOSC 5MHZ Digital Oscillator as clock source
    	 * Use default clock divider of 1
    	 */
    	ADC_init(ADC_BASE, ADC_SAMPLEHOLDSOURCE_SC, ADC_CLOCKSOURCE_ADCOSC, ADC_CLOCKDIVIDER_1);
    
    
    	ADC_enable(ADC_BASE);
    
    	ADC_setupSamplingTimer(ADC_BASE, ADC_CYCLEHOLD_1024_CYCLES, ADC_MULTIPLESAMPLESDISABLE);
    
    	if(adc_channel == ADCINCH_12)
    	{
    	    ADC_configureMemory(ADC_BASE, adc_channel, ADC_VREFPOS_INT, ADC_VREFNEG_AVSS);
    	}
    	else
    	{
    	    ADC_configureMemory(ADC_BASE, adc_channel, ADC_VREFPOS_AVCC, ADC_VREFNEG_AVSS);  
    	}
    
    	ADC_clearInterrupt(ADC_BASE, ADC_COMPLETED_INTERRUPT);
    
    	//Enable the Memory Buffer Interrupt
    	ADC_enableInterrupt(ADC_BASE, ADC_COMPLETED_INTERRUPT);
    }
    
    void disable_ADC10(void){
    	ADC_disableConversions(ADC_BASE,0);
    	ADC_disable(ADC_BASE);
    }
    
    void adc1Sample(void)
    {
        enable_ADC10(ADCINCH_1);
    
        __delay_cycles(15);
    
        //Enable and Start the conversion
        //in Single-Channel, Single Conversion Mode
        ADC_startConversion(ADC_BASE, ADC_SINGLECHANNEL);
        //LPM0, ADC conversion complete will force exit
    	interrupt_id = 1;
        __bis_SR_register(LPM0_bits + GIE);
    
        disable_ADC10();
    }
    
    void adc0Sample(void)
    {
        enable_ADC10(ADCINCH_0);  // should be 0
    
        __delay_cycles(15);
    
        //Enable and Start the conversion
        //in Single-Channel, Single Conversion Mode
        ADC_startConversion(ADC_BASE, ADC_SINGLECHANNEL);
    	//LPM0, ADC conversion complete will force exit
    	interrupt_id = 2;
        __bis_SR_register(LPM0_bits + GIE);
    
        disable_ADC10();
    }
    
    void tempSample(void)
    {
        enable_ADC10(ADCINCH_12);
    
        __delay_cycles(15);
    
        //Enable and Start the conversion
        //in Single-Channel, Single Conversion Mode
        ADC_startConversion(ADC_BASE, ADC_SINGLECHANNEL);
    
    	//LPM0, ADC conversion complete will force exit
    	interrupt_id = 3;
        __bis_SR_register(LPM0_bits + GIE);
    
        disable_ADC10();
    }
    
    void initGPIO(void){
    
        P1DIR |= 0b01000000; 
    
        P2DIR |= 0b00001111;  // P0-P3 all outputs
        P2OUT = 0x00;
    
        PMM_enableTempSensor();  // enable temperature sensor
        PMM_enableInternalReference();
    
        P1SEL1 |= GPIO_PIN6;    // PWM mode
    
        P1SEL1 &= ~(BIT7);                 // USCI_A0 UART operation TX only
        P1SEL0 |= BIT7;
    
        // I2C pins
        P1SEL0 |= BIT2 | BIT3;
        P1SEL1 &= ~(BIT2 | BIT3);
    
        //ADC Pins
        P1SEL0 |= BIT0 | BIT1;
        P1SEL1 |= BIT0 | BIT1;
        /*
         * Disable the GPIO power-on default high-impedance mode to activate
         * previously configured port settings
         */
        PMM_unlockLPM5();
    }
    
    // ADC interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=ADC_VECTOR
    __interrupt void ADC_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(ADC_VECTOR))) ADC_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
        ADC_Conversion_Result = ADCMEM0;  // AP
    
    	__bic_SR_register_on_exit(LPM0_bits);              // Exits LPM0
    }
    
    void initClockTo16MHz()
    {
        // Configure one FRAM waitstate as required by the device datasheet for MCLK
        // operation beyond 8MHz _before_ configuring the clock system.
        FRCTL0 = FRCTLPW | NWAITS_1;
    
        __bis_SR_register(SCG0);    // disable FLL
        CSCTL8 |= MODOSCREQEN;      
        CSCTL3 |= SELREF__REFOCLK;  // Set REFO as FLL reference source
        CSCTL0 = 0;                 // clear DCO and MOD registers
        CSCTL1 &= ~(DCORSEL_7);     // Clear DCO frequency select bits first
        CSCTL1 |= DCORSEL_5;        // Set DCO = 16MHz
        CSCTL2 = FLLD_0 + 487;      // set to fDCOCLKDIV = (FLLN + 1)*(fFLLREFCLK/n)
                                    //                   = (487 + 1)*(32.768 kHz/1)
                                    //                   = 16 MHz
    
        __delay_cycles(3);
        __bic_SR_register(SCG0);                        // enable FLL
        while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1));      // FLL locked
    
        CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK;
    }
    
    
    // RTC interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=RTC_VECTOR
    __interrupt void RTC_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(RTC_VECTOR))) RTC_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
    	interrupt_id = 0;
        __bic_SR_register_on_exit(LPM0_bits);              // Sleep Timer Exits LPM0
    
       switch(__even_in_range(RTCIV,RTCIV_RTCIF))
    
       {
           case  RTCIV_NONE:   break;          // No interrupt
           case  RTCIV_RTCIF:                  // RTC Overflow
               break;
           default: break;
       }
    }
    
    void initRTC()
    {
        RTCMOD = 16-1;  // setup for 256Hz
        SYSCFG2 |= RTCCKSEL;                    // Select ACLK as RTC clock
        RTCCTL = RTCSS_1 | RTCSR | RTCPS__16 | RTCIE;
    }
    
    

  • It looks as though you've introduced a state machine, which might be an interesting approach but I don't think gets at the race condition.

    All I was suggesting was:

    1) Introduce 2 ("volatile") variables: RTC_done and ADC_done. Each is set to 1 by the relevant ISR.

    2) When you want to wait for the ADC following the Start call, add:

    > while (!ADC_done) LPM0;  // Wait for completion event

    > ADC_done = 0;   // Acknowledge event

    Thus if the RTC interrupt happens out of turn, the program won't think the ADC has finished. The RTC interrupt (event) will stay pending until the analogous check at the bottom of the loop.

    (There's still a small race between fetching the ADC_done value and the LPM0. This is probably not a big problem now.)

  • Bruce,

    Thank you again for your valuable insight.  I believe this is what you are suggesting?

    #include "driverlib.h"
    #include <msp430.h>
    
    unsigned int interrupt_id = 0;
    volatile unsigned int ADC_done = 0;
    volatile unsigned int RTC_done = 0;
    /*
     * main.c
     */
    int main(void) {
        //Stop WDT
        WDT_A_hold(WDT_A_BASE);
        initClockTo16MHz();
        initUART();
    
    /* Initialize peripherals */
        initGPIO();
        initRTC();
    
        __delay_cycles(10000);
    
        EUSCI_A_UART_enable(EUSCI_A0_BASE);
    
        while(1){
        
            //woken by RTC interrrupt
    
            P2OUT |= BIT3;  //check CPU usage
    
            if(interrupt_id == 0)
            {
            
                adc1Sample();
                adc1_reading = ADC_Conversion_Result;
            }
    
            if(interrupt_id == 1)
            {
                adc0Sample();
                adc0_reading = ADC_Conversion_Result;
            }
                
    
            if(interrupt_id == 2)
            {
                tempSample();
                temperature_reading = ADC_Conversion_Result;
            }
    
            if(interrupt_id == 3)
            {
            
                do_other_processing();
            }
    
            P2OUT &= ~BIT3;  // check cpu usage
    		
    		while(!RTC_done)
    		{
    			__bis_SR_register(LPM0_bits + GIE);  // change to LPM0
    		}
    		
    		RTC_done = 0;
    
            //__bis_SR_register(LPM0_bits + GIE);  // change to LPM0
    
        }
    
    }
    
    void enable_ADC10(uint8_t adc_channel){
        //Initialize the ADC Module
        /*
         * Base Address for the ADC Module
         * Use internal ADC bit as sample/hold signal to start conversion
         * USE MODOSC 5MHZ Digital Oscillator as clock source
         * Use default clock divider of 1
         */
        ADC_init(ADC_BASE, ADC_SAMPLEHOLDSOURCE_SC, ADC_CLOCKSOURCE_ADCOSC, ADC_CLOCKDIVIDER_1);
    
    
        ADC_enable(ADC_BASE);
    
        ADC_setupSamplingTimer(ADC_BASE, ADC_CYCLEHOLD_1024_CYCLES, ADC_MULTIPLESAMPLESDISABLE);
    
        if(adc_channel == ADCINCH_12)
        {
            ADC_configureMemory(ADC_BASE, adc_channel, ADC_VREFPOS_INT, ADC_VREFNEG_AVSS);
        }
        else
        {
            ADC_configureMemory(ADC_BASE, adc_channel, ADC_VREFPOS_AVCC, ADC_VREFNEG_AVSS);  
        }
    
        ADC_clearInterrupt(ADC_BASE, ADC_COMPLETED_INTERRUPT);
    
        //Enable the Memory Buffer Interrupt
        ADC_enableInterrupt(ADC_BASE, ADC_COMPLETED_INTERRUPT);
    }
    
    void disable_ADC10(void){
        ADC_disableConversions(ADC_BASE,0);
        ADC_disable(ADC_BASE);
    }
    
    void adc1Sample(void)
    {
        enable_ADC10(ADCINCH_1);
    
        __delay_cycles(15);
    
        //Enable and Start the conversion
        //in Single-Channel, Single Conversion Mode
        ADC_startConversion(ADC_BASE, ADC_SINGLECHANNEL);
        //LPM0, ADC conversion complete will force exit	
        
        //__bis_SR_register(LPM0_bits + GIE);
    	
    	while(!ADC_done)
    	{
    		__bis_SR_register(LPM0_bits + GIE);
    	}
    	
    	ADC_done = 0;
    	interrupt_id = 1;
    
        disable_ADC10();
    }
    
    void adc0Sample(void)
    {
        enable_ADC10(ADCINCH_0);  // should be 0
    
        __delay_cycles(15);
    
        //Enable and Start the conversion
        //in Single-Channel, Single Conversion Mode
        ADC_startConversion(ADC_BASE, ADC_SINGLECHANNEL);
        //LPM0, ADC conversion complete will force exit
    
        //__bis_SR_register(LPM0_bits + GIE);
    	
    	while(!ADC_done)
    	{
    		__bis_SR_register(LPM0_bits + GIE);
    	}
    	
    	ADC_done = 0;
    	interrupt_id = 2;
    
        disable_ADC10();
    }
    
    void tempSample(void)
    {
        enable_ADC10(ADCINCH_12);
    
        __delay_cycles(15);
    
        //Enable and Start the conversion
        //in Single-Channel, Single Conversion Mode
        ADC_startConversion(ADC_BASE, ADC_SINGLECHANNEL);
        //LPM0, ADC conversion complete will force exit
    
        //__bis_SR_register(LPM0_bits + GIE);
    	
    	while(!ADC_done)
    	{
    		__bis_SR_register(LPM0_bits + GIE);
    	}
    	
    	ADC_done = 0;
    	interrupt_id = 3;
    
        disable_ADC10();
    }
    
    void initGPIO(void){
    
        P1DIR |= 0b01000000; 
    
        P2DIR |= 0b00001111;  // P0-P3 all outputs
        P2OUT = 0x00;
    
        PMM_enableTempSensor();  // enable temperature sensor
        PMM_enableInternalReference();
    
        P1SEL1 |= GPIO_PIN6;    // PWM mode
    
        P1SEL1 &= ~(BIT7);                 // USCI_A0 UART operation TX only
        P1SEL0 |= BIT7;
    
        // I2C pins
        P1SEL0 |= BIT2 | BIT3;
        P1SEL1 &= ~(BIT2 | BIT3);
    
        //ADC Pins
        P1SEL0 |= BIT0 | BIT1;
        P1SEL1 |= BIT0 | BIT1;
        /*
         * Disable the GPIO power-on default high-impedance mode to activate
         * previously configured port settings
         */
        PMM_unlockLPM5();
    }
    
    // ADC interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=ADC_VECTOR
    __interrupt void ADC_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(ADC_VECTOR))) ADC_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
        ADC_Conversion_Result = ADCMEM0;  // AP
    	
    	ADC_done = 1;
    
        __bic_SR_register_on_exit(LPM0_bits);              // Exits LPM0
    }
    
    void initClockTo16MHz()
    {
        // Configure one FRAM waitstate as required by the device datasheet for MCLK
        // operation beyond 8MHz _before_ configuring the clock system.
        FRCTL0 = FRCTLPW | NWAITS_1;
    
        __bis_SR_register(SCG0);    // disable FLL
        CSCTL8 |= MODOSCREQEN;      
        CSCTL3 |= SELREF__REFOCLK;  // Set REFO as FLL reference source
        CSCTL0 = 0;                 // clear DCO and MOD registers
        CSCTL1 &= ~(DCORSEL_7);     // Clear DCO frequency select bits first
        CSCTL1 |= DCORSEL_5;        // Set DCO = 16MHz
        CSCTL2 = FLLD_0 + 487;      // set to fDCOCLKDIV = (FLLN + 1)*(fFLLREFCLK/n)
                                    //                   = (487 + 1)*(32.768 kHz/1)
                                    //                   = 16 MHz
    
        __delay_cycles(3);
        __bic_SR_register(SCG0);                        // enable FLL
        while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1));      // FLL locked
    
        CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK;
    }
    
    
    // RTC interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=RTC_VECTOR
    __interrupt void RTC_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(RTC_VECTOR))) RTC_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
        interrupt_id = 0;
    	RTC_done = 1;
        __bic_SR_register_on_exit(LPM0_bits);              // Sleep Timer Exits LPM0
    
       switch(__even_in_range(RTCIV,RTCIV_RTCIF))
    
       {
           case  RTCIV_NONE:   break;          // No interrupt
           case  RTCIV_RTCIF:                  // RTC Overflow
               break;
           default: break;
       }
    }
    
    void initRTC()
    {
        RTCMOD = 16-1;  // setup for 256Hz
        SYSCFG2 |= RTCCKSEL;                    // Select ACLK as RTC clock
        RTCCTL = RTCSS_1 | RTCSR | RTCPS__16 | RTCIE;
    }

  • That's pretty much what I had in mind. What does it do when you run it?

  • I implemented it and I see no ill effects.  It is hard to tell if it improved anything because the problem sort of disappeared as I modified code (gotta love these types of problems).  I do agree with you that it should be more robust.  

**Attention** This is a public forum