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.

CCS/MSP430F5529: implementing button interrupt with cc3100sdk on msp430f5529lp, question on correct use of existing code when sdk example is imported into CCS

Part Number: MSP430F5529
Other Parts Discussed in Thread: CC3100SDK, CC3100BOOST, CC3100

Tool/software: Code Composer Studio

Hi. I am having trouble understanding best practice for using the code provided by CCS when importing a project from the cc3100sdk. I would like to set up an interrupt to handle a button press (on P1.4) and see that board.c has existing code that I believe I should be adding to or modifying (for instance the PORT1_ISR and registerButtonIrqHandler). Unfortunately, I cannot find any documentation on how to properly add to this code. board.c/h have existing code for s1 (a switch on the msp430f5529lp that is covered by the cc3100boost, so I cannot use that existing code but would like to either copy or modify it).


I have tried to add a function in board.c that I could point the BUTTON_PRESS_HANDLER to and a flag that could be set in this function which I can reference from within my main function. This created symbol redefined errors in obj files that were created when compiling. For instance error symbol "btnP1_4Flag" first defined in "./main.obj"; redefined in "./board/board.obj"  Should I be writing this code in user.h and my main.c files while leaving board.c/h untouched? Thanks for pointing me in the right direction to solve this problem.


I am using CCS7, compiler msp430_4.3.1, cc3100sdk_1.2.0 with a msp430f5529lp and cc3100BOOST.


I have selected the code that I am referring to from board.c below...

BUTTON_PRESS_HANDLER            buttonIrqHandler = 0;
static void enable_button_s1_irq()
{
    PADIR &= ~0x1080;
    P2OUT |= BIT1;
    P2DIR &= ~(BIT1);
    P2REN |= BIT1;
    P2IES &= ~(BIT1);
    P2IFG = 0;
    P2IE |= BIT1;
}
void enableButtonIrq(void)
{
    enable_button_s1_irq();
}

int registerButtonIrqHandler(BUTTON_PRESS_HANDLER InterruptHdl , void* pValue)
{
    buttonIrqHandler = InterruptHdl;

    /* Enable Switch interrupt*/
    enableButtonIrq();

    return 0;
}
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=PORT1_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(PORT1_VECTOR)))
#endif
void Port1_ISR(void)
{
    /* Context save interrupt flag before calling interrupt vector. */
    /* Reading interrupt vector generator will automatically clear IFG flag */

    switch (__even_in_range(P1IV, P1IV_P1IFG7))
    {
        /* Vector  P1IV_NONE:  No Interrupt pending */
        case  P1IV_NONE:
            break;

        /* Vector  P1IV_P1IFG0:  P1IV P1IFG.0 */
        case  P1IV_P1IFG0:
            break;
...
        case  P1IV_P1IFG7:
            break;

        /* Default case */
        default:
            break;
    }
}

  • Hi Nick,

    You'll find more examples for setting up interrupts and creating ISRs for MSP products in Resource Explorer / MSPWare.

    The board.h/.c files were created as an example of code that can be used to perform board specific setup in an application. In this case, the BUTTON_PRESS_HANDLER is just one method for allowing an application function (defined in main.c) to be indirectly called from the actual GPIO Port ISR  when the button P2.1 on the MSP430F5529LP is pressed. This is done to simplify the code in IntSpiGPIOHandler() since it is called to handle two different interrupt sources: the HOST interrupt for the interface to the CC3100 and the button connected to P2.1.  The MQTT example in the SDK demonstrates how this can be done because it makes use of the button.

    You do not have to use this same scheme when writing your code for handling an interrupt on a different pin. You could instead just place the code you want executed upon an interrupt for P1.4 in the appropriate case of the Port1_ISR() function.

    Again, I recommend taking a look at the MSP430F552x examples in Resource Explorer for additional references of writing application code for it.

    Best Regards,

    Ben M

  • Thanks Ben. The MQTT example was just what I was looking for. I'm including my changes to board.c/h and main.c in the http_client example of msp430f5529lp for the record. I have a followup question regarding the assignment of PADIR &= ~0x1080; in the enable_button function. Since PADIR deals with both upper and lower bit fields (Ports 1 and 2), doesn't the hex value of 0x1080 clear pins 1.7 and 2.4 (not 1.4 as needed for S1 on the launchpad)?

    Anyway, this works for me now. Thanks again for the quick reply!

    /****** from board.h ******/
    /*
     * event handler for P1.4 not part of original cc3100sdk code
     */
    void button_P1_4_EventHandler(void);
    
    /****** from board.c ******/
    /*!
        \brief          Enable the IRQ for button on P1.4
                        copied from example in board.c
                        enable_button_s1_irq()
    */
    static void enable_button_P1_4_irq()
    {
        //PADIR &= ~0x1080;
        P1OUT |= BIT4;      // set pin high
        P1DIR &= ~(BIT4);   // set pin input
        P1REN |= BIT4;      // enable pull up
        P1IES &= ~(BIT1);   // high to low transition
        P1IFG = 0;          // cancel interrupt
        P1IE |= BIT4;       // enable
    }
    /*
     *  \brief          disable P1.4
    */
    static void disable_button_P1_4_irq()
    {
        P1IE &= ~BIT4;
    }
    void enableButtonIrq(void)
    {
        //enable_button_s1_irq();
        enable_button_P1_4_irq();
    }
    
    void disableButtonIrq(void)
    {
        //disable_button_s1_irq();
        disable_button_P1_4_irq();
    }
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=PORT1_VECTOR
    __interrupt
    #elif defined(__GNUC__)
    __attribute__((interrupt(PORT1_VECTOR)))
    #endif
    void Port1_ISR(void)
    {
        /* Context save interrupt flag before calling interrupt vector. */
        /* Reading interrupt vector generator will automatically clear IFG flag */
    
        switch (__even_in_range(P1IV, P1IV_P1IFG7))
        {
            /* Vector  P1IV_P1IFG4:  P1IV P1IFG.4 */
            case  P1IV_P1IFG4:
                if(buttonIrqHandler)
                {
                    disableButtonIrq();
                    buttonIrqHandler();
                }
                break;
    	    /* Default case */
    	    default:
    	        break;
    	}
    }
    /****** from main.c ******/
    /* in global variables section */
    /* to handle pushbutton events off msp430f5529lp board */
    enum io_events{NO_ACTION = -1, PUSH_BUTTON_PRESSED = 0};
    enum io_events g_io_events;
    /*!
     *  Button event handler on P1.4
     */
    void button_P1_4_EventHandler(void)
    {
        g_io_events = PUSH_BUTTON_PRESSED;
    }
    int mainb(int argc, char** argv)
    {
    	/* showing only changes made re button (P1.4) handler*/
        registerButtonIrqHandler(button_P1_4_EventHandler, NULL);
        /*test button press*/
        for(;;)
        {
            if(PUSH_BUTTON_PRESSED == g_io_events)
            {
                CLI_Write("button pressed\n");
                g_io_events = NO_ACTION;
                enableButtonIrq();
            }
        }
        return 0;
    }

  • Hi Nick,

    I'm glad you have it working!

    Yes, I believe the pins you pointed out are the ones that would be cleared to outputs. The lines following that one should work for setting up P2.1 on the LP to use SW1. Removing the line like you had should be fine.


    Best Regards,
    Ben M

  • Sorry for not clearly stating my followup question. What is the purpose of setting PADIR &= ~1080 in the enable_button_s1_irq function in board.c? It is my understanding that this would make P2.4 and P1.3 INPUT and all other pins OUTPUT. The P2.1 (the pin connected to S1 on the MSP430F5529LP) is cleared later in the function with P2DIR &= ~(BIT1). For my purposes, I just commented out the PADIR line in the function I used to enable an off board switch connected to P1.4 but that may not be the right approach. I am copying the original code from board.c here. Thanks again!

    /*!
        \brief          Enable the IRQ for button S1 on the Launchpad
    
        \param[in]      none
    
        \return         none
    
        \note
    
        \warning
    */
    static void enable_button_s1_irq()
    {
        PADIR &= ~0x1080;
        P2OUT |= BIT1;
        P2DIR &= ~(BIT1);
        P2REN |= BIT1;
        P2IES &= ~(BIT1);
        P2IFG = 0;
        P2IE |= BIT1;
    }

  • Hi Nick,

    Since the "~" is used, it seems to be performing a bit-wise AND with PADIR and the binary value 1110 1111 0111 1111. This should clear the DIR bit for 2.4 and 1.7. Meaning it would set these two pins as inputs, but just retain the state of the rest of the pins (either input or output).

    If called early in the application, PADIR may be 0x0000 anyway meaning the call would have no effect.

    Best Regards,
    Ben M
  • Okay, I got the 0x1080 mixed up with 0x1008 so as you said the word &'d with PADIR is 1110 1111 0111 1111 clearing bits associated with P2.4 and P1.7. I'm still puzzled since the original function was enabling P2.1 and unsure whether this will crop up as my application gets more complex. But I'll follow your recommendation and leave this statement out of my enable_button_P1_4_irq function for now.
    Cheers,
    N