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.

RTOS/MSP430F5528: RTOS is not operating after exiting from LPM4

Part Number: MSP430F5528

Tool/software: TI-RTOS

Hi, 

I have successfully gotten my CPU into LPM4.  I exit LPM4 by using one of the hardware buttons on my system to generate an interrupt.  I have verified that the ISR is being executed using my debugger.  The last statement executed before returning from the interrupt is   __bic_SR_register_on_exit( 0xF0 ); 

The problem arises after returning from the interrupt.  My .cfg has timer0 ( instantiated with XGCONF ) associated with a function called heartBeatFxn().  This has period of 25mS, and it is never being executed after RETI.  At this point the SR has a value of 0x040C.  Also I have verified that TA0 is running.

Is there something I need to do to get the RTOS operating after exiting LPM4 ?

Thank you

Roy

  

  • Hi Roy,

    Have you checked if that function was being correctly before going into LPM4?

    Regards,
    Nathan
  • Hi Nathan,

    heartBeatFxn() is working perfectly before entering LPM4.

    However, it never recovers after exiting the ISR .

    Roy 

  • Hi Roy,

    Are you seeing the timer interrupt being hit? I am assuming that this is how you are calling heartBeatFxn().

    Regards,
    Nathan
  • Hi Nathan,

    I have not looked for an interrupt. The way I determine if heartBeatFxn() is getting called is by setting a breakpoint inside the function. I think TA0 is associated with my clock0 timer in XGCONF. I have noted that when I pause the debugger, after exiting LPM4, I see that the interrupt is not enabled for TA0, and the interrupt flag is set.

    Where would I look for the ISR associated with TA0 ?

    Roy
  • Hi Nathan,
    My research into the sys/bios timer implementation shows that one hardware ( I think it is using TA0 ) timer is configured to produce clock ticks for clock0, clock1, etc. TA0 is supposed to be operating continuously in the count up mode, and producing an Hwi every 1000us. I think this is when the Clock_tick() function is called.
    The clock0 in my system is configured to count up to 25 clock ticks, and then call heartBeatFxn().

    After exiting the LPM4, heartBeatFxn() is never called. However, using the debugger, I can see that TA0 is running. One thing I have noticed, before entering LPM4, is that TACCR0 is being changed each time that I pause the debugger. After exiting LPM4, when I pause the debugger, I see that TACCR0 is no longer being changed.

    I think that something is not right with the sys/bios timer module after exiting LPM4.

    Roy
  • Roy,

    I see that your issue is 5 day old and not well advancing.

    I do not have 5528 to recreate your issue however I have MSP-EXP4305529LP which is very similar. to your chip.

    I do not agree with your first statement: I have successfully gotten my CPU into LPM4.

    If we cannot properly exit LPM4 we cannot say that we were ready to enter LPM4.

    You provide almost no information on your environment and code like:

    - CCS version, compiler version, a custom board or a LP,

    - your ISR code and how did linked it with TI-RTOS, do you use hwi(), zero latency, custom interrupt?

    You say: This has period of 25mS, and it is never being executed after RETI.  At this point the SR has a value of 0x040C.

    For your supporter having no 5528, like me, it will up to 30 minutes to decode your SR value.

    Help me to let me help you.

    Could you check if your ISR is working properly if you do not enter LPM4?

    Please check that your Clock System is properly configured to support LPM4 for your MCU and confirm.

    If Clock System is properly configured, I would recommend to go to ISR details.

  • Roy,

    looks to me that your are mixing low level intrinsic function rules with TI-RTOS interrupt requirements.
  • 1641.SPI_UCB0.c
    /*
     * SPI_UCB0.c
     *
     *  Created on: Feb 20, 2018
     *
     */
    
    // copied from I2C_UCB1.c on 4.13.18
    // I had to do this to get "mutex_sem_VRS" recognized
    #include <Debug/configPkg/package/cfg/empty_min_pe430X.h>
    #include <gpio.h>
    #include <msp430f5528.h>
    #include <my_board.h>
    #include <stdbool.h>
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Semaphore.h>
    // removed 7.31.18
    // The RTOS does not use the power management module
    // See TI wiki sysbios msp430 Power Management
    // #include <ti/sysbios/family/msp430/Power.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/System.h>
    #include <xdc/std.h>
    
    #include <stdio.h>
    #include "misc_stuff.h"
    #include "com.h"
    // NOTE:  driverlib.h will include all of the other header files
    // that are associated with the driver library
    #include <driverlib.h>
    #include "font_table.h"
    
    BYTE LCD_state = LCD_IDLE;
    float pressure_samples[LOPS];
    BYTE pressure_samples_index = 0;
    float system_slope;
    float system_offset = 0.5;
    QDATA full_scale_pressure;
    BYTE LCD_choice = CHOICE_SF_HOME;
    
    
    
    
    USCI_B_SPI_initMasterParam DAC_LCD_SPI_param;
    
    bool DAC_LCD_SPI_initMaster_return_value = false;
    
    void init_UCB0( void )
    {
        extern void write_DACV( QUADLET value );
        extern void UCB0_write_DACI( BYTE command, DOUBLET value );
        extern DOUBLET vrs_ehc;
        extern QUADLET read_VRS( BYTE offset );
    
    
        DOUBLET i;
    
        // Power_changeIdleMode( Power_LPM4 );
    
        // read the full scale pressure from the VRS
        full_scale_pressure.quadlet = read_VRS( VRS_FULL_SCALE_OFFSET );
    
        // init the pressure samples
        for(i=0; i<LOPS; i++)
        {
          pressure_samples[i] = 0;
        }
    
        DAC_LCD_SPI_param.selectClockSource = USCI_B_SPI_CLOCKSOURCE_SMCLK;
        DAC_LCD_SPI_param.clockSourceFrequency = UCS_getSMCLK();
        // try 1.0 MHz
        DAC_LCD_SPI_param.desiredSpiClock = 1000000;
        DAC_LCD_SPI_param.msbFirst = USCI_B_SPI_MSB_FIRST;
        DAC_LCD_SPI_param.clockPhase = USCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT;
        DAC_LCD_SPI_param.clockPolarity = USCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH;
    
        switch ( vrs_ehc )
        {
        	case VRS_EHC_VOLTAGE:
    
        		// calculate the slope of the system,
        	    // this is used only for the T5 ( Voltage Output )
        	    //      Y = mX + b
        	    //      (0 PSI, 0.5V)
        	    //      (Full Scale Pressure PSI, 4.5V)
        	    //      m = (4.5V - 0.5V) / (FSP PSI - 0 PSI)
        	    system_slope = (4 / full_scale_pressure.float_num);
    
        		// configure P2.7 as output and set high
        		// signal is DAC_/SYNC_A or RGLTR_/SYNC
        		GPIO_setAsOutputPin( GPIO_PORT_P2, GPIO_PIN7 );
        		GPIO_setOutputHighOnPin( GPIO_PORT_P2, GPIO_PIN7 ); // default state
       		 	// enable output pins for UCBSIMO, and UCB0CLK
       		    GPIO_setAsPeripheralModuleFunctionOutputPin( GPIO_PORT_P3, (GPIO_PIN0 | GPIO_PIN2) );
        		DAC_LCD_SPI_initMaster_return_value = USCI_B_SPI_initMaster( USCI_B0_BASE, &DAC_LCD_SPI_param );
        		USCI_B_SPI_enable( USCI_B0_BASE );  // enables operation of the SPI block
    
    			// configure P2.5, P2.6 as outputs and set high
    			// these are the signals OE (for the TXB104 level shifter), and DAC_/CLR_A
    			GPIO_setAsOutputPin( GPIO_PORT_P2, (GPIO_PIN5 | GPIO_PIN6) );
    			GPIO_setOutputHighOnPin( GPIO_PORT_P2, (GPIO_PIN5 | GPIO_PIN6) );
    			// Asynchronously clear the DAC output
    			GPIO_setOutputLowOnPin( GPIO_PORT_P2, GPIO_PIN6 );
    			__delay_cycles( 8 );   // must be low 80nS minimum, at 16Mhz this should provide 500nS
    			GPIO_setOutputHighOnPin( GPIO_PORT_P2, GPIO_PIN6 );
    
    			// software reset of the DAC7562
    			write_DACV( 0x280001 );
    
    			// Power up DAC-A
    			write_DACV( 0x200001 );
    
    			// enable the internal voltage reference of the DAC7562
    			write_DACV( 0x380001 );
    
    			break;
    
        	case VRS_EHC_4_20MA:
    
        		DAC_LCD_SPI_param.clockPhase = USCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT;
    
        		// configure P2.7 as output and set high
        		// signal is DAC_/SYNC_A or RGLTR_/SYNC
        		GPIO_setAsOutputPin( GPIO_PORT_P2, GPIO_PIN7 );
        		GPIO_setOutputHighOnPin( GPIO_PORT_P2, GPIO_PIN7 ); // default state
    
        		// enable output pins for UCBSIMO, and UCB0CLK
        		GPIO_setAsPeripheralModuleFunctionOutputPin( GPIO_PORT_P3, (GPIO_PIN0 | GPIO_PIN2) );
        		DAC_LCD_SPI_initMaster_return_value = USCI_B_SPI_initMaster( USCI_B0_BASE, &DAC_LCD_SPI_param );
        		USCI_B_SPI_enable( USCI_B0_BASE );  // enables operation of the SPI block
    
    			// configure P3.0 ( UCB0SOMI ) as an input
    			GPIO_setAsInputPin( GPIO_PORT_P3, GPIO_PIN0 );
    
    			// reset the 4-20mA regulator
    			UCB0_write_DACI( 0x07, 0x0000 );
    
    			break;
    
        	case VRS_EHC_LCD_BATTERY:
    
                DAC_LCD_SPI_param.clockPhase = USCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT;
    
                // configure P2.7 as output and set high
                // signal is LCD_CS1
                GPIO_setAsOutputPin( GPIO_PORT_P2, GPIO_PIN7 );
                GPIO_setOutputHighOnPin( GPIO_PORT_P2, GPIO_PIN7 ); // default state
    
                // configure P2.6 as output and set high
                // signal is LCD_/RES
                GPIO_setAsOutputPin( GPIO_PORT_P2, GPIO_PIN6 );
                GPIO_setOutputHighOnPin( GPIO_PORT_P2, GPIO_PIN6 ); // default state
    
                // configure P2.5 as output and set low
                // signal is LCD_A0
                GPIO_setAsOutputPin( GPIO_PORT_P2, GPIO_PIN5 );
                GPIO_setOutputLowOnPin( GPIO_PORT_P2, GPIO_PIN5 ); // default state
    
                // enable output pins for UCBSIMO, and UCB0CLK
                GPIO_setAsPeripheralModuleFunctionOutputPin( GPIO_PORT_P3, (GPIO_PIN0 | GPIO_PIN2) );
                DAC_LCD_SPI_initMaster_return_value = USCI_B_SPI_initMaster( USCI_B0_BASE, &DAC_LCD_SPI_param );
                USCI_B_SPI_enable( USCI_B0_BASE );  // enables operation of the SPI block
    
        	    break;
    
    
        	case VRS_EHC_LCD_4_20MA:
    
        		DAC_LCD_SPI_param.clockPhase = USCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT;
    
    			// configure P2.7 as output and set high
    			// signal is LCD_CS1
    		    GPIO_setAsOutputPin( GPIO_PORT_P2, GPIO_PIN7 );
    		    GPIO_setOutputHighOnPin( GPIO_PORT_P2, GPIO_PIN7 ); // default state
    
    		    // configure P2.6 as output and set high
    		   	// signal is LCD_/RES
    		    GPIO_setAsOutputPin( GPIO_PORT_P2, GPIO_PIN6 );
    		    GPIO_setOutputHighOnPin( GPIO_PORT_P2, GPIO_PIN6 ); // default state
    
    		    // configure P2.5 as output and set low
    		   	// signal is LCD_A0
    		    GPIO_setAsOutputPin( GPIO_PORT_P2, GPIO_PIN5 );
    		    GPIO_setOutputLowOnPin( GPIO_PORT_P2, GPIO_PIN5 ); // default state
    
    		    // enable output pins for UCBSIMO, and UCB0CLK
    		    GPIO_setAsPeripheralModuleFunctionOutputPin( GPIO_PORT_P3, (GPIO_PIN0 | GPIO_PIN2) );
    		    DAC_LCD_SPI_initMaster_return_value = USCI_B_SPI_initMaster( USCI_B0_BASE, &DAC_LCD_SPI_param );
    		    USCI_B_SPI_enable( USCI_B0_BASE );  // enables operation of the SPI block
    
    			break;
    
    
    
        	default:
        		break;
    
    	}	// end of switch *******************************************************
    
    }   // end of my_board_init_UCB0() ******************************************
    
    
    void pressure_to_voltage( float current_pressure )
    {
        extern void write_DACV( QUADLET value );
        BYTE i;
        QDATA avg_pressure;
        DOUBLET DAC_register;
        QDATA DAC_input;
        float system_voltage;
    
        // The function compute_pressure() can return a value of -1.0 PSI
        // This indicates an error.     See misc_stuff.h
        if( current_pressure == PRESSURE_ERROR_VALUE )
        {
        	// Program the DAC to 125 mV so the operator knows.
        	// Also useful when doing screening of incoming parts,
        	// you will know the DAC is operating.
        	write_DACV( INVALID_PRESSURE_ERROR );
            return;
        }
    
        pressure_samples[pressure_samples_index++] = current_pressure;
    
        if( pressure_samples_index >= LOPS )
        {
            pressure_samples_index = 0;
        }
    
        // calculate the average pressure
        avg_pressure.float_num = 0;
    
        for(i=0; i<LOPS; i++)
        {
            avg_pressure.float_num += pressure_samples[i];
        }
    
        avg_pressure.float_num /= LOPS;
    
        // calculate the voltage output
    
        system_voltage = (( system_slope * avg_pressure.float_num ) + system_offset );
    
        // convert the voltage to a DAC setting
        DAC_register =  (DOUBLET)(system_voltage * 819.2);
    
        // left shift 4 bits
        DAC_register <<= 4;
    
        // program the DAC
        DAC_input.quadlet = 0;
        DAC_input.doublet[0] = DAC_register;
        DAC_input.byte[2] = 0x18;
    
        write_DACV( DAC_input.quadlet );
    
    }   // end of convert_pressure_to_voltage() ***************************************
    
    
    
    void write_DACV( QUADLET value )
    {
    	// write to DAC7562, 0-5V output
    
        QDATA temp;
        BYTE busy;
    
        // experimental !!!!!!!
        USCI_B_SPI_enable( USCI_B0_BASE );  // enables operation of the SPI block
    
        // assert low during SPI activity
        // signal DAC_/SYNC_A
        GPIO_setOutputLowOnPin( GPIO_PORT_P2, GPIO_PIN7 );
    
        // parse the input value
        temp.quadlet = value;
    
        // send first byte
        USCI_B_SPI_transmitData( USCI_B0_BASE, temp.byte[2] );
    
        while( true )
        {
            busy = USCI_B_SPI_isBusy( USCI_B0_BASE );
    
            if( busy == USCI_B_SPI_NOT_BUSY )
            {
                break;
            }
        }
    
        // send 2nd byte
        USCI_B_SPI_transmitData( USCI_B0_BASE, temp.byte[1] );
    
        while( true )
        {
            busy = USCI_B_SPI_isBusy( USCI_B0_BASE );
    
            if( busy == USCI_B_SPI_NOT_BUSY )
            {
                break;
            }
        }
    
        // send 3rd byte
        USCI_B_SPI_transmitData( USCI_B0_BASE, temp.byte[0] );
    
        while( true )
        {
            busy = USCI_B_SPI_isBusy( USCI_B0_BASE );
    
            if( busy == USCI_B_SPI_NOT_BUSY )
            {
                break;
            }
        }
    
        // deassert after SPI activity is complete
        // signal DAC_/SYNC_A
        GPIO_setOutputHighOnPin( GPIO_PORT_P2, GPIO_PIN7 );
    
        return;
    
    }   // end of write_DACV() ******************************************************
    
    
    
    void pressure_to_current( float current_pressure )
    {
    	// This function is meant to be used with the AD5421,
    	// 4-20mA current loop regulator.
    
    	// It can be used on both the T6 ( via UCB0 ) or the LCD 4-20mA ( via UCA1 )
    
        extern void UCB0_write_DACI( BYTE command, DOUBLET value );
        extern void UCA1_write_DACI( BYTE command, DOUBLET value );
        extern DOUBLET vrs_ehc;
        BYTE i;
        QDATA avg_pressure;
        float i_value;
    
    
        // The function compute_pressure() can return a value of -1.0 PSI
        // This indicates an error.     See misc_stuff.h
        if( current_pressure == PRESSURE_ERROR_VALUE )
        {
    
        	switch ( vrs_ehc )
    		{
    			case VRS_EHC_4_20MA:
    
    		  		// program the 4-20mA output, on UCB0
    				// set the AD5421 to the error current, 3.20mA
    				UCB0_write_DACI( 0x06, 0x0000 );
    		  		break;
    
    		  	case VRS_EHC_LCD_4_20MA:
    
    		  		// program the 4-20mA output, on UCA1
    		  		// set the AD5421 to the error current, 3.20mA
    		  		UCA1_write_DACI( 0x06, 0x0000 );
    		  		break;
    
    		  	default:
    		  		break;
    
    		}	// end of switch ***************************************************
            return;
        }
    
        pressure_samples[pressure_samples_index++] = current_pressure;
    
        if( pressure_samples_index >= LOPS )
        {
            pressure_samples_index = 0;
        }
    
        // calculate the average pressure
        avg_pressure.float_num = 0;
    
        for(i=0; i<LOPS; i++)
        {
            avg_pressure.float_num += pressure_samples[i];
        }
    
        avg_pressure.float_num /= LOPS;
    
        // calculate the current loop output
    
        i_value = ((avg_pressure.float_num / full_scale_pressure.float_num) * 65535.0 );
    
    	switch ( vrs_ehc )
    	{
    		case VRS_EHC_4_20MA:
    
    	  		// program the 4-20mA output, on UCB0
    			// write to the DAC register
    			UCB0_write_DACI( 0x01, (DOUBLET)i_value );
    
    			// Load the DAC
    			UCB0_write_DACI( 0x05, 0x0000 );
    
    	  		break;
    
    	  	case VRS_EHC_LCD_4_20MA:
    
    	  		// program the 4-20mA output, on UCA1
    	  		// set the AD5421 to the error current, 3.20mA
    	  		UCA1_write_DACI( 0x01, (DOUBLET)i_value );
    
    	  		// Load the DAC
    	  		UCA1_write_DACI( 0x05, 0x0000 );
    
    	  		break;
    
    	  	default:
    	  		break;
    
    	}	// end of switch *******************************************************
    
        return;
    
    }   // end of pressure_to_current() ********************************************
    
    
    void write_byte_LCD( BYTE value, BYTE A0 )
    {
    
    	// write a byte to the Graphics Display
    
    	BYTE busy;
    
    	// assert P2.7 for signal LCD_/CS1
    	GPIO_setOutputLowOnPin( GPIO_PORT_P2, GPIO_PIN7 );
    	// This bit is from P2.5
    	// It is used by the LCD interface to distinguish
    	// between command data, and display data.
    	if( A0 )
    	{
    		// set LCD_A0, Display Data
    		GPIO_setOutputHighOnPin( GPIO_PORT_P2, GPIO_PIN5 );
    	}
    	else
    	{
    		// clear LCD_A0, Command Data
    		GPIO_setOutputLowOnPin( GPIO_PORT_P2, GPIO_PIN5 );
    	}
    
        // write the byte
    	    USCI_B_SPI_transmitData( USCI_B0_BASE, value );
    
        while( true )
        {
            busy = USCI_B_SPI_isBusy( USCI_B0_BASE );
    
            if( busy == USCI_B_SPI_NOT_BUSY )
            {
                break;
            }
        }
    
        // de-assert P2.7 for signal LCD_/CS1
        GPIO_setOutputHighOnPin( GPIO_PORT_P2, GPIO_PIN7 );
    
        return;
    
    }	// end of write_byte_LCD() *************************************************
    
    
    void UCB0_write_DACI( BYTE command, DOUBLET value )
    {
    	// for the 4-20mA loop regulator ( AD5421 )
    
        DDATA temp;
        BYTE busy;
    
        // assert low during SPI activity
        // signal RGLTR_/SYNC
        GPIO_setOutputLowOnPin( GPIO_PORT_P2, GPIO_PIN7 );
    
        // parse the input value
        temp.doublet = value;
    
        // send first byte
        USCI_B_SPI_transmitData( USCI_B0_BASE, command );
    
        while( true )
        {
            busy = USCI_B_SPI_isBusy( USCI_B0_BASE );
    
            if( busy == USCI_B_SPI_NOT_BUSY )
            {
                break;
            }
        }
    
        // send 2nd byte
        USCI_B_SPI_transmitData( USCI_B0_BASE, temp.byte[1] );
    
        while( true )
        {
            busy = USCI_B_SPI_isBusy( USCI_B0_BASE );
    
            if( busy == USCI_B_SPI_NOT_BUSY )
            {
                break;
            }
        }
    
        // send 3rd byte
        USCI_B_SPI_transmitData( USCI_B0_BASE, temp.byte[0] );
    
        while( true )
        {
            busy = USCI_B_SPI_isBusy( USCI_B0_BASE );
    
            if( busy == USCI_B_SPI_NOT_BUSY )
            {
                break;
            }
        }
    
        // deassert after SPI activity is complete
        // signal DAC_/SYNC_A
        GPIO_setOutputHighOnPin( GPIO_PORT_P2, GPIO_PIN7 );
    
        return;
    
    }   // end of write_regulator **************************************************
    
    
    
    void program_LCD_task( void )
    {
    	/*	I wanted to put this function into display.c, however a lot of
    	 * 	of overhead would have come along with the RTOS stuff.
    	 *
    	 * 	18-06-27	Got a crash of the RTOS when the function sprintf()
    	 * 	was executed. By increasing the stack size from 512 to 768 it
    	 * 	solved the problem.
    	 */
    
    	extern void reset_LCD( void );
        extern void configure_LCD( void);
        extern void clear_display_data( void );
        extern BYTE font_type;
        extern void write_string( BYTE x, BYTE y, char *str_ptr );
        extern void draw_pixel( DOUBLET column, DOUBLET row, BYTE data_bit );
        extern void write_display_data_to_LCD( void );
        extern void write_rectangle( BYTE x1, BYTE y1, BYTE x2, BYTE y2 );
        extern DOUBLET LCD_time_counter;
        extern BYTE LCD_units;
        extern BYTE LCD_units_graphic;
        extern DOUBLET vrs_ehc;
        extern float LCD_average_pressure;
        extern QUADLET read_VRS( BYTE offset );
        extern BYTE tank_level_state;
        extern char buffer[25];
        extern BYTE switch1_debounce_counter;
        extern bool debounce_switch1( bool reset );
        extern BYTE tank_level_state;
        extern void manage_ADC12_heater( void );
        extern void draw_tank( void );
        extern void prepare_to_sleep( void );
        extern void exp_sleep_prep( void );
    
        QDATA temp;
        float LCD_pressure;
    
    	while( 1 )
    	{
    
    		// this semaphore is posted in HES_task()
    		Semaphore_pend( LCD_sem, BIOS_WAIT_FOREVER );
    
    		if( vrs_ehc == VRS_EHC_LCD_4_20MA )
    		{
    		    manage_ADC12_heater();
    		}
    
    		// lock the mutex so an interrupt from the switches can't
    		// corrupt this function
    		Semaphore_pend( mutex_prog_LCD, BIOS_WAIT_FOREVER );
    
    		switch( LCD_state )
    		{
    			case LCD_IDLE:
    
    				// 3V stuff was powered up in init_GPIO()
    				// allow another 25mS for power stabilization
    				LCD_state = LCD_POWER_UP;
    				break;
    
    			case LCD_POWER_UP:
    
    				LCD_state = LCD_CONFIGURE;
    				break;
    
    			case LCD_CONFIGURE:
    
    				reset_LCD();
    
    				// this takes about 2mS to accomplish
    				clear_display_data();
    
    				configure_LCD();
    
    				font_type = LARGE_FONT;
    
    				write_string( 23, 8, "ORANGE" );
    				write_string( 10, 38, "RESEARCH" );
    
    				font_type = SMALL_FONT;
    
    				write_rectangle( 0, 0, 127, 63 );
    				write_rectangle( 1, 1, 126, 62 );
    
    				write_display_data_to_LCD();
    
    				LCD_state = LCD_DWELL_BOOT_SCREEN;
    
    				LCD_time_counter = 0;
    
    				LCD_units = LBS_PER_SQUARE_INCH;	// default
    
    				break;
    
    			case LCD_DWELL_BOOT_SCREEN:
    
    				LCD_time_counter++;
    
    				if( LCD_time_counter > LCD_DWELL_TIME_COUNT )
    				{
    					// it is time to move on, and draw the operation screen
    					LCD_state = LCD_PREPARE_TO_GATHER_SAMPLES;
    				}
    
    				break;
    
    			case LCD_PREPARE_TO_GATHER_SAMPLES:
    
    			    // The LCD 4-20mA does not have a battery !
    			    if( vrs_ehc == VRS_EHC_LCD_BATTERY )
    			    {
    			        // get the input to the ADC powered-up so it is stabilzed
    			        ENABLE_BATLVL_PWR;
    			        __no_operation();
    			        // Initiate the first conversion.
    			        // The finished conversion value will be available
    			        // when this function is revisited 25mS from now.
    			        START_ADC12_CONVERSION;
    			    }
    
    				LCD_average_pressure = 0;
    				LCD_time_counter = 0;
    
    				LCD_choice = CHOICE_SF_HOME;
    
    				LCD_state = LCD_GATHER_SAMPLES;
    
    				/* this battery stuff is disabled for now
    				 * in I2C_UCB1.c, If HES_data_is_good,
    				 * the latest pressure is written to the VRS
    
    				average_battery_level = 0;
    				// This will make the averaging process start over
    				// and collect new samples.  See compute_pressure() in SPI_UCB0.c
    				// A timer0 interrupt will occur, causing compute_pressure() to be called,
    				// and this variable to be incremented.
    				HES_avg_index = 0;
    
    				*/
    
    				break;
    
    			case LCD_GATHER_SAMPLES:
    
    
    				temp.quadlet = read_VRS( VRS_PRESSURE_OFFSET );
    
    				LCD_average_pressure += temp.float_num;		// sum the samples
    
    				LCD_time_counter++;
    
    				if( LCD_time_counter >= NOPS )
    				{
    					// all samples have been summed
    					LCD_average_pressure /= ((float) NOPS);
    
    					LCD_state = LCD_DRAW_OPERATING_SCREEN;
    				}
    
    				/*
    				if( tank_level_state == TANK_PREPARING_TO_SET_FULL )
    				{
    					// In the switch2 ISR
    					// the operator selected to set the tank as full
    					LCD_full_tank_pressure = LCD_average_pressure;
    					tank_level_state = TANK_WAS_FILLED;
    				}
    				*/
    
    				break;
    
    			case LCD_DRAW_OPERATING_SCREEN:
    
    				reset_LCD();		// this takes about 25uS to execute
    				configure_LCD();	// sets up all of the misc. registers in the LCD
    
    				clear_display_data();
    
    				/*
    				// check to see if the battery level is OK
    				// this ADC level corresponds with a battery voltage of 4.5V
    				if( average_battery_level <= FOUR_AND_ONE_HALF_VOLTS )
    				{
    					// the battery is low !
    					// post a warning
    					sprintf(buffer, "Low Bat" );
    					write_string( 86, 0, buffer );
    				}
    				*/
    
    
    
    				switch( LCD_units )
    				{
    					case MILLIMETERS_H2O:
    						LCD_pressure = (  LCD_average_pressure * 7.0309E2 );
    						sprintf(buffer, "%d mm H2O dP", (DOUBLET)LCD_pressure );
    
    						break;
    
    					case INCHES_H2O:
    						LCD_pressure = (  LCD_average_pressure * 2.7680E1 );
    						sprintf(buffer, "%4.1f in H2O dP", LCD_pressure );
    						break;
    
    					case LBS_PER_SQUARE_INCH:
    						LCD_pressure = LCD_average_pressure;
    						sprintf(buffer, "%4.2f PSI dP", LCD_pressure );
    						break;
    
    					default:
    						break;
    
    				}	// end of switch( LCD_units )
    
    
    				// display the resultant string
    				write_string( 41, 42, buffer );
    
    				// Remember:  The native pressuure units are PSI
    
    
    				// Do not draw the tank if it has never been filled !
    				if( tank_level_state == TANK_WAS_FILLED )
    				{
    				    draw_tank();
    				}
    
    
    				write_display_data_to_LCD();
    				LCD_time_counter = 0;
    
    				/*
    				LCD_level_choice = CHOICE_SF_HOME;	// init to default state
    
    				// Testing of the membrane switches shows that they have a significant
    				// amount of bouncing.
    				// Instead of enabling the switch2 interrupt here, delay this.
    				// A state machine using the variable switch_counter is
    				// incremented every 10mS. See timer_A0.c
    
    				switch_counter = SWITCH_DEBOUNCE_INITIATE;
    				CLEAR_SWITCH2_INTERRUPT;
    
    				// Enable sw3 for the back light
    				CLEAR_SWITCH3_INTERRUPT;
    				ENABLE_SWITCH3_INTERRUPT;
    				*/
    
    
    
    				CLEAR_SWITCH2_INTERRUPT;
    				ENABLE_SWITCH2_INTERRUPT;
    
    				CLEAR_SWITCH3_INTERRUPT;
    				ENABLE_SWITCH3_INTERRUPT;
    
    				LCD_state = LCD_OPERATING_SCREEN_WAITING;
    				break;
    
    			case LCD_OPERATING_SCREEN_WAITING:
    
    				LCD_time_counter++;
    
    				// The Switch2 interrupt is currently enabled
    				// so that we can get into the programming states
    
    				if( vrs_ehc == VRS_EHC_LCD_BATTERY )
    				{
    
    					// Do not sleep if the flag in the status register is set
    					if( (read_VRS( VRS_STATUS_OFFSET ) & VRS_STATUS_FLAG_DO_NOT_SLEEP) == 0  )
    					{
    						// Is it time to go to sleep ?
    						if(  LCD_time_counter >= AWAKE_TIME )
    						{
    							// It is time to sleep !
    							LCD_state = LCD_SLEEPING;
    
    							exp_sleep_prep();
    
    							__bis_SR_register( 0x00F0 );
    
    						}
    					}
    				}
    
    			    if( vrs_ehc == VRS_EHC_LCD_4_20MA )
    			    {
    			        	// This device does not go to sleep.
    				        // It must continue to service the 4-20mA Regulator.
    				        // However, the LCD is blanked.
    
    				        // Is it time to blank the LCD ?
    				        if( LCD_time_counter >= AWAKE_TIME )
    				        	{
    				        		// It is time to blank the LCD !
    
    				                // The interrupt will be enabled in program_LCD(),
    				                // as it finishes drawing the operating screen.
    				                DISABLE_SWITCH3_INTERRUPT;  // the backlight switch
    				                CLEAR_SWITCH3_INTERRUPT;
    
    				                LCD_state = LCD_BLANKED;
    				                DISABLE_BKLT_PWR;
    				                clear_display_data();
    				                write_display_data_to_LCD();
    
    				                // The display is refreshed when Switch2 is depressed,
    				                // causing an Interrupt.
    				                // see switches.c,  case LCD_BLANKED:
    				            }
    			    }
    
    			    break;
    
    			case LCD_DRAW_SET_FULL_SCREEN:
    
    				// One of the Program Modes
    				// If Switch2 is activated, while in LCD_OPERATING_SCREEN_WAITING,
    				// the interrupt will get you here.
    				clear_display_data();
    				write_string( 0, 0, "Set Full ?" );
    
    				if( LCD_choice == CHOICE_SF_UNITS )
    				{
    					write_string( (WOF+1),  HOF   , "   =  Units" );
    				}
    				else
    				{
    					write_string( (WOF+1),  HOF   , "      Units" );
    				}
    
    				if( LCD_choice == CHOICE_SF_YES )
    				{
    					write_string( (WOF+1), (HOF*2), "   =  Yes" );
    				}
    				else
    				{
    					write_string( (WOF+1), (HOF*2), "      Yes" );
    				}
    
    				if( LCD_choice == CHOICE_SF_HOME )
    				{
    					write_string( (WOF+1), (HOF*3), "   =  Home" );
    				}
    				else
    				{
    					write_string( (WOF+1), (HOF*3), "      Home" );
    				}
    
    				write_display_data_to_LCD();
    				LCD_time_counter = 0;
    				CLEAR_SWITCH1_INTERRUPT;	// the arrow button
    				CLEAR_SWITCH2_INTERRUPT;	// On - Select button
    				debounce_switch1( 1 ); // reset
    				LCD_units_graphic = UNITS_CHOICE_HOME;
    
    				LCD_state = LCD_SET_FULL_WAITING;
    
    				break;
    
    			case  LCD_SET_FULL_WAITING:
    
    				LCD_time_counter++;
    
    				// switch1 needs debouncing before the interrupt is enabled
    				if( debounce_switch1(0) == false )
    				{
    					break;	// switch1 is still bouncing
    				}
    
    				CLEAR_SWITCH1_INTERRUPT;
    				ENABLE_SWITCH1_INTERRUPT;
    
    				CLEAR_SWITCH2_INTERRUPT;
    				ENABLE_SWITCH2_INTERRUPT;
    
    				if( vrs_ehc == VRS_EHC_LCD_4_20MA )
    				{
    					// Has this screen has been idle for too long ?
    					if( LCD_time_counter >= AWAKE_TIME )
    					{
    						// It is time to return to the operating screen
    						LCD_state = LCD_PREPARE_TO_GATHER_SAMPLES;
    
    						// The interrupt will be enabled in program_LCD(),
    						// as it finishes drawing the operating screen.
    					}
    				}
    
    				break;
    
    			case  LCD_DRAW_SET_UNITS_SCREEN:
    				// draw the units screen
    
    				LCD_time_counter = 0;
    
    				clear_display_data();
    
    				if( LCD_units_graphic == UNITS_CHOICE_MILLIMTERS_H2O )
    				{
    					write_string( (WOF+1),  0, 			"  =  mm H2O" );
    				}
    				else
    				{
    					write_string( (WOF+1),  0, 			"     mm H2O" );
    				}
    
    				if( LCD_units_graphic == UNITS_CHOICE_INCHES_H2O	)
    				{
    					write_string( (WOF+1), (HOF*1), 	"  =  in H2O" );
    				}
    				else
    				{
    					write_string( (WOF+1),  (HOF*1), 	"     in H2O" );
    				}
    
    				if( LCD_units_graphic == UNITS_CHOICE_PSI )
    				{
    					write_string( (WOF+1),  (HOF*2), 	"  =  PSI  " );
    				}
    				else
    				{
    					write_string( (WOF+1),  (HOF*2), 	"     PSI  " );
    				}
    
    				if( LCD_units_graphic == UNITS_CHOICE_HOME )
    				{
    					write_string( (WOF+1),  (HOF*3), 	"  =  Home " );
    				}
    				else
    				{
    					write_string( (WOF+1),  (HOF*3), 	"     Home " );
    				}
    
    				write_display_data_to_LCD();
    
    				debounce_switch1(1);	// reset
    
    				// wait here so that the operator can make a choice of units
    				LCD_state = LCD_SET_UNITS_WAITING;
    
    				break;
    
    			case  LCD_SET_UNITS_WAITING:
    
    				LCD_time_counter++;
    
    				// switch1 needs debouncing before the interrupt is enabled
    				if( debounce_switch1(0) == false )
    				{
    					break;	// switch1 is still bouncing
    				}
    
    				CLEAR_SWITCH1_INTERRUPT;
    				ENABLE_SWITCH1_INTERRUPT;
    
    				CLEAR_SWITCH2_INTERRUPT;
    				ENABLE_SWITCH2_INTERRUPT;
    
    				if( vrs_ehc == VRS_EHC_LCD_4_20MA )
    				{
    					// Has this screen has been idle for too long ?
    					if( LCD_time_counter >= AWAKE_TIME )
    					{
    						// It is time to return to the operating screen
    						LCD_state = LCD_PREPARE_TO_GATHER_SAMPLES;
    
    						// The interrupt will be enabled in program_LCD(),
    						// as it finishes drawing the operating screen.
    					}
    				}
    
    				break;
    
    			case LCD_BLANKED:
    
    			    __no_operation();
    
    			    break;
    
    
    			default:
    				break;
    
    		}	// end of switch LCD_state *****************************************
    
    		// unlock the mutex so a switch interrupt can modify LCD_state
    		Semaphore_post( mutex_prog_LCD );
    	}	// end of while() ******************************************************
    
    }	// end of progam_LCD_task() *************************************************
    
    
    misc_stuff.h
    3716.main.c
    
    /*		Interface Assignments
     *
     *
     * 				UCB1			UCB0			UCA1			UCA0
     *
     *
     * 	T5			I2C,			SPI DAC,		not				UART,
     *				HES				0.5-4.5V		used			RX, TX
     *
     *	T6			I2C,			SPI DAC,		not				UART,
     *				HES				4-20mA			used			RX, TX
     *
     * 	LCD 		I2C,			SPI				not				UART,
     *	Battery		HES				Display			used			RX, TX
     *
     *	LCD 		I2C,			SPI				SPI				UART
     *	4-20mA		HES				Display			4-20mA			RX, TX
     *
     */
    
    
    /*
     * 		Error
     * 		Outputs				T5			T6
     *
     * 		Loss of
     * 		communication		none		3.20mA
     * 		with 4-20mA
     * 		Regulator
     *
     *
     * 		I2C Bus Error		0.250V		3.20mA
     *
     *
     * 		Not Calibrated		0.125V		3.20mA
     *
     *
     *
     */
    
    
    
    
    /* XDCtools Header files */
    #include <xdc/std.h>
    #include <stdio.h>
    
    #include <xdc/runtime/log.h>
    
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/hal/Hwi.h>
    
    /* TI-RTOS Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/I2C.h>
    #include <ti/drivers/i2c/I2CUSCIB.h>
    #include <ti/drivers/uart/UARTUSCIA.h>  // contains "bool"
    
    // This was added 6.16.16 so that the symbols generated by .cfg
    // can be recognized
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/System.h>
    
    /* Board Header file */
    #include "my_board.h"
    
    // NOTE:  driverlib.h will include all of the other header files
    // that are associated with the driver library
    #include <driverlib.h>
    #include "com.h"
    
    
    
    unsigned int LED_count = 0;
    
    
    
    // Interrupt vector for P2.0, P2.1, and P2.2
    // Operate the On button to wakeup from LPM4 (when switch S2 is activated).
    // See the .cfg using XGCONF, where this ISR has been defined
    void switches_ISR( void )
    {
    	extern BYTE LCD_state;
    	extern BYTE LCD_choice;
    	// determines what units will be displayed in the operating screen
    	extern BYTE LCD_units;
    	// determines the graphic for the set units screen
    	extern BYTE LCD_units_graphic;
    	extern BYTE tank_level_state;
    	extern DOUBLET vrs_ehc;
    	extern bool set_full;
    	extern DOUBLET TA0CTL_value, TA1CTL_value, TA2CTL_value;
        extern DOUBLET flag_average_battery_level_ready;    // needs work !!!
        extern void init_tactile_switches( void );
    
        // Bool clock0_state;
    
    	// lock the mutex so execution of program_LCD_task() can't
    	// corrupt the LCD operation.
    	Semaphore_pend( mutex_prog_LCD, BIOS_WAIT_FOREVER );
    
    
        // Did P2.2 ( switch3 ) cause this interrupt ?
        if( P2IFG & 0x04 )
        {
            CLEAR_SWITCH3_INTERRUPT;
            DISABLE_SWITCH3_INTERRUPT;
    
            switch ( vrs_ehc )
            {
    
            case VRS_EHC_LCD_BATTERY:
            /*
                // You cannot enable the backlight until the battery voltage
                // has been measured.   See program_LCD(), SPI_UCB0.c
                if( flag_average_battery_level_ready )
                {
                    if( average_battery_level > FOUR_AND_ONE_HALF_VOLTS )
                    {
                        // enable the Back Light
                        ENABLE_BKLT_PWR;
                    }
                }
                // Note:  The Back Light will be disabled when the unit goes back
                // to sleep.
            */
                break;
    
            case VRS_EHC_LCD_4_20MA:
    
                // If the LCD is blanked you do Not want to enable the backlight !
                if( LCD_state != LCD_BLANKED )
                {
                    // enable the Back Light
                    ENABLE_BKLT_PWR;
                }
    
                break;
    
            default:
                break;
    
            }   // end of switch
    
    
        }   // end of if( P2IFG & 0x04 )
    
    
    
    	// Did P2.1 (switch2) cause this interrupt ?
    	if( P2IFG & 0x02 )
    	{
    
    		CLEAR_SWITCH2_INTERRUPT;
    		DISABLE_SWITCH2_INTERRUPT;
    
    		switch ( LCD_state )
    		{
    
    			case LCD_BLANKED:
    
    				LCD_state = LCD_PREPARE_TO_GATHER_SAMPLES;
    
    				break;
    
    			case LCD_SLEEPING:
    
    	            LCD_state = LCD_PREPARE_TO_GATHER_SAMPLES;
    
    	            // Restore TA0CTL.  A copy was made in exp_sleep_prep()  [display.c],
    	            // before going into LPM4
    	            TA0CTL = TA0CTL_value;
    
                    CLR_SMCLKOFF;   // get the SMCLK operating
    
                    // __bic_SR_register_on_exit( 0xF0 );
    
    				break;
    
    			case LCD_OPERATING_SCREEN_WAITING:
    
    				LCD_state = LCD_DRAW_SET_FULL_SCREEN;
    
    				break;
    
    			case LCD_SET_FULL_WAITING:
    
    				if( LCD_choice == CHOICE_SF_UNITS   )
    				{
    					LCD_state = LCD_DRAW_SET_UNITS_SCREEN;
    				}
    
    
    				if( LCD_choice == CHOICE_SF_YES  )
    				{
    					LCD_state = LCD_PREPARE_TO_GATHER_SAMPLES;
    					tank_level_state = TANK_WAS_FILLED;
    					// this will cause the tank level to be set as full
    					set_full = true;
    				}
    
    
    				break;
    
    			case LCD_SET_UNITS_WAITING:
    
    				switch ( LCD_units_graphic )
    				{
    					case UNITS_CHOICE_PSI:
    						LCD_units = LBS_PER_SQUARE_INCH;
    						break;
    
    					case UNITS_CHOICE_INCHES_H2O:
    						LCD_units = INCHES_H2O;
    						break;
    
    					case UNITS_CHOICE_MILLIMTERS_H2O:
    						LCD_units = MILLIMETERS_H2O;
    						break;
    
    					default:
    						break;
    				}	// end of switch
    
    				LCD_state = LCD_PREPARE_TO_GATHER_SAMPLES;
    
    				break;
    
    			default:
    				break;
    		}	// end of switch
    
    	}	// end of if( P2IFG & 0x02 )
    
    
    	// Did P2.0 ( switch1 ) cause this interrupt ?
    	if( P2IFG & 0x01 )
    	{
    
    		CLEAR_SWITCH1_INTERRUPT;
    		DISABLE_SWITCH1_INTERRUPT;
    
    		switch ( LCD_state )
    		{
    			case LCD_SET_FULL_WAITING:
    
    				LCD_choice++;
    				if( LCD_choice > CHOICE_SF_UNITS )
    				{
    					LCD_choice = CHOICE_SF_HOME;
    				}
    				// now redraw the Set Full Screen
    				LCD_state = LCD_DRAW_SET_FULL_SCREEN;
    
    				break;
    
    			case LCD_SET_UNITS_WAITING:
    
    				LCD_units_graphic++;
    				if( LCD_units_graphic >  UNITS_CHOICE_MILLIMTERS_H2O )
    				{
    					LCD_units_graphic = UNITS_CHOICE_HOME;
    				}
    				// now redraw the Set Units Screen
    				LCD_state = LCD_DRAW_SET_UNITS_SCREEN;
    
    				break;
    
    			default:
    				break;
    		}
    
    
    
    	}	// end of if( P2IFG & 0x01 )
    
    	// unlock the mutex so program_LCD_task() can operate the LCD
    	Semaphore_post( mutex_prog_LCD );
    
    }	// end of switches_ISR() ***************************************************
    
    
    Void heartBeatFxn( void )
    {
    
    	LED_count++;
    
    	// timer0 is set up to interrupt every 25mS, so it occurs 40 times per second
    
    	// operate the Hall Effect Sensor ( AS5510 )
    	// It occurs 40 times/second ( every 25mS )
    
    	Semaphore_post( HES_sem );
    
    
    	if( LED_count == 39 )
    	{
    		// enable LED1 for 25mS
    		GPIO_write(LED1, LED1_ON);
    	}
    	else
    	{
    		GPIO_write(LED1, LED1_OFF);
    	}
    
    	if( LED_count >= 40 )
    	{
    		LED_count = 0;
    	}
    
    }   // end of  heartBeatFxn() **************************************************
    
    void init( void )
    {
    	extern void init_GPIO( void );
    	extern void init_I2C( void );
    	extern void init_UART( void );
    	extern void init_UCB0( void );
    	extern void init_UCA1( void );
    	extern void init_VRS( void );
    	extern void set_vcore_up( void );
    	extern void init_ADC12( void );
    
    
    	set_vcore_up();
    
    	init_VRS();
    
    	// The USB LDO's need to be disabled
    	// If not disabled you will draw about 25uA in LPM4 mode !
        USBKEYPID = 0x9628; // unlock the USB registers
        // clear these bits to disable the on board LDOs
        // SLDOEN, VUSBEN, SLDOAON
        USBPWRCTL &= 0xE7BF;
        USBKEYPID = 0x0000; // lock the USB registers
    
    	/* Call board init functions */
    	init_GPIO();
    	init_UART();
    	init_UCB0();
    	init_UCA1();
    	init_I2C();
    	init_ADC12();
    
    	/* Turn off user LED  */
    	GPIO_write(LED1, LED1_OFF);
    
    	init_ADC12();
    
    	return;
    
    }	// end of init() ***********************************************************
    
    
    int main(void)
    {
    
    	init();
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    
    }   // end of main() ***********************************************************
    
    I2C_UCB1.c
    /*
     * I2C_UCB1.c
     *
     *  Created on: Jul 5, 2016
     *      Author: roy
     */
    
    
    #include <Debug/configPkg/package/cfg/empty_min_pe430X.h>
    #include <gpio.h>
    #include <msp430f5528.h>
    #include <my_board.h>
    #include <stdbool.h>
    #include <ti/drivers/i2c/I2CUSCIB.h>
    #include <ti/drivers/I2C.h>
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Semaphore.h>
    
    // This was added 4.26.18 so that the symbols generated by .cfg
    // can be recognized
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/System.h>
    
    #include <usci_b_i2c.h>
    #include <xdc/std.h>
    #include <misc_stuff.h>
    #include "com.h"
    // added for uart testing
    #include <ti/drivers/UART.h>
    #include "ADC12.h"
    
    // added 4.6.2018 to support DAC SPI bus implementation
    #include <driverlib.h>
    
    // AS5510 stuff
    
    #define SENS_25mT                                               1
    
    #define DATA_REG_ADDR                                           0x00
    #define SPD_POL_PWR_REG_ADDR                                    0x02
    #define REG_0x02_SlowMode_ReversePolarity_PowerDown             0x07
    #define REG_0x02_SlowMode_ReversePolarity_PowerUp               0x06
    #define SENS_REG_ADDR                                           0x0B
    
    // state constants for the Hall Effect Sensor (HES)
    #define HES_IDLE                0
    #define HES_INIT_DEVICE         1   // this only occurs once at power-up
    // After initialization is done, this is executed every time the
    // heartBeatFxn() is called.    See main.c
    #define HES_READ_DATA           2
    
    #define I2C_BUS_ERROR       0x8000
    
    
    #define OFFSET_CODE_ERROR      -1
    
    // Length Of Hall Effect Sensor Averaging Data
    #define LOHESAD     16
    
    #define I2C_ERROR_OUTPUT_VOLTAGE   0x180CD0   // 0.25 Volts
    #define I2C_ERROR_OUTPUT_CURRENT   0x180CD0   // 22 milliAmps
    
    // This constant determines the amount of time allowed for a hung I2C transfer.
    // I have searched diligently, and cannot find good information.
    // Even the forum could not give me a straight answer. "Very dependant on system
    // clock speeds"
    // Experimentation has shown that some of the calls start timing out at a
    // value of 62.  So I will run with this value.
    #define I2C_TIMEOUT     	1000
    
    
    /*
     *   I do not know why but some of this I2C stuff needs to be defined,
     *   even though you are not using it!  Otherwise you will get an unresolved
     *   linker error(s)
     */
    I2CUSCIB_Object i2cDriver_objects[1];
    const I2CUSCIB_HWAttrs i2cDriver_hwattrs[1] =
    {
        {
             .baseAddr = USCI_B1_BASE,
             .clockSource = USCI_B_I2C_CLOCKSOURCE_SMCLK
        }
    };
    const I2C_Config I2C_config[] =
    {
        {
            .fxnTablePtr = &I2CUSCIB_fxnTable,
            .object      = &i2cDriver_objects[0],
            .hwAttrs     = &i2cDriver_hwattrs[0]
        },
        {NULL, NULL, NULL}
    };
    
    
    DOUBLET HES_avg_data[ LOHESAD ];
    BYTE HES_avg_index = 0;
    
    BYTE HES_state = HES_INIT_DEVICE;
    
    // This variable is incremented each time that I2C_bus_error() is called.
    // If enough errors accumulate, the Voltage Output is set to 0.25V
    // If one good HES data acquistion occurs, the counter is cleared.
    BYTE I2C_error_counter = 0;
    
    BYTE uart_write_buffer[10] = {0,0,0,0,0,0,0,0,0,0};	// for uart testing
    extern UART_Handle uart_handle;
    
    DOUBLET I2C_transfer_failures = 0;
    DOUBLET OCF_failures = 0;
    
    // driver for the I2C Bus
    USCI_B_I2C_initMasterParam HES_i2c_params = {0};
    
    
    
    void init_I2C( void )
    {
    	extern void wait_until_I2C_bus_is_idle ( void );
    
    	UInt i;
    
    	// see MSP430F5xx_6xx DriverLib Users Guide
    	// This setting should allow the I2C module to control
    	// the directions of the pins.
    	// pin 43, UCB1SCL (HES_SCL), P4.2
    	// pin 42, UCB1SDA (HES_SDA), P4.1
    	GPIO_setAsPeripheralModuleFunctionInputPin( GPIO_PORT_P4,
    		GPIO_PIN2 | GPIO_PIN1);
    
    	HES_i2c_params.selectClockSource = USCI_B_I2C_CLOCKSOURCE_SMCLK;
    
    	HES_i2c_params.i2cClk = UCS_getSMCLK();
    
    	HES_i2c_params.dataRate = USCI_B_I2C_SET_DATA_RATE_100KBPS;
    
    	USCI_B_I2C_initMaster( USCI_B1_BASE, &HES_i2c_params );
    
    	// slave address for the AS5510
    	USCI_B_I2C_setSlaveAddress( USCI_B1_BASE, 0x56 );
    
    	USCI_B_I2C_setMode( USCI_B1_BASE, USCI_B_I2C_TRANSMIT_MODE );
    
    	USCI_B_I2C_enable( USCI_B1_BASE );
    
    	// clear averaging buffer for the Hall Effect Sensor
    	for(i=0; i<LOHESAD; i++)
    	{
    	    HES_avg_data[i] = 0;
    	}
    
    }	// end of my_board_init_I2C() **********************************************
    
    
    
    void HES_task( void )
    {
    	extern QUADLET X;
    	extern QUADLET ram_VRS[LORVRS];
    	// QDATA sensor_data, avg_sensor_offset, slope, output_pressure;
    
    	extern BYTE continuous_readout_packet[ LOCRP ];
    	extern bool transmit_continuous_readout_packet( void );
    	extern QUADLET flash_VRS_lo[ (LOVRS/2) ];
    	extern QUADLET flash_VRS_hi[ (LOVRS/2) ];
    	extern bool coefficient_selection_mode;
    	extern void I2C_bus_error( void );
    	extern float compute_pressure( DOUBLET HES_data );
    	extern void pressure_to_voltage( float current_pressure );
    	extern void pressure_to_current( float current_pressure );
    	extern bool calibrate_mode;
    	extern bool test_mode;
    	extern bool write_VRS( QUADLET data, BYTE offset );
    	extern QUADLET read_VRS( BYTE offset );
    	extern BYTE I2C_error_counter;
    	extern void wait_until_I2C_bus_is_idle ( void );
    	extern DOUBLET vrs_ehc;
    
    	uint8_t value_of_sens_reg = 0;
    	BYTE value_of_spd_pol_pwr_reg = 0;
    	QDATA HES_data;
    	QDATA pressure;
    	BYTE i;
    	bool i2c_transfer_success;
    	bool read_success;
    	bool  HES_data_is_good;
    
    	while( 1 )
    	{
    		// This semaphore is posted once, under the control of the heartbeat function
    		Semaphore_pend( HES_sem, BIOS_WAIT_FOREVER );
    
    		switch ( HES_state )
    		{
    
    		    case HES_INIT_DEVICE:
    
    		        // program the sensitivity register
    		        // only occurs once at power-up
    
    		        // write pointer
    		        i2c_transfer_success =
    		                USCI_B_I2C_masterSendSingleByteWithTimeout(
    		                        USCI_B1_BASE, SENS_REG_ADDR, I2C_TIMEOUT );
    		        if( i2c_transfer_success == false )
    		        {
    		            // failure !
    		            I2C_error_counter++;
    		            I2C_bus_error();
    		            break;
    		        }
    
    		        wait_until_I2C_bus_is_idle();
    
    		        // Read the current contents of the sensitiviy register
    		        i2c_transfer_success =
    		                USCI_B_I2C_masterReceiveSingleStartWithTimeout(
    		                        USCI_B1_BASE, I2C_TIMEOUT );
    		        if( i2c_transfer_success == false )
    		                        {
    		                            // failure !
    		                            I2C_error_counter++;
    		                            I2C_bus_error();
    		                            break;
    		                        }
    
    		        // read the value from the USCI_B register
    		        value_of_sens_reg = USCI_B_I2C_masterReceiveSingle(
    		                USCI_B1_BASE );
                    // we want 25 mT
                    // clear bits Sens1, Sens0
                    value_of_sens_reg &= 0xFC;
                    // set bit Sens0
                    value_of_sens_reg |= 0x01;
                    // write pointer for the sensitvity register
    
                    wait_until_I2C_bus_is_idle();
    
                    i2c_transfer_success =
                            USCI_B_I2C_masterSendMultiByteStartWithTimeout(
                                    USCI_B1_BASE, SENS_REG_ADDR, I2C_TIMEOUT );
                    if( i2c_transfer_success == false )
                    {
                        // failure !
                        I2C_error_counter++;
                        I2C_bus_error();
                        break;
                    }
    
    		        // no delay needed here
    
                    // write value of sensitvity register
                    i2c_transfer_success =
                            USCI_B_I2C_masterSendMultiByteNextWithTimeout(
                                    USCI_B1_BASE, value_of_sens_reg, I2C_TIMEOUT );
                    if( i2c_transfer_success == false )
                    {
                        // failure !
                        I2C_error_counter++;
                        I2C_bus_error();
                        break;
                    }
    
                    // no delay needed here
    
                    // write a Stop
                    i2c_transfer_success =
                            USCI_B_I2C_masterSendMultiByteStopWithTimeout(
                                    USCI_B1_BASE, I2C_TIMEOUT );
                    if( i2c_transfer_success == false )
                    {
                        // failure !
                        I2C_error_counter++;
                        I2C_bus_error();
                        break;
                    }
    
                    // move to the next state
                    HES_state = HES_READ_DATA;
                    break;
    
    		    case HES_READ_DATA:
    
    		        HES_data.quadlet = 0;
    
                    // configure for Slow mode, reverse polarity, and power-up
                    // read the speed, polarity, power register
    
                    // write pointer for the speed, polarity, power register
                    i2c_transfer_success =
                            USCI_B_I2C_masterSendSingleByteWithTimeout(
                                    USCI_B1_BASE, SPD_POL_PWR_REG_ADDR, I2C_TIMEOUT );
                    if( i2c_transfer_success == false )
                    {
                        // failure !
                        I2C_error_counter++;
                        I2C_bus_error();
                        break;
                    }
    
                    wait_until_I2C_bus_is_idle();
    
                    // Read the current contents of the
                    // speed, polarity, power register
                    i2c_transfer_success =
                            USCI_B_I2C_masterReceiveSingleStartWithTimeout(
                                    USCI_B1_BASE, I2C_TIMEOUT );
                    if( i2c_transfer_success == false )
                                    {
                                        // failure !
                                        I2C_error_counter++;
                                        I2C_bus_error();
                                        break;
                                    }
    
                    // read the value from the USCI_B register
                    value_of_spd_pol_pwr_reg = USCI_B_I2C_masterReceiveSingle(
                            USCI_B1_BASE );
    
    		        // clear bits: mode, polarity, power-down
    		        value_of_spd_pol_pwr_reg &= 0xF8;
    
    		        // set bits: slow mode, reverse polarity
    		        value_of_spd_pol_pwr_reg |= 0x06;
    
    		        wait_until_I2C_bus_is_idle();
    
                    // write pointer to the speed, polarity, power register
                    i2c_transfer_success =
                            USCI_B_I2C_masterSendMultiByteStartWithTimeout(
                                    USCI_B1_BASE, SPD_POL_PWR_REG_ADDR, I2C_TIMEOUT );
                    if( i2c_transfer_success == false )
                    {
                        // failure !
                        I2C_error_counter++;
                        I2C_bus_error();
                        break;
                    }
    
                    // no delay here
    
                    // write value of speed, polarity, power register
                    i2c_transfer_success =
                            USCI_B_I2C_masterSendMultiByteNextWithTimeout(
                                    USCI_B1_BASE, value_of_spd_pol_pwr_reg, I2C_TIMEOUT );
                    if( i2c_transfer_success == false )
                    {
                        // failure !
                        I2C_error_counter++;
                        I2C_bus_error();
                        break;
                    }
    
    		        // no delay here
    
                    // write a Stop
                    i2c_transfer_success =
                            USCI_B_I2C_masterSendMultiByteStopWithTimeout(
                                    USCI_B1_BASE, I2C_TIMEOUT );
                    if( i2c_transfer_success == false )
                    {
                        // failure !
                        I2C_error_counter++;
                        I2C_bus_error();
                        break;
                    }
    
    		        HES_data_is_good = false;
    		        read_success = true;
    		        //  Now that the device is woken up, try and get a reading.
    		        //
    		        //  It requires 250 uS (typical) for the AS5510 to
    		        //  wakeup from the low power state. 400uS elapses from the
    		        //  time that the part exits low power, to my first data read.
    		        //  So 3 attempts should be sufficient to find good data.
    		        //	In scope observations, the first attempt always works.
    		        for(i=0; i<3; i++)
    		        {
    		        	wait_until_I2C_bus_is_idle();
    
    		            // write pointer for lower data byte
    		            i2c_transfer_success =
    		                    USCI_B_I2C_masterSendSingleByteWithTimeout(
    		                        USCI_B1_BASE, DATA_REG_ADDR,
    		                        I2C_TIMEOUT );
    		            if( i2c_transfer_success == false )
    		            {
    		                read_success = false;
    		            }
    
    		            wait_until_I2C_bus_is_idle();
    
    		            // read lower data byte
    		            i2c_transfer_success = USCI_B_I2C_masterReceiveSingleStartWithTimeout(
    		                    USCI_B1_BASE, I2C_TIMEOUT );
    		            if( i2c_transfer_success == false )
    		            {
    		                read_success = false;
    		            }
    		            else
    		            {
    		                // read the value from the USCI_B register
    		                HES_data.byte[0] = USCI_B_I2C_masterReceiveSingle(
    		                        USCI_B1_BASE );
    		            }
    
    		            wait_until_I2C_bus_is_idle();
    
    		            // read upper data byte
                        i2c_transfer_success = USCI_B_I2C_masterReceiveSingleStartWithTimeout(
                                USCI_B1_BASE, I2C_TIMEOUT );
                        if( i2c_transfer_success == false )
                        {
                            read_success = false;
                        }
                        else
                        {
                            // read the value from the USCI_B register
                            HES_data.byte[1] = USCI_B_I2C_masterReceiveSingle(
                                    USCI_B1_BASE );
                        }
    
                        if( read_success == true )
                        {
                            // the data has been read correctly
                            // Check the OCF flag to make sure the part has had
                            // suffient time to wakeup.
    
                            if( HES_data.byte[1] & 0x08 )
                            {
                                // the OCF flag is set, the data is good
                                HES_data_is_good = true;
                                break;      // exit this loop
                            }
                        }
    
                        // go around for another read of the HES
    		        }
    
    		        // put the HES back into the low power state
    
    		        wait_until_I2C_bus_is_idle();
    
    		        // write pointer to the speed, polarity, power register
    		        i2c_transfer_success =
    		                USCI_B_I2C_masterSendSingleByteWithTimeout(
    		                        USCI_B1_BASE, SPD_POL_PWR_REG_ADDR, I2C_TIMEOUT );
    		        if( i2c_transfer_success == false )
    		        {
    		            // failure !
    		            I2C_error_counter++;
    		            I2C_bus_error();
    		            break;
    		        }
    
    		        wait_until_I2C_bus_is_idle();
    
                    // Read the current contents of the speed, polarity, power register
                    i2c_transfer_success =
                            USCI_B_I2C_masterReceiveSingleStartWithTimeout(
                                    USCI_B1_BASE, I2C_TIMEOUT );
                    if( i2c_transfer_success == false )
                    {
                        // failure !
                        I2C_error_counter++;
                        I2C_bus_error();
                        break;
                    }
    
                    // read the value from the USCI_B register
                    value_of_spd_pol_pwr_reg = USCI_B_I2C_masterReceiveSingle(
                            USCI_B1_BASE );
    
                    // clear bits: mode, polarity, power-down
                    value_of_spd_pol_pwr_reg &= 0xF8;
    
                    // set bits: slow mode, reverse polarity, Power Down
                    value_of_spd_pol_pwr_reg |= 0x07;
    
                    wait_until_I2C_bus_is_idle();
    
                    // write pointer to the speed, polarity, power register
                    i2c_transfer_success =
                            USCI_B_I2C_masterSendMultiByteStartWithTimeout(
                                    USCI_B1_BASE, SPD_POL_PWR_REG_ADDR, I2C_TIMEOUT );
                    if( i2c_transfer_success == false )
                    {
                        // failure !
                        I2C_error_counter++;
                        I2C_bus_error();
                        break;
                    }
    
    		        // no delay here
    
                    // write value of speed, polarity, power register
                    i2c_transfer_success =
                            USCI_B_I2C_masterSendMultiByteNextWithTimeout(
                                    USCI_B1_BASE, value_of_spd_pol_pwr_reg, I2C_TIMEOUT );
                    if( i2c_transfer_success == false )
                    {
                        // failure !
                        I2C_error_counter++;
                        I2C_bus_error();
                        break;
                    }
    
    		        // no delay here
    
                    // write a Stop
                    i2c_transfer_success =
                            USCI_B_I2C_masterSendMultiByteStopWithTimeout(
                                    USCI_B1_BASE, I2C_TIMEOUT );
                    if( i2c_transfer_success == false )
                    {
                        // failure !
                        I2C_error_counter++;
                        I2C_bus_error();
                        break;
                    }
    
    		        // we are done with the I2C bus !
    
                    if( HES_data_is_good )
                    {
                    	  I2C_error_counter = 0;	// reset the counter
    
                    	  // Write HES data into the VRS
                    	  write_VRS( HES_data.quadlet, VRS_HES_OFFSET );
    
                    	  if( calibrate_mode == false )
                    	  {
                    		  pressure.float_num = compute_pressure( HES_data.doublet[0] );
                    		  // Write pressure value into the VRS
                    		  write_VRS( pressure.quadlet, VRS_PRESSURE_OFFSET );
                    	  }
    
                    	  if( (calibrate_mode == false) & (test_mode == false)    )
                    	  {
                    		  switch ( vrs_ehc )
                    		  {
                    		  	  case VRS_EHC_VOLTAGE:
    
                    		  		  // now program the voltage output
                    		  		  pressure_to_voltage( pressure.float_num );
                    		  		  break;
    
                    		  	  case VRS_EHC_4_20MA:
    
                    		  		  // program the 4-20mA output
                    		  		  pressure_to_current( pressure.float_num  );
                    		  		  break;
    
                    		  	  case VRS_EHC_LCD_4_20MA:
    
                    		  		  // program the 4-20mA output
                    		  		  pressure_to_current( pressure.float_num  );
    
                    		  		  // see program_LCD_task() in display.c
                    		  		  Semaphore_post( LCD_sem );
    
                    		  		  break;
    
                    		  	case VRS_EHC_LCD_BATTERY:
    
                    		  	    // see program_LCD_task() in display.c
                    		  	    Semaphore_post( LCD_sem );
    
                    		  	    break;
    
    
    
                    		  	  default:
                    		  		  break;
                    		  }		// end of switch *******************************
                    	  }
    
                    }	// end of if( HES_data_is_good ) ***************************
                    /*
                     *
                     * if the HES data is Not Good,
                     * you should write an error value (into the VRS) for both the HES value and the
                     * pressure value.  In that way, any task trying to use thes values
                     * will know that it should Not !
                     *
                     */
    
                    break;
    
    		    default:
    		        break;
    
    		}   // end of switch ( HES_state )
    
    	}	// end of while( 1 ) ***************************************************
    
    }	// end of HES_task() *******************************************************
    
    void I2C_bus_error( void )
    {
        extern BYTE I2C_error_counter;
        extern bool write_VRS( QUADLET data, BYTE offset );
        extern void write_DACV( QUADLET value );
        extern void UCB0_write_DACI( BYTE command, DOUBLET value );
        extern void UCA1_write_DACI( BYTE command, DOUBLET value );
        extern DOUBLET vrs_ehc;
        // Write the error code into the VRS
        // When another process tries to use the HES data,
        // it will know that the last HES session failed
    
        write_VRS( I2C_BUS_ERROR, VRS_HES_OFFSET );
    
        if( I2C_error_counter >= 5 )
        {
    
        	// clearly, the HES data is not making its way to the uC
            switch ( vrs_ehc )
    		{
            	case VRS_EHC_VOLTAGE:
    
                    // set the output voltage to 0.25V
                    write_DACV( I2C_ERROR_OUTPUT_VOLTAGE );
    
            		break;
    
            	case VRS_EHC_4_20MA:
    
            		// force the alarm current (3.20mA) on the AD5421 loop regulator
            		UCB0_write_DACI( 0x06, 0x0000 );
    
            		break;
    
            	case VRS_EHC_LCD_4_20MA:
    
            		// force the alarm current (3.20mA) on the AD5421 loop regulator
            		UCA1_write_DACI( 0x06, 0x0000 );
    
            		break;
    
    
    
            	default:
            		break;
    
    		}	// end of switch ***************************************************
    
        }
    
    
        if( I2C_error_counter >= 250 )
        {
        	// it is time to roll over
            I2C_error_counter = 5;
    
            // Since this I2C bus failure has been going on for a long time,
            // try re-initializing the interface.
    
            init_I2C();
        }
    
        return;
    }   // end of I2C_bus_error() **************************************************
    
    
    float compute_pressure( DOUBLET HES_data )
    {
    
        extern int locate_offset( float HES_value );
        extern float calculate_pressure( int offset, float HES_value );
        extern DOUBLET HES_avg_data[ LOHESAD ];
        extern BYTE HES_avg_index;
    
        int offset;
        QDATA temp0;
    
        temp0.float_num = PRESSURE_ERROR_VALUE;
    
        // make sure the OCF flag from the AS5510 is set,
        // otherwise the data is no good
        if( (0x800 & HES_data) == 0 )
        {
            // do nothing, there is no data to work with
            return temp0.float_num;
        }
    
        // mask the OCF and parity bits
        HES_data &= 0x3FF;
    
        // make sure the HES value is OK
        if( HES_data > 1023 )
        {
            // The maximum output value for the AS5510 is 1023
            // do nothing
            return temp0.float_num;
        }
    
        /*
         * 5.30.18 Averaging disabled for debug
        // store the HES value in the averaging array
        HES_avg_data[ HES_avg_index++ ] = HES_data;
        if( HES_avg_index >= LOHESAD )
        {
            HES_avg_index = 0;
        }
    
        // sum the HES values
        sum = 0;
        for(i=0; i<LOHESAD; i++)
        {
            sum += HES_avg_data[i];
        }
    
        HES_avg_value = ( (float)sum / (float)LOHESAD );
    
        __no_operation();
    
    	*/
    
        offset = locate_offset( HES_data );
    
        // check for an error
        // normally the offset is 0, 1, 2 ... (LOCA-2)
        if( offset < 0 )
        {
            // this is an error !
            return ((float)PRESSURE_ERROR_VALUE);
        }
    
        // calculate the average pressure
        // Each device type will use this value to control
        // 4-20mA regulator, voltage output, and display of LCD
        temp0.float_num = calculate_pressure( offset, HES_data );
    
        return temp0.float_num;
    }   // End of compute_pressure() ***********************************************
    
    
    int locate_offset( float HES_value )
    {
        extern QUADLET read_flash_VRS( BYTE offset );
        int offset = OFFSET_CODE_ERROR;  // this is the error value
    
        QDATA temp0;
        float low_side, high_side;
        DOUBLET i;
    
        // check for an out of range HES_value !
    
        if( HES_value > ((float)1023.1) )
        {
            // this is an error !
            return offset;
        }
    
        if( HES_value < ((float)-0.1) )
        {
            // this is an error !
            return offset;
        }
    
    
        // Do all the other HES values here
        for(i=0; i<=(LOCA-2); i++)
        {
            temp0.quadlet = read_flash_VRS( VRS_START_OF_HES_CAL_DATA_OFFSET + i);
    
            // check for an uncalibrated unit, all bits are set to 1
            if( temp0.quadlet == 0xFFFFFFFF )
            {
            	// this is not calibrated, return a failure
            	return OFFSET_CODE_ERROR;
            }
    
            low_side = temp0.float_num;
    
            temp0.quadlet = read_flash_VRS( (VRS_START_OF_HES_CAL_DATA_OFFSET + i + 1) );
    
            // check for an uncalibrated unit, all bits are set to 1
            if( temp0.quadlet == 0xFFFFFFFF )
            {
            	// this is not calibrated, return a failure
                return OFFSET_CODE_ERROR;
            }
    
            high_side = temp0.float_num;
    
            // check for an uncalibrated unit or
            // out of range pressure ( units are PSI )
            if( (high_side < -1.0) || ((low_side > 1024)) )
            {
            	// this is out of range, return a failure
    
    
            }
    
            // special case i == 0
            // an average HES value less than low_side
            if(i == 0)
            {
                if( HES_value < low_side )
                {
                    offset = 0;
                    break;
                }
            }
    
            // special case i == 19
            // an average HES value greater than high_side
            if( i == 19 )
            {
                if( HES_value >= high_side )
                {
                    offset = 19;
                    break;
                }
            }
    
            // all other cases are handled here
            if( (HES_value>=low_side) && (HES_value<high_side) )
            {
                // the correct pair of data points has been identified !
                offset = i;
                break;
            }
    
        }
    
        return offset;
    
    }   // end of locate_offset() **************************************************
    
    
    float calculate_pressure( int offset, float HES_value )
    {
        float pressure = PRESSURE_ERROR_VALUE;
        QDATA temp0, temp1;
        float x, y, m, b, delta_y, delta_x;
    
        extern QUADLET read_flash_VRS( BYTE offset );
    
        // Create the coefficients for a linear equation using the
        // selected pair of calibration data points
        // Pressure = (m * HES_value) + b
        // m = (Change of Y / Change of X)
        // Note:  Pressure data has units of PSI.
        // It is encoded as a 32-bit IEEE floating point format
    
        // trap a low HES value in the turn-down region
        if(offset == 0)
        {
            // Check for a very low HES_value
            // It should be clamped to zero output pressure
            temp0.quadlet = read_flash_VRS( VRS_START_OF_HES_CAL_DATA_OFFSET );
            if( HES_value < (temp0.float_num + ((float)8.0)) )
            {
                return 0.0;
            }
        }
    
        // Delta Y
        temp0.quadlet = read_flash_VRS( VRS_START_OF_PRESS_CAL_DATA_OFFSET + offset );
        y = temp0.float_num;
        temp1.quadlet = read_flash_VRS( VRS_START_OF_PRESS_CAL_DATA_OFFSET + offset + 1 );
        delta_y =  ( temp1.float_num - temp0.float_num );
    
        // Delta X
        temp0.quadlet = read_flash_VRS( VRS_START_OF_HES_CAL_DATA_OFFSET + offset );
        x = temp0.float_num;
        temp1.quadlet = read_flash_VRS( VRS_START_OF_HES_CAL_DATA_OFFSET + offset + 1 );
        delta_x =  ( temp1.float_num - temp0.float_num );
    
        // Slope = delta_y / delta_x
        m = ( delta_y / delta_x );
    
        // offset        b = Y - (m * X)
        b = ( y - (m * x) );
    
        // Pressure = (m * HES_value) + b
        pressure = ((m * HES_value) + b);
    
        // Trap a negative number, it will give strange results
        // when you go to program the DAC, 4-20mA or LCD.
        if( pressure < 0.0 )
        {
            pressure = 0.0;
        }
    
        // Trap a pressure above Full Scale
        temp0.quadlet = read_flash_VRS( VRS_FULL_SCALE_OFFSET );
        if( pressure > temp0.float_num )
        {
            pressure = temp0.float_num;
        }
    
        return pressure;
    
    }   // end of calculate_pressure() *********************************************
    
    
    void I2C_timeout( void )
    {
    
        Clock_stop( clock1 );
    
    
    
    }   // end of I2C_timeout ******************************************************
    
    
    
    void wait_until_I2C_bus_is_idle ( void )
    {
    	BYTE timeout = 0;
    	BYTE value;
    
    	while( 1 )
    	{
    		value = USCI_B_I2C_isBusBusy( USCI_B1_BASE );
    
    		if( value == USCI_B_I2C_BUS_NOT_BUSY )
    		{
    			break;
    		}
    
    
    		timeout++;
    		if( timeout >= 250 )
    		{
    			break;
    		}
    	}
    
    	return;
    }	// end of wait_until_I2C_bus_is_idle () ************************************
    
    
    
    
    6305.empty_min.cfg
    display.c
    
    
    
    #include <msp430f5528.h>
    #include <gpio.h>
    #include "misc_stuff.h"
    #include "ADC12.h"
    #include <driverlib.h>
    #include <ti/drivers/uart/UARTUSCIA.h>  // contains "bool"
    #include <stdio.h>
    
    #include "bfcfont.h"
    #include "font_table.h"
    
    // These lines needs to be in any file selecting the font
    extern const BFC_CHARINFO BFC_Font_my_Arial14h_CharInfo[NOC];
    extern const BFC_CHARINFO BFC_Font_my_Arial21h_CharInfo[NOC];
    
    // The 128x64 pixel bitmap that is to be written to the LCD
    // The USB module has 2K of RAM that can be used as
    // general purpose RAM.   LODD has a value of 1024.  From the data
    // sheet USB RAM starts at 0x001C00 and ends at 0x0023FF.
    #pragma location = 0x001C00;
    BYTE display_data[LODD];
    // Allows the firmware to select between two different fonts
    BYTE font_type = SMALL_FONT;
    DOUBLET LCD_time_counter;	// see program_LCD_task() in SPI_UCB0().c
    
    // determines the graphic for the set units screen
    BYTE LCD_units_graphic;
    // determines the units that are displayed in the operating screen
    BYTE LCD_units;	// default units are PSI, see SPI_UCB0.c
    
    float LCD_average_pressure;
    BYTE tank_level_state = TANK_NEVER_FILLED;
    char buffer[25];
    BYTE switch_counter;
    BYTE switch1_debounce_counter;
    bool set_full = false;
    float LCD_full_tank_pressure;
    
    // Used by LCD Battery when emerging from sleep ( LPM4 )
    DOUBLET TA0CTL_value, TA1CTL_value, TA2CTL_value;
    
    
    void reset_LCD( void )
    {
    	// generate a reset signal using P2.6
    	// the signal needs to be low for at least 20uS
    	// After the reset goes high, the LCD module is not
    	// ready for 2 uS.
    
    	// This function is set up to produce a reset pulse
    	// approximately 40 uS
    
    	// clear P2.6
    	GPIO_setOutputLowOnPin( GPIO_PORT_P2, GPIO_PIN6 );
    
    	__delay_cycles( 300 );	// measured 40 uS
    
    	// set P2.6
    	GPIO_setOutputHighOnPin( GPIO_PORT_P2, GPIO_PIN6 );
    
    	// measured 13 uS from /reset going high
    	// to the start of the first /CS going low
    	__delay_cycles( 50 );
    
    	return;
    
    }	// end reset_LCD()
    
    void configure_LCD( void)
    {
    	extern void write_byte_LCD( BYTE value, BYTE A0 );
    
    	// this function takes care of a whole laundry list of register
    	// initializations for the LCD.
    
    	// 1.
    	write_byte_LCD( 0xA2, CMD_DATA );	// LCD Bias, not sure if 0xA2 or oxA3
    
    	// 2.
    	write_byte_LCD( 0xA1, CMD_DATA );	// ADC select = 1, L to R RAM write
    
    	// 3.
    	write_byte_LCD( 0xC0, CMD_DATA );	// Output Status select = normal
    
    	// 4.
    	write_byte_LCD( 0x40, CMD_DATA );	// Diplay Start Line select = normal
    
    	// 5.
    	write_byte_LCD( 0xE4, CMD_DATA );	// Oscillation Frequency Select
    
    	// 6.
    	write_byte_LCD( 0xE6, CMD_DATA );	// Enable DC Boost Clock
    										// 6 and 7 must be executed in this order
    	// 7.
    	write_byte_LCD( 0x03, CMD_DATA );	// DC/DC frequency Division set
    
    	// 8.
    	write_byte_LCD( 0x85, CMD_DATA );	// Enable N-Line Voltage Inversion
    
    	//9.
    	write_byte_LCD( 0x05, CMD_DATA );	// Set N-Line Inversion Number
    
    	// 10.
    	// set value of the internal resistor 1+(Rb/Ra) = 5
    	// for the Voltage Regulator, see figure 5
    	write_byte_LCD( 0x25, CMD_DATA );
    
    	// 11.		Volume Mode Set
    	write_byte_LCD( 0x81, CMD_DATA );
    
    	// 12.		Volume Register Set		11 and 12 must be exceuted in this order
    	write_byte_LCD( 39, CMD_DATA );
    
    	// 13.		Power Control Set		Rcommended setting
    	write_byte_LCD( 0x2F, CMD_DATA );
    
    	// 14.		Display On,  Normal mode = 0xA4,	All pixels on mode = 0xA5
    	write_byte_LCD( 0xA4, CMD_DATA );
    
    	// 15.		Display On/Off command, turn display On
    	write_byte_LCD( 0xAF, CMD_DATA );
    
    	return;
    }	// end of configure_LCD() **************************************************
    
    
    void clear_display_data( void )
    {
    	DOUBLET i;
    
    	for(i=0; i<LODD; i++ )
    	{
    		display_data[i] = 0;
    	}
    
    	return;
    }	// end of clean_display_data()	********************************************
    
    
    
    void write_string( BYTE x, BYTE y, char *str_ptr )
    {
    	// writes the given character string to display_data[]
    	// x, and y are the coordinates for the first font.
    
    	extern BYTE write_font_to_display_data( DOUBLET column, DOUBLET row, BYTE font_cde );
    
    	DOUBLET font_code;
    	DOUBLET font_width;
    
    	font_code =  ((DOUBLET)(*str_ptr));
    
    	while(font_code != A_NULL)
    	{
    		write_font_to_display_data( x, y, font_code );
    
    		// Adjust the column to the right for the next character.
    		// The amount of adjustment is not constant, and varies
    		// among fonts.
    		if( font_type == SMALL_FONT )
    		{
    			// use the small font
    			font_width  = BFC_Font_my_Arial14h_CharInfo[(font_code - FFC)].Width;
    		}
    		else
    		{
    			// use the large font
    			font_width  = BFC_Font_my_Arial21h_CharInfo[(font_code - FFC)].Width;
    		}
    
    		x += ((BYTE)font_width);
    
    		// increment the pointer to get the next font code
    		str_ptr++;
    
    		font_code =  ((DOUBLET)(*str_ptr));
    
    	}
    
    	return;
    }	// end of write_string() ***************************************************
    
    
    
    BYTE write_font_to_display_data( DOUBLET column, DOUBLET row, BYTE font_cde )
    {
    	// The column and row are the x,y coordinates where the font is to be placed
    	// within the display_data[].
    
    	extern void draw_pixel( DOUBLET column, DOUBLET row, BYTE data_bit );
    
    	BYTE success = 1;	// failure is zero
    	QDATA one_row;
    	BYTE i, j, pixel, font_index;
    	DOUBLET x, y, width, height;
    	QUADLET mask;
    
    	if( font_cde < 0x20 )
    	{
    		// the font_code is out of range !
    		success = 0;
    		return( success );
    	}
    
    	if( font_cde > 0x7E )
    	{
    		// the font_code is out of range !
    		success = 0;
    		return( success );
    	}
    
    	if(font_cde == 0x25)
    	{
    		_nop(); 	//trouble shooting
    	}
    
    	// compute the index for the font information array
    	// FFC is the First Font Code
    	font_index = ( font_cde - (BYTE)FFC );
    
    	// Get the width and height of the font in pixels, see font_table.c
    	 if( font_type == SMALL_FONT)
    	 {
    		width  = BFC_Font_my_Arial14h_CharInfo[font_index].Width;
    		height = BFC_Font_my_Arial14h_CharInfo[font_index].DataSize;
    	 }
    	 else
    	 {
    		 // use the large font
    		 width  = BFC_Font_my_Arial21h_CharInfo[font_index].Width;
    		 height = BFC_Font_my_Arial21h_CharInfo[font_index].DataSize;
    	 }
    
    	y = row;
    	for(i=0; i<=(height-1); i++)
    	{
    		one_row.quadlet = 0;
    		// read each row of the font vector, starting at the top
    		// depending on the particular character, it may need 1 or 2 bytes
    		if( width <= 8 )
    		{
    			// read one byte for each row of the font
    			if( font_type == SMALL_FONT)
    			{
    				// use the small font
    				one_row.byte[3] = *( BFC_Font_my_Arial14h_CharInfo[font_index].p.pData8 + i );
    
    			}
    			else
    			{
    				// use the large font
    				one_row.byte[3] = *( BFC_Font_my_Arial21h_CharInfo[font_index].p.pData8 + i );
    			}
    		}
    
    		if( (width > 8) && (width <= 16) )
    		{
    			// read 2 bytes for each row of the font
    			if( font_type == SMALL_FONT )
    			{
    				// use the small font
    				one_row.doublet[1] = *( BFC_Font_my_Arial14h_CharInfo[font_index].p.pData16 + i );
    
    			}
    			else
    			{
    				one_row.doublet[1] = *( BFC_Font_my_Arial21h_CharInfo[font_index].p.pData16 + i );
    			}
    			// reverse the byte order
    			font_cde = one_row.byte[3];
    			one_row.byte[3] = one_row.byte[2];
    			one_row.byte[2] = font_cde;
    		}
    
    		if( (width > 16) && (width <= 24) )
    		{
    			// read 4 bytes for each row of the font
    			if( font_type == SMALL_FONT )
    			{
    				// use the small font
    				one_row.quadlet = *( BFC_Font_my_Arial14h_CharInfo[font_index].p.pData32 + i );
    			}
    			else
    			{
    				one_row.quadlet = *( BFC_Font_my_Arial21h_CharInfo[font_index].p.pData32 + i );
    			}
    			// reverse the byte order in the quadlet
    			font_cde = one_row.byte[3];	// save [3]
    			one_row.byte[3] = one_row.byte[0];
    			one_row.byte[0] = font_cde;
    
    			font_cde = one_row.byte[2]; // save [2]
    			one_row.byte[2] = one_row.byte[1];
    			one_row.byte[1] = font_cde;
    		}
    		// Now you have read a row of the character !
    
    		mask = 0x80000000;
    		x = column;
    		// write one pixel at a time to display_data[]
    		for(j=0; j<=(width-1); j++)
    		{
    			// pick off each data bit starting from the left (most sig. bit)
    			if( one_row.quadlet & mask )
    			{
    				pixel = 1;
    			}
    			else
    			{
    				pixel = 0;
    			}
    
    			// write the given pixel into the display_data[]
    			draw_pixel( x, y, pixel );
    
    			mask = (mask >> 1);	// shift to the next bit
    			x++;	// incrementt to the next column
    		}	// end of column iteration
    
    		y++;	// increment to the next row
    	}	// end of row interation
    
    	return success;
    }	// end of write_font_to_display_data() *************************************
    
    
    
    void draw_pixel( DOUBLET column, DOUBLET row, BYTE data_bit  )
    {
    	DOUBLET page, index, bit_indicator;
    
    	// Check for Out of Bound coordinates
    	if((column >= NOCS) || (row >= NORS))
    	{
    		return;	// This is an error. Do nothing.
    	}
    
    	// determine which page the pixel is in
    	// The integer math will truncate properly
    	page = (row / 8);		//    0 <= page <= 7
    
    	// determine the offset for the vector of display data
    	index = ( ( page * 128 ) + column );
    
    	// depending on the state of the data_bit, set or clear the selected bit
    
    
    	// determine which data bit is affected in a given byte   ( D7, D6, ... D0 )
    	bit_indicator = ( row - (page * 8) );
    
    	switch ( bit_indicator )
    	{
    		case 0:		// D0
    			if(data_bit)
    			{
    				display_data[index] |= 0x01;
    			}
    			else
    			{
    				display_data[index] &= 0xFE;
    			}
    			break;
    
    		case 1:		// D1
    			if(data_bit)
    			{
    				display_data[index] |= 0x02;
    			}
    			else
    			{
    				display_data[index] &= 0xFD;
    			}
    			break;
    
    		case 2:		// D2
    			if(data_bit)
    			{
    				display_data[index] |= 0x04;
    			}
    			else
    			{
    				display_data[index] &= 0xFB;
    			}
    			break;
    
    		case 3:		// D3
    			if(data_bit)
    			{
    				display_data[index] |= 0x08;
    			}
    			else
    			{
    				display_data[index] &= 0xF7;
    			}
    			break;
    
    		case 4:		// D4
    			if(data_bit)
    			{
    				display_data[index] |= 0x10;
    			}
    			else
    			{
    				display_data[index] &= 0xEF;
    			}
    			break;
    
    		case 5:		// D5
    			if(data_bit)
    			{
    				display_data[index] |= 0x20;
    			}
    			else
    			{
    				display_data[index] &= 0xDF;
    			}
    			break;
    
    		case 6:		// D6
    			if(data_bit)
    			{
    				display_data[index] |= 0x40;
    			}
    			else
    			{
    				display_data[index] &= 0xBF;
    			}
    			break;
    
    		case 7:		// D7
    			if(data_bit)
    			{
    				display_data[index] |= 0x80;
    			}
    			else
    			{
    				display_data[index] &= 0x7F;
    			}
    			break;
    
    		default:
    			break;
    
    	}	// end of switch
    
    	return;
    }	// end of draw_pixel() *****************************************************
    
    
    
    void write_display_data_to_LCD( void )
    {
    	extern void write_byte_LCD( BYTE value, BYTE A0 );
    	BYTE i, j;
    	BYTE page;
    	DOUBLET x;
    
    	page = 0xB0;	// page address set command
    	x = 0;
    
    	for(i=0; i<=7; i++)
    	{
    
    		// set the page address,  0 <= page address <= 7
    		write_byte_LCD( page, CMD_DATA );
    
    		// clear the upper 4 bits of the column address
    		write_byte_LCD( 0x10, CMD_DATA );
    
    		// clear the lower 4 bits of the column address
    		write_byte_LCD( 0x00, CMD_DATA );
    
    		for(j=0; j<=127; j++)
    		{
    			// write the display data
    			write_byte_LCD( display_data[x++], DISPLAY_DATA );
    		}
    
    		// increment the page counter
    		page++;
    	}
    
    	return;
    }	// end of write_display_data_to_LCD() **************************************
    
    
    void write_line( BYTE x1, BYTE y1, BYTE x2, BYTE y2 )
    {
    	// function only writes horizontal or vertical lines n!  No diagonals !
    
    	DOUBLET row, col;
    
    
    	if( x1 == x2)
    	{
    		// a vertical line
    		for(row=y1; row<=y2; row++)
    		{
    			draw_pixel( x1, row, 1 );
    		}
    	}
    
    	if( y1 == y2)
    	{
    		// a vertical line
    		for(col=x1; col<=x2; col++)
    		{
    			draw_pixel( col, y1, 1 );
    		}
    	}
    
    	return;
    
    }	// end of write_line() *****************************************************
    
    
    void write_rectangle( BYTE x1, BYTE y1, BYTE x2, BYTE y2 )
    {
    	// requires that (x1 <= x2) and (y1 <= y2)
    
    	write_line( x1,  y1,  x2,  y1 );
    	write_line( x2,  y1,  x2,  y2 );
    	write_line( x1,  y2,  x2,  y2 );
    	write_line( x1,  y1,  x1,  y2 );
    
    	return;
    }	// end of writeRectangle() *************************************************
    
    
    
    /*
     *
     *      This code is used to support the operation of the 3
     *      tactile switches in the LCD Battery, and LCD 4-20mA project
     *
     *      S1 (P2.0), Up Arrow
     *      S2 (P2.1), On / Select
     *      S3 (P2.2), Backlight Enable
     *
     *		Additionally, it supports the 3 load switches in the LCD Level system
     */
    
    void init_tactile_switches( void )
    {
    
    	//	S1 (P2.0) - Up Arrow
    	//  S2 (P2.1) - On/Select
    	//  S3 (P2.2) - Back Light Enable
    	// configure as Input with Pullup
    	P2DIR &= 0xF8;
    	P2REN |= 0x07;
    	P2OUT |= 0x07;
    
    	// configure P2.0-P2.2 for high to low edge interrupt transition
    	P2IES |= 0x07;
    
    	// clear the P2 interrupt flag register
    	P2IFG = 0x00;
    
    	switch_counter = SWITCH_DEBOUNCE_IDLE;
    
    	return;
    }
    
    
    bool debounce_switch1( bool reset )
    {
    
    	bool success = false;
    
    	if( reset == true )
    	{
    		switch1_debounce_counter = 0;
    	}
    	else
    	{
    		// switch1 needs debouncing before the interrupt is enabled
    		if( READ_SWITCH1 )
    		{
    			// switch1 is high
    			switch1_debounce_counter++;
    		}
    		else
    		{
    			// switch1 is low
    			switch1_debounce_counter = 0;
    		}
    
    		if( switch1_debounce_counter > 10 )
    		{
    			// we have gone 250mS without bouncing
    			success = true;
    		}
    	}
    
    	return success;
    
    }	// end of debounce_switch1() ***********************************************
    
    void draw_IBT( short x, short y ){
    
        // x, and y are the coordinate location for the center of the
        // Outside Bottom of the Tank. Note that the arguments are signed.
    
        // segment 0
        write_line( (x-3), (y), (x+3), (y)  );
    
        // segment -1
        write_line( (x-7), (y-1), (x-4), (y-1) );
    
        // segment 1
        write_line( (x+4), (y-1), (x+7), (y-1) );
    
        // segment -2
        write_line( (x-10), (y-2), (x-8), (y-2) );
    
        // segment 2
        write_line( (x+8), (y-2), (x+10), (y-2) );
    
        // segment -3
        write_line( (x-13), (y-3), (x-11), (y-3) );
    
        // segment 3
        write_line( (x+11), (y-3), (x+13), (y-3) );
    
        return;
    }   // end of draw_IBT() *******************************************************
    
    void draw_ITT( short x, short y )
    {
        // x, and y are the coordinate location for the center of the
        // Inside Top of the Tank. Note that the arguments are signed.
    
        // segment 0
        write_line( (x-3), (y), (x+3), (y)  );
    
        // segment -1
        write_line( (x-7), (y+1), (x-4), (y+1) );
    
        // segment 1
        write_line( (x+4), (y+1), (x+7), (y+1) );
    
        // segment -2
        write_line( (x-10), (y+2), (x-8), (y+2) );
    
        // segment 2
        write_line( (x+8), (y+2), (x+10), (y+2) );
    
        // segment -3
        write_line( (x-13), (y+3), (x-11), (y+3) );
    
        // segment 3
        write_line( (x+11), (y+3), (x+13), (y+3) );
    
        // segment -4
        //write_line( (x-15), (y+4), (x-14), (y+4) );
    
        // segment 4
        //write_line( (x+14), (y+4), (x+15), (y+4) );
    
        return;
    }   // end of draw_OBT() *******************************************************
    
    
    void draw_OBT( short x, short y )
    {
    
        // x, and y are the coordinate location for the center of the
        // Outside Bottom of the Tank. Note that the arguments are signed.
    
        // segment 0
        write_line( (x-3), (y), (x+3), (y)  );
    
        // segment -1
        write_line( (x-7), (y-1), (x-4), (y-1) );
    
        // segment 1
        write_line( (x+4), (y-1), (x+7), (y-1) );
    
        // segment -2
        write_line( (x-10), (y-2), (x-8), (y-2) );
    
        // segment 2
        write_line( (x+8), (y-2), (x+10), (y-2) );
    
        // segment -3
        write_line( (x-13), (y-3), (x-11), (y-3) );
    
        // segment 3
        write_line( (x+11), (y-3), (x+13), (y-3) );
    
        // segment -4
        write_line( (x-15), (y-4), (x-14), (y-4) );
    
        // segment 4
        write_line( (x+14), (y-4), (x+15), (y-4) );
    
        // segment -5
        draw_pixel( (DOUBLET)(x-16), (DOUBLET)(y-5), 1 );
    
        // segment -5
        draw_pixel( (DOUBLET)(x+16), (DOUBLET)(y-5), 1 );
    
        return;
    }   // end of draw_OBT() *******************************************************
    
    void draw_OTT( short x, short y )
    {
    
        // x, and y are the coordinate location for the center of the
        // Outside Top of the Tank. Note that the arguments are signed.
    
        // segment 0
        write_line( (x-3), (y), (x+3), (y)  );
    
        // segment -1
        write_line( (x-7), (y+1), (x-4), (y+1) );
    
        // segment 1
        write_line( (x+4), (y+1), (x+7), (y+1) );
    
        // segment -2
        write_line( (x-10), (y+2), (x-8), (y+2) );
    
        // segment 2
        write_line( (x+8), (y+2), (x+10), (y+2) );
    
        // segment -3
        write_line( (x-13), (y+3), (x-11), (y+3) );
    
        // segment 3
        write_line( (x+11), (y+3), (x+13), (y+3) );
    
        // segment -4
        write_line( (x-15), (y+4), (x-14), (y+4) );
    
        // segment 4
        write_line( (x+14), (y+4), (x+15), (y+4) );
    
        // segment -5
        draw_pixel( (DOUBLET)(x-16), (DOUBLET)(y+5), 1 );
    
        // segment -5
        draw_pixel( (DOUBLET)(x+16), (DOUBLET)(y+5), 1 );
    
        return;
    }   // end of draw_OBT() *******************************************************
    
    
    void draw_tank( float pressure )
    {
        char buffer[25];
        int percent_full;
        DOUBLET liquid_rows, empty_rows;
        BYTE row, col, first_pixel, pixel_data;
    
        if( set_full == true )
        {
            set_full = false;       // clear the flag
            LCD_full_tank_pressure = pressure;    }
    
    
        // Post the Percent Full
        percent_full = (int)(( LCD_average_pressure / LCD_full_tank_pressure ) * 100.0);
    
        // If the value is greater than 100 %,
        // strange display errors can occur.
        // Trap this condtion !
        if( percent_full > 100 )
        {
            percent_full = 100;
        }
    
        font_type = LARGE_FONT;
        // conversion specifier "%d" is for a signed integer
        sprintf(buffer, "%d %% Full", percent_full );
        write_string( 36, HOF, buffer );
        font_type = SMALL_FONT;
    
        write_line(  0, 0,  32, 0 ); // Top Handle of Tank
        write_line(  0, 1,  32, 1 );
    
        write_line(  4, 0,  4 , 5 ); // Left vertical support
        write_line(  5, 0,  5 , 5 );
    
        write_line( 28, 0, 28 , 5 ); // Right vertical support
        write_line( 27, 0, 27 , 5 );
    
        // draw the Outside of the tank
        draw_OBT( 16, 63 );
        draw_OTT( 16, 3 );
        write_line(  0,  9,  0, 57 );   // left side
        write_line( 32,  9, 32, 57 );   // right side
    
        // draw the Inside of the tank
        draw_ITT( 16,  5 );
        draw_IBT( 16, 61 );
        write_line(  LEFT, TOP,  LEFT, BOT );   // left side
        write_line( RIGHT, TOP, RIGHT, BOT );   // right side
    
    
        // calculate the number of rows to be filled with liquid
        liquid_rows =
                ((((BOIT - TOP) - 1) * (DOUBLET)percent_full) / 100 );
    
        empty_rows = ( ((BOIT-TOP)-1)-liquid_rows );
    
        // Start drawing the liquid rows from the top down
        first_pixel = 0;
    
        for(row=((TOP+1)+ empty_rows); row<=(BOT+3); row++)
        {
            first_pixel = ~first_pixel;
            pixel_data = first_pixel;
            for(col=(LEFT+1); col<RIGHT; col++)
            {
                if(row <= (BOT))
                {
                    // full rows
                    draw_pixel( col, row, pixel_data );
                }
    
                if(row == (BOT+1))
                {
                    if( (col>=(LEFT+3)) && (col<(RIGHT-2)) )
                    {
                        draw_pixel( col, row, pixel_data );
                    }
                }
    
                if(row == (BOT+2))
                {
                    if( (col>=(LEFT+6)) && (col<(RIGHT-5)) )
                    {
                        draw_pixel( col, row, pixel_data );
                    }
                }
    
                if(row == (BOT+3))
                {
                    if( (col>=(LEFT+10)) && (col<(RIGHT-9)) )
                    {
                        draw_pixel( col, row, pixel_data );
                    }
                }
    
                                pixel_data = ~pixel_data;
            }
        }
    
     return;
    
    }   // end of draw_tank() ******************************************************
    
    
    void prepare_to_sleep( void )
    {
        #define HES_INIT_DEVICE         1
        // Hall Effcet Sensor, reading data.  See timer_A0.c and I2C_UCB1.c
        extern BYTE HES_state;
        // Hall Effect Sensor Program Sensitivity, execute this once after
        // power-up or after wake-up from sleeping.
        extern BYTE HES_PS_state;
    
        extern void change_I_O_to_inputs( void );
        extern BYTE LCD_state;
        extern DOUBLET LCD_time_counter;
        extern BYTE LCD_state;
    
        // power down unused devices
    
        CLR_GIE;    // disable all interrupts
    
        // clear any interrupt flags that may be hanging around
        P1IFG = 0x00;
        P2IFG = 0X00;
    
        LCD_time_counter = 0;
    
        LCD_state = LCD_SLEEPING;
    
        HES_state = HES_INIT_DEVICE;
    
        CLEAR_WATCHDOG_TIMER;
        DISABLE_WATCHDOG;   // set WDTHLD last,
        // otherwise WDTHLD will be cleared by CLEAR_WATCHDOG_TIMER;
    
        // shut the ADC and Reference 0ff
        DISABLE_ADC12;
        ADC12CTL0 = 0x0000;
        ADC12CTL1 = 0x0000;
        REFCTL0 = 0x0080;
    
        // NOTE:
        // All timers and USCI periperals must be stopped.  Otherwise their
        // respective clocks will remain active !
        TA0CTL_value = TA0CTL; // Save the settings
        TA0CTL = 0;             //stops timer A0
    
        TA1CTL_value = TA1CTL;  // Save the settings
        TA1CTL = 0;             //stops timer A1
    
        TA2CTL_value = TA2CTL;  // Save the settings
        TA2CTL = 0;             //stops timer A2
    
        change_I_O_to_inputs(); // float all of the inputs ( see switches.c )
    
        DISABLE_BATLVL_PWR;     // now you can power stuff down without contentions
    
        DISABLE_STUFF_PWR;
    
        DISABLE_BKLT_PWR;
    
        I2C_UCB1_SET_UCWRST;    // stops UCB1
        I2C_UCB1_CLR_ALL_INTERRUPTS;
        // I2C_UCB1_DISABLE_ALL_INTERRUPTS;
    
        UCB0_UCSWRST( 1 );      // stops UCB0
    
        COM_UCSWRST( 1 );       // stops UCA0
    
    
        LED1_DISABLE;   // you don't want LED1 enabled while asleep !
    
        // I/O
    
        // de-assert P2.7 for signal LCD_/CS1
        GPIO_setOutputHighOnPin( GPIO_PORT_P2, GPIO_PIN7 );
        // assert P2.6 for signal LCD_/RES
        GPIO_setOutputLowOnPin( GPIO_PORT_P2, GPIO_PIN6 ); // default state
    
    
        // clear LCD_A0
        GPIO_setOutputLowOnPin( GPIO_PORT_P2, GPIO_PIN5 );
    
    
        // UCB0CLK is sitting at 3V output. We need to get it low
        CLR_P3SEL_2;
        CLR_P3OUT_2;
    
        // UCB0SIMO  (LCD_SDI)
        CLR_P3SEL_0;
        CLR_P3OUT_0;
    
        // UCB1SCL (HES_SCL)
        P4DIR |= 0x04;  // make P4.2 and output
        CLR_P4SEL_2;
        CLR_P4OUT_2;
    
        // UCB1SDA (HES_SDA)
        P4DIR |= 0x02;  // make P4.1 and output
        CLR_P4SEL_1;
        CLR_P4OUT_1;
    
        // for now, leave the tactile switches S1 - S3, configured as input
        // with pullup.
    
        // signal RS232_TXD (P4.4)
        SET_P4DIR_4;
        CLR_P4SEL_4;
        CLR_P4OUT_4;
    
        // signal RS232_RXD (P4.5)
        SET_P4DIR_5;
        CLR_P4SEL_5;
        CLR_P4OUT_5;
    
        // Disable interrupts on P2.0       (S1, Arrow)
        CLEAR_SWITCH1_INTERRUPT;
        DISABLE_SWITCH1_INTERRUPT;
    
        // Enable the interrupt on P2.1     (S2, On / Select)
        CLEAR_SWITCH2_INTERRUPT;
        ENABLE_SWITCH2_INTERRUPT;
    
        // Disable interrupts on P2.2       (S3, Backlight)
        CLEAR_SWITCH3_INTERRUPT;
        DISABLE_SWITCH3_INTERRUPT;
    
        SET_GIE;    // enable all interrupts
    
        return;
    
    }   // end of prepare_to_sleep() ***********************************************
    
    void exp_sleep_prep( void )
    {
    
        CLR_GIE;    // disable all interrupts
    
        /*
        // NOTE:
        // All timers and USCI periperals must be stopped.  Otherwise their
        // respective clocks will remain active !
        */
    
        TA0CTL_value = TA0CTL;  // save settings
        TA0CTL = 0x0000;       // stop TA0
    
        SET_SMCLKOFF;
    
        // Disable interrupts on P2.0       (S1, Arrow)
        CLEAR_SWITCH1_INTERRUPT;
        DISABLE_SWITCH1_INTERRUPT;
    
        // Enable the interrupt on P2.1     (S2, On / Select)
        CLEAR_SWITCH2_INTERRUPT;
        ENABLE_SWITCH2_INTERRUPT;
    
        // Disable interrupts on P2.2       (S3, Backlight)
        CLEAR_SWITCH3_INTERRUPT;
        DISABLE_SWITCH3_INTERRUPT;
    
        DISABLE_ACLK;
        DISABLE_SMCLK;
    
        SET_GIE;    // enable all interrupts
    
        return;
    }
    
    void change_I_O_to_inputs( void )
    {
        // make used I/O into inputs so that we don't get a contention
        // when Stuff is powered Up or Down !
        // Note:  Other dedicated outputs, where no contention is possible,
        // are left as is;
    
        // ADC_INPUT
        P6DIR &= 0xFE;
    
        // All of P2
        P2DIR = 0x00;
    
        // LCD_SDI and LCD_SCLK
        P3DIR &= 0xFA;
    
        // HES_SDA, HES_SCL, RS232_TXD, RS232_RXD
        P4DIR &= 0xC9;
    
        return;
    }   // end of change_I_O_to_inputs() *******************************************
    
    
    
    Hi Tomasz,

    1.     I believe that I am getting into LPM4, because when I pause the debugger, I get an SR value of 0x00FB.  This indicates that the bits SCG1, SCG0, OSCOFF, CPUOFF are all set.

    2.      CCS Version:    7.3.0.00019,  Compiler:   TI V16.9.4 LTS,  I am using a custom PCB

    3.       The ISR is implemented via my  .cfg file and XGCONG under the Hwi section.  My ISR function is named switches_ISR (see the attached .cfg file).     switches_ISR() is in main.c

    When you asked me to verify that the rtos was OK if I used the ISR, when I was operating in a normal manner ( not in LPM4 ) , the rtos crashed.  I discovered that using the _interrupt keyword on my ISR was incorrect.  After taking the keyword out the compiler choked on the statement __bic_SR_register_on_exit(0xF0);  Just to get things going I commented out this statement.  The compiler worked, and the switches_ISR() does not crash the rtos when used during normal operation.

    However, if the ISR is used to exit LPM4, the rtos is still not functional. 

    Where do I place the   __bic_SR_register_on_exit(0xF0)    function ?

    My code flows like this:

                        every 25mS clock0 times out calling heartBeatFxn(),  see .cfg, and main.c 

                        heartBeatFxn() posts HES_sem

                        HES_task() executes,   see I2C_UCB1.c

                        this task posts LCD_sem

                        program_LCD_task() is executed, see SPI_UCB0.c

                        After several seconds exp_sleep_prep() ( see display.c ) is called to prepare for LPM4 

                       Then __bis_SR_register(0x00F0) is executed, placing the CPU into LPM4

    A hardware switch is used to exit LPM4

    Thank you very much for your help

    Roy

  • Roy,
    it is past 2 a.m. my time.
    I will back to your issue on Sat.
  • HwiFuncs.c
    #include <xdc/std.h>
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Swi.h>
    #define ti_sysbios_family_msp430_Hwi__internalaccess
    #include <ti/sysbios/family/msp430/Hwi.h>
    #include <ti/sysbios/family/msp430/Power.h>
    
    extern ti_sysbios_family_msp430_Hwi_Object ti_sysbios_family_msp430_Hwi_Object__table__V[];
    
    #if defined(__ICC430__)
    #pragma vector = 0 * 2
    #else
    #pragma vector = 0;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi0(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 1 * 2
    #else
    #pragma vector = 1;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi1(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 2 * 2
    #else
    #pragma vector = 2;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi2(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 3 * 2
    #else
    #pragma vector = 3;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi3(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 4 * 2
    #else
    #pragma vector = 4;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi4(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 5 * 2
    #else
    #pragma vector = 5;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi5(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 6 * 2
    #else
    #pragma vector = 6;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi6(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 7 * 2
    #else
    #pragma vector = 7;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi7(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 8 * 2
    #else
    #pragma vector = 8;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi8(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 9 * 2
    #else
    #pragma vector = 9;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi9(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 10 * 2
    #else
    #pragma vector = 10;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi10(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 11 * 2
    #else
    #pragma vector = 11;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi11(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 12 * 2
    #else
    #pragma vector = 12;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi12(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 13 * 2
    #else
    #pragma vector = 13;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi13(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 14 * 2
    #else
    #pragma vector = 14;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi14(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 15 * 2
    #else
    #pragma vector = 15;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi15(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 16 * 2
    #else
    #pragma vector = 16;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi16(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 17 * 2
    #else
    #pragma vector = 17;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi17(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 18 * 2
    #else
    #pragma vector = 18;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi18(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 19 * 2
    #else
    #pragma vector = 19;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi19(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 20 * 2
    #else
    #pragma vector = 20;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi20(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 21 * 2
    #else
    #pragma vector = 21;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi21(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 22 * 2
    #else
    #pragma vector = 22;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi22(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 23 * 2
    #else
    #pragma vector = 23;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi23(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 24 * 2
    #else
    #pragma vector = 24;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi24(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 25 * 2
    #else
    #pragma vector = 25;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi25(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 26 * 2
    #else
    #pragma vector = 26;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi26(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 27 * 2
    #else
    #pragma vector = 27;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi27(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 28 * 2
    #else
    #pragma vector = 28;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi28(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 29 * 2
    #else
    #pragma vector = 29;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi29(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 30 * 2
    #else
    #pragma vector = 30;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi30(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 31 * 2
    #else
    #pragma vector = 31;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi31(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 32 * 2
    #else
    #pragma vector = 32;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi32(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 33 * 2
    #else
    #pragma vector = 33;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi33(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 34 * 2
    #else
    #pragma vector = 34;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi34(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 35 * 2
    #else
    #pragma vector = 35;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi35(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 36 * 2
    #else
    #pragma vector = 36;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi36(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 37 * 2
    #else
    #pragma vector = 37;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi37(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 38 * 2
    #else
    #pragma vector = 38;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi38(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 39 * 2
    #else
    #pragma vector = 39;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi39(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 40 * 2
    #else
    #pragma vector = 40;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi40(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 41 * 2
    #else
    #pragma vector = 41;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi41(Void)
    {
        while(1){};
    }
    
    extern Void ti_sysbios_family_xxx_Hwi_switchAndRunFunc(Void (*func)());
    
    extern Void ti_sysbios_family_msp430_Hwi42_p2(Void);
    
    #if defined(__ICC430__)
    #pragma inline=never
    #endif
    extern Void switches_ISR(UArg);
    #if defined(__ICC430__)
    #pragma vector = 42 * 2
    #else
    #pragma vector = 42;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi42(Void)
    {
        UInt taskKey;
    
        /* disable Task scheduler */
        taskKey = ti_sysbios_knl_Task_disable();
    
        /* switch stacks and then run the phase 2 function */
        ti_sysbios_family_xxx_Hwi_switchAndRunFunc(&ti_sysbios_family_msp430_Hwi42_p2);
    
        /* handle any Task re-scheduling as required */
        ti_sysbios_knl_Task_restoreHwi(taskKey);
    
    }
    
    Void ti_sysbios_family_msp430_Hwi42_p2(Void)
    {
        ti_sysbios_BIOS_ThreadType prevThreadType;
        UInt swiKey;
    
        /* disable Swi scheduler */
        swiKey = ti_sysbios_knl_Swi_disable();
    
        /* set thread type to Hwi */
        prevThreadType = ti_sysbios_BIOS_setThreadType(ti_sysbios_BIOS_ThreadType_Hwi);
    
        /* run ISR function */
        switches_ISR(0);
    
        /* run any posted Swis */
        ti_sysbios_knl_Swi_restoreHwi(swiKey);
    
        /* restore thread type */
        ti_sysbios_BIOS_setThreadType(prevThreadType);
    
    }
    
    #if defined(__ICC430__)
    #pragma vector = 43 * 2
    #else
    #pragma vector = 43;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi43(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 44 * 2
    #else
    #pragma vector = 44;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi44(Void)
    {
        while(1){};
    }
    
    extern Void ti_sysbios_family_xxx_Hwi_switchAndRunFunc(Void (*func)());
    
    extern Void ti_sysbios_family_msp430_Hwi45_p2(Void);
    
    #if defined(__ICC430__)
    #pragma inline=never
    #endif
    extern Void I2CUSCIB_hwiIntFxn(UArg);
    #if defined(__ICC430__)
    #pragma vector = 45 * 2
    #else
    #pragma vector = 45;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi45(Void)
    {
        UInt taskKey;
    
        /* disable Task scheduler */
        taskKey = ti_sysbios_knl_Task_disable();
    
        /* switch stacks and then run the phase 2 function */
        ti_sysbios_family_xxx_Hwi_switchAndRunFunc(&ti_sysbios_family_msp430_Hwi45_p2);
    
        /* handle any Task re-scheduling as required */
        ti_sysbios_knl_Task_restoreHwi(taskKey);
    
    }
    
    Void ti_sysbios_family_msp430_Hwi45_p2(Void)
    {
        ti_sysbios_BIOS_ThreadType prevThreadType;
        UInt swiKey;
    
        /* disable Swi scheduler */
        swiKey = ti_sysbios_knl_Swi_disable();
    
        /* set thread type to Hwi */
        prevThreadType = ti_sysbios_BIOS_setThreadType(ti_sysbios_BIOS_ThreadType_Hwi);
    
        /* run ISR function */
        I2CUSCIB_hwiIntFxn(0);
    
        /* run any posted Swis */
        ti_sysbios_knl_Swi_restoreHwi(swiKey);
    
        /* restore thread type */
        ti_sysbios_BIOS_setThreadType(prevThreadType);
    
    }
    
    #if defined(__ICC430__)
    #pragma vector = 46 * 2
    #else
    #pragma vector = 46;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi46(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 47 * 2
    #else
    #pragma vector = 47;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi47(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 48 * 2
    #else
    #pragma vector = 48;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi48(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 49 * 2
    #else
    #pragma vector = 49;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi49(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 50 * 2
    #else
    #pragma vector = 50;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi50(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 51 * 2
    #else
    #pragma vector = 51;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi51(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 52 * 2
    #else
    #pragma vector = 52;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi52(Void)
    {
        while(1){};
    }
    
    extern Void ti_sysbios_family_xxx_Hwi_switchAndRunFunc(Void (*func)());
    
    extern Void ti_sysbios_family_msp430_Hwi53_p2(Void);
    
    #if defined(__ICC430__)
    #pragma inline=never
    #endif
    extern Void ti_sysbios_family_msp430_Timer_periodicStub__E(UArg);
    #if defined(__ICC430__)
    #pragma vector = 53 * 2
    #else
    #pragma vector = 53;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi53(Void)
    {
        UInt taskKey;
    
        /* disable Task scheduler */
        taskKey = ti_sysbios_knl_Task_disable();
    
        /* switch stacks and then run the phase 2 function */
        ti_sysbios_family_xxx_Hwi_switchAndRunFunc(&ti_sysbios_family_msp430_Hwi53_p2);
    
        /* handle any Task re-scheduling as required */
        ti_sysbios_knl_Task_restoreHwi(taskKey);
    
    }
    
    Void ti_sysbios_family_msp430_Hwi53_p2(Void)
    {
        ti_sysbios_BIOS_ThreadType prevThreadType;
        UInt swiKey;
    
        /* disable Swi scheduler */
        swiKey = ti_sysbios_knl_Swi_disable();
    
        /* set thread type to Hwi */
        prevThreadType = ti_sysbios_BIOS_setThreadType(ti_sysbios_BIOS_ThreadType_Hwi);
    
        /* run ISR function */
        ti_sysbios_family_msp430_Timer_periodicStub__E(0);
    
        /* run any posted Swis */
        ti_sysbios_knl_Swi_restoreHwi(swiKey);
    
        /* restore thread type */
        ti_sysbios_BIOS_setThreadType(prevThreadType);
    
    }
    
    #if defined(__ICC430__)
    #pragma vector = 54 * 2
    #else
    #pragma vector = 54;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi54(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 55 * 2
    #else
    #pragma vector = 55;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi55(Void)
    {
        while(1){};
    }
    
    extern Void ti_sysbios_family_xxx_Hwi_switchAndRunFunc(Void (*func)());
    
    extern Void ti_sysbios_family_msp430_Hwi56_p2(Void);
    
    #if defined(__ICC430__)
    #pragma inline=never
    #endif
    extern Void UARTUSCIA_hwiIntFxn(UArg);
    #if defined(__ICC430__)
    #pragma vector = 56 * 2
    #else
    #pragma vector = 56;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi56(Void)
    {
        UInt taskKey;
    
        /* disable Task scheduler */
        taskKey = ti_sysbios_knl_Task_disable();
    
        /* switch stacks and then run the phase 2 function */
        ti_sysbios_family_xxx_Hwi_switchAndRunFunc(&ti_sysbios_family_msp430_Hwi56_p2);
    
        /* handle any Task re-scheduling as required */
        ti_sysbios_knl_Task_restoreHwi(taskKey);
    
    }
    
    Void ti_sysbios_family_msp430_Hwi56_p2(Void)
    {
        ti_sysbios_BIOS_ThreadType prevThreadType;
        UInt swiKey;
    
        /* disable Swi scheduler */
        swiKey = ti_sysbios_knl_Swi_disable();
    
        /* set thread type to Hwi */
        prevThreadType = ti_sysbios_BIOS_setThreadType(ti_sysbios_BIOS_ThreadType_Hwi);
    
        /* run ISR function */
        UARTUSCIA_hwiIntFxn(0);
    
        /* run any posted Swis */
        ti_sysbios_knl_Swi_restoreHwi(swiKey);
    
        /* restore thread type */
        ti_sysbios_BIOS_setThreadType(prevThreadType);
    
    }
    
    #if defined(__ICC430__)
    #pragma vector = 57 * 2
    #else
    #pragma vector = 57;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi57(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 58 * 2
    #else
    #pragma vector = 58;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi58(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 59 * 2
    #else
    #pragma vector = 59;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi59(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 60 * 2
    #else
    #pragma vector = 60;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi60(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 61 * 2
    #else
    #pragma vector = 61;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi61(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 62 * 2
    #else
    #pragma vector = 62;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi62(Void)
    {
        while(1){};
    }
    
    
    
    Hi Tomasz

    I did some more digging into the where to put   __bic_SR_register_on_exit(0xF0)    function.

    I have attached the file HwiFuncs.c

    I think it has to be placed into the interrupt stub at line 444.

    One issue is that the exit function has to be conditionally executed depending on if it is an interrupt from regular operation or an interrupt from LPM4.

    So code would need to be written in the interrupt stub that can determine this.  I am not sure if this is the right approach, and if it is I do not know how to make this determination.

    Also, would not modifications to the interrupt stub be lost every time I perform a clean and build ? 

    Thank you for your help.

    Roy

  • 1727.HwiFuncs.c
    #include <xdc/std.h>
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Swi.h>
    #define ti_sysbios_family_msp430_Hwi__internalaccess
    #include <ti/sysbios/family/msp430/Hwi.h>
    #include <ti/sysbios/family/msp430/Power.h>
    
    extern ti_sysbios_family_msp430_Hwi_Object ti_sysbios_family_msp430_Hwi_Object__table__V[];
    
    #if defined(__ICC430__)
    #pragma vector = 0 * 2
    #else
    #pragma vector = 0;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi0(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 1 * 2
    #else
    #pragma vector = 1;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi1(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 2 * 2
    #else
    #pragma vector = 2;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi2(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 3 * 2
    #else
    #pragma vector = 3;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi3(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 4 * 2
    #else
    #pragma vector = 4;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi4(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 5 * 2
    #else
    #pragma vector = 5;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi5(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 6 * 2
    #else
    #pragma vector = 6;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi6(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 7 * 2
    #else
    #pragma vector = 7;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi7(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 8 * 2
    #else
    #pragma vector = 8;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi8(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 9 * 2
    #else
    #pragma vector = 9;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi9(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 10 * 2
    #else
    #pragma vector = 10;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi10(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 11 * 2
    #else
    #pragma vector = 11;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi11(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 12 * 2
    #else
    #pragma vector = 12;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi12(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 13 * 2
    #else
    #pragma vector = 13;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi13(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 14 * 2
    #else
    #pragma vector = 14;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi14(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 15 * 2
    #else
    #pragma vector = 15;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi15(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 16 * 2
    #else
    #pragma vector = 16;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi16(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 17 * 2
    #else
    #pragma vector = 17;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi17(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 18 * 2
    #else
    #pragma vector = 18;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi18(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 19 * 2
    #else
    #pragma vector = 19;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi19(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 20 * 2
    #else
    #pragma vector = 20;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi20(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 21 * 2
    #else
    #pragma vector = 21;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi21(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 22 * 2
    #else
    #pragma vector = 22;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi22(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 23 * 2
    #else
    #pragma vector = 23;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi23(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 24 * 2
    #else
    #pragma vector = 24;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi24(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 25 * 2
    #else
    #pragma vector = 25;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi25(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 26 * 2
    #else
    #pragma vector = 26;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi26(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 27 * 2
    #else
    #pragma vector = 27;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi27(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 28 * 2
    #else
    #pragma vector = 28;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi28(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 29 * 2
    #else
    #pragma vector = 29;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi29(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 30 * 2
    #else
    #pragma vector = 30;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi30(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 31 * 2
    #else
    #pragma vector = 31;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi31(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 32 * 2
    #else
    #pragma vector = 32;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi32(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 33 * 2
    #else
    #pragma vector = 33;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi33(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 34 * 2
    #else
    #pragma vector = 34;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi34(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 35 * 2
    #else
    #pragma vector = 35;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi35(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 36 * 2
    #else
    #pragma vector = 36;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi36(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 37 * 2
    #else
    #pragma vector = 37;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi37(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 38 * 2
    #else
    #pragma vector = 38;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi38(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 39 * 2
    #else
    #pragma vector = 39;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi39(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 40 * 2
    #else
    #pragma vector = 40;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi40(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 41 * 2
    #else
    #pragma vector = 41;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi41(Void)
    {
        while(1){};
    }
    
    extern Void ti_sysbios_family_xxx_Hwi_switchAndRunFunc(Void (*func)());
    
    extern Void ti_sysbios_family_msp430_Hwi42_p2(Void);
    
    #if defined(__ICC430__)
    #pragma inline=never
    #endif
    extern Void switches_ISR(UArg);
    #if defined(__ICC430__)
    #pragma vector = 42 * 2
    #else
    #pragma vector = 42;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi42(Void)
    {
        UInt taskKey;
    
        /* disable Task scheduler */
        taskKey = ti_sysbios_knl_Task_disable();
    
        /* switch stacks and then run the phase 2 function */
        ti_sysbios_family_xxx_Hwi_switchAndRunFunc(&ti_sysbios_family_msp430_Hwi42_p2);
    
        /* handle any Task re-scheduling as required */
        ti_sysbios_knl_Task_restoreHwi(taskKey);
    
        // added 8.27.18 as an experiment
        // This statement works as long as the interrupt is always caused by an
        // exit from LPM4. I think we need to execute it conditionally, based upon
        // the SR value that is on the system stack.
        __bic_SR_register_on_exit(0xF0);
    
    }
    
    Void ti_sysbios_family_msp430_Hwi42_p2(Void)
    {
        ti_sysbios_BIOS_ThreadType prevThreadType;
        UInt swiKey;
    
        /* disable Swi scheduler */
        swiKey = ti_sysbios_knl_Swi_disable();
    
        /* set thread type to Hwi */
        prevThreadType = ti_sysbios_BIOS_setThreadType(ti_sysbios_BIOS_ThreadType_Hwi);
    
        /* run ISR function */
        switches_ISR(0);
    
        /* run any posted Swis */
        ti_sysbios_knl_Swi_restoreHwi(swiKey);
    
        /* restore thread type */
        ti_sysbios_BIOS_setThreadType(prevThreadType);
    
    }
    
    #if defined(__ICC430__)
    #pragma vector = 43 * 2
    #else
    #pragma vector = 43;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi43(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 44 * 2
    #else
    #pragma vector = 44;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi44(Void)
    {
        while(1){};
    }
    
    extern Void ti_sysbios_family_xxx_Hwi_switchAndRunFunc(Void (*func)());
    
    extern Void ti_sysbios_family_msp430_Hwi45_p2(Void);
    
    #if defined(__ICC430__)
    #pragma inline=never
    #endif
    extern Void I2CUSCIB_hwiIntFxn(UArg);
    #if defined(__ICC430__)
    #pragma vector = 45 * 2
    #else
    #pragma vector = 45;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi45(Void)
    {
        UInt taskKey;
    
        /* disable Task scheduler */
        taskKey = ti_sysbios_knl_Task_disable();
    
        /* switch stacks and then run the phase 2 function */
        ti_sysbios_family_xxx_Hwi_switchAndRunFunc(&ti_sysbios_family_msp430_Hwi45_p2);
    
        /* handle any Task re-scheduling as required */
        ti_sysbios_knl_Task_restoreHwi(taskKey);
    
    }
    
    Void ti_sysbios_family_msp430_Hwi45_p2(Void)
    {
        ti_sysbios_BIOS_ThreadType prevThreadType;
        UInt swiKey;
    
        /* disable Swi scheduler */
        swiKey = ti_sysbios_knl_Swi_disable();
    
        /* set thread type to Hwi */
        prevThreadType = ti_sysbios_BIOS_setThreadType(ti_sysbios_BIOS_ThreadType_Hwi);
    
        /* run ISR function */
        I2CUSCIB_hwiIntFxn(0);
    
        /* run any posted Swis */
        ti_sysbios_knl_Swi_restoreHwi(swiKey);
    
        /* restore thread type */
        ti_sysbios_BIOS_setThreadType(prevThreadType);
    
    }
    
    #if defined(__ICC430__)
    #pragma vector = 46 * 2
    #else
    #pragma vector = 46;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi46(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 47 * 2
    #else
    #pragma vector = 47;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi47(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 48 * 2
    #else
    #pragma vector = 48;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi48(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 49 * 2
    #else
    #pragma vector = 49;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi49(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 50 * 2
    #else
    #pragma vector = 50;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi50(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 51 * 2
    #else
    #pragma vector = 51;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi51(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 52 * 2
    #else
    #pragma vector = 52;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi52(Void)
    {
        while(1){};
    }
    
    extern Void ti_sysbios_family_xxx_Hwi_switchAndRunFunc(Void (*func)());
    
    extern Void ti_sysbios_family_msp430_Hwi53_p2(Void);
    
    #if defined(__ICC430__)
    #pragma inline=never
    #endif
    extern Void ti_sysbios_family_msp430_Timer_periodicStub__E(UArg);
    #if defined(__ICC430__)
    #pragma vector = 53 * 2
    #else
    #pragma vector = 53;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi53(Void)
    {
        UInt taskKey;
    
        /* disable Task scheduler */
        taskKey = ti_sysbios_knl_Task_disable();
    
        /* switch stacks and then run the phase 2 function */
        ti_sysbios_family_xxx_Hwi_switchAndRunFunc(&ti_sysbios_family_msp430_Hwi53_p2);
    
        /* handle any Task re-scheduling as required */
        ti_sysbios_knl_Task_restoreHwi(taskKey);
    
    }
    
    Void ti_sysbios_family_msp430_Hwi53_p2(Void)
    {
        ti_sysbios_BIOS_ThreadType prevThreadType;
        UInt swiKey;
    
        /* disable Swi scheduler */
        swiKey = ti_sysbios_knl_Swi_disable();
    
        /* set thread type to Hwi */
        prevThreadType = ti_sysbios_BIOS_setThreadType(ti_sysbios_BIOS_ThreadType_Hwi);
    
        /* run ISR function */
        ti_sysbios_family_msp430_Timer_periodicStub__E(0);
    
        /* run any posted Swis */
        ti_sysbios_knl_Swi_restoreHwi(swiKey);
    
        /* restore thread type */
        ti_sysbios_BIOS_setThreadType(prevThreadType);
    
    }
    
    #if defined(__ICC430__)
    #pragma vector = 54 * 2
    #else
    #pragma vector = 54;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi54(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 55 * 2
    #else
    #pragma vector = 55;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi55(Void)
    {
        while(1){};
    }
    
    extern Void ti_sysbios_family_xxx_Hwi_switchAndRunFunc(Void (*func)());
    
    extern Void ti_sysbios_family_msp430_Hwi56_p2(Void);
    
    #if defined(__ICC430__)
    #pragma inline=never
    #endif
    extern Void UARTUSCIA_hwiIntFxn(UArg);
    #if defined(__ICC430__)
    #pragma vector = 56 * 2
    #else
    #pragma vector = 56;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi56(Void)
    {
        UInt taskKey;
    
        /* disable Task scheduler */
        taskKey = ti_sysbios_knl_Task_disable();
    
        /* switch stacks and then run the phase 2 function */
        ti_sysbios_family_xxx_Hwi_switchAndRunFunc(&ti_sysbios_family_msp430_Hwi56_p2);
    
        /* handle any Task re-scheduling as required */
        ti_sysbios_knl_Task_restoreHwi(taskKey);
    
    }
    
    Void ti_sysbios_family_msp430_Hwi56_p2(Void)
    {
        ti_sysbios_BIOS_ThreadType prevThreadType;
        UInt swiKey;
    
        /* disable Swi scheduler */
        swiKey = ti_sysbios_knl_Swi_disable();
    
        /* set thread type to Hwi */
        prevThreadType = ti_sysbios_BIOS_setThreadType(ti_sysbios_BIOS_ThreadType_Hwi);
    
        /* run ISR function */
        UARTUSCIA_hwiIntFxn(0);
    
        /* run any posted Swis */
        ti_sysbios_knl_Swi_restoreHwi(swiKey);
    
        /* restore thread type */
        ti_sysbios_BIOS_setThreadType(prevThreadType);
    
    }
    
    #if defined(__ICC430__)
    #pragma vector = 57 * 2
    #else
    #pragma vector = 57;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi57(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 58 * 2
    #else
    #pragma vector = 58;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi58(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 59 * 2
    #else
    #pragma vector = 59;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi59(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 60 * 2
    #else
    #pragma vector = 60;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi60(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 61 * 2
    #else
    #pragma vector = 61;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi61(Void)
    {
        while(1){};
    }
    
    #if defined(__ICC430__)
    #pragma vector = 62 * 2
    #else
    #pragma vector = 62;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi62(Void)
    {
        while(1){};
    }
    
    
    
    Hi Tomasz,

    As an experiment, I put the __bic_SR_register_on_exit(0xF0) statement  into the interrupt stub in HwiFuncs.c

    When the system is in LPM4, and I use switch2 to wake it up, the RTOS seems to be working after exiting LPM4.

    See the attached file, on line 461.

    What I am still missing is the correct way to conditionally execute __bic_SR_register_on_exit().

    Thank you for your help.

    Roy

**Attention** This is a public forum