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.

Interrup handling in MSP430x21x1

Hi,

I am a beginner in MSP430x platform. I am trying to understand how the interrupt in general I/O pin is handled. In my code, I am trying to give a a Hi/Lo transition at Pin 1.7, which triggers an interrupt. In te ISR, PIN 1.6 is set and a global variable is also set. In the main loop, the value of the global variable is checked, and if it is == 1, another pin P1.0 should toggle for sometime. However, the code never enters the "if" block, i.e the PIN P1.0 never toggles.

Could someone explain me what exactly I am doing wrong?And how exactly the the _bis_SR_register works?

 

Please find the code below:   I am using msp430-gcc in linux platform.

 

#ifdef __MSP430_2132__
#include <msp430x21x2.h>
#else
#include <msp430x21x1.h>
#endif

#if defined(__MSP430__)
  #include <signal.h>                                        //interrupt vector slots and addresses are given
#endif
void cleanup (void);
static volatile unsigned int FLAG;


void main(void)
{
    unsigned int i, j;
    WDTCTL = WDTPW + WDTHOLD;                    //stop watchdog timer
    P1DIR |= 0x41;                                                     // set P1.6 and P1.0 in output direction
    P1IE |= 0x80;                                                       // P1.7 interrupt enable
    P1IES |= 0x80;                                                    // IES-> edge select 1 -> Hi/Lo edge, 0 otherwise; here P1.7 is set to detect Hi/Lo edge
    P1IFG &= ~0x80;                                              //P1.7 interrupt flag register is cleared

  
   
        __bis_SR_register(LPM0_bits + GIE);        // enter LPM0 with interrrupt enable


        if(FLAG == 1){
            for(i=0; i< 40; i++){
                for(j=0; j<40000; j++);
                P1OUT ^= 0x01;
            }
        }
       
   
}


//PORT 1 interrupt service routine
#if !defined(__MSP430__) && !defined(__clang__)
#pragma vector=PORT1_VECTOR
_interrupt void Port_1 (void)                                                                                             //IAR
#elif defined(_clang_)
void Port_1 (void) __attribute__((interrupt(PORT1_VECTOR)));                             //Clang only
void Port_1 (void)
#else
interrupt (PORT1_VECTOR) Port_1 (void)                                                                   //msp430-gcc in linux
#endif
{

    P1OUT |= 0x40;             //P1.6 set
    P1IFG &= ~0x80;            //P1.7 IFG is  cleared
    FLAG = 1;
    __bis_SR_register_on_exit(LPM0_bits);
}

 

 

  • Hi,

    I have not tested the following on my hardware, but I think it should resolve your issue:

    C compilers do not allow to get access to the CPU control registers. On MSP430 the CPU Register R2 is used as the Status Register (SR).
    There are bits within the SR that allows to configure the chip into its Low Power Modes and there is the General Interrupt Enable (GIE) bit.
    So if you want to change either the LPM mode or set/clear the GIE bit you use an intrinsic function of the C compiler - that's the __bis_SR_register() function.

    In the main loop you use:

            __bis_SR_register(LPM0_bits + GIE);        // enter LPM0 with interrrupt enable

    This causes that all maskable interrupt are allows (GIE=1) and the chip is switched into LPM0 mode (no further code execution untill an interrupt wakes up the chip again).

    In the interrupt service routine you used:

        __bis_SR_register_on_exit(LPM0_bits);

    This intrinsic function manipulates the SR that is stored on Stack. Asap the interrupt service routine is finished this content is poped back to SR. So manipulating the value with the  ..._on_exti() function allows to define a different LPM mode in the main loop.
    And here is the problem within your code... You are using __bis_SR_register_on_exit()... "bis" means that the bits will be set. However, you would like to clear the bits and by this switch the controll into active mode when it leaves the ISR and jumps back into main loop.
    So use the following intrinsic function in your interrupt service routine (the "bic" takes care that the bits mentioned in the bracket will be cleared):

        __bic_SR_register_on_exit(LPM0_bits);

    Regards.


  • Thank you. It works n

**Attention** This is a public forum