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.

MSP430FR6989: Is it possible to have an interrupt call a function once the interrupt is exited?

Part Number: MSP430FR6989

My question is more of an abstract one, but I will try and give some pseudo-code later. I am trying to implement a system where my MSP will begin a certain process once it receives an external signal. I am familiar with interrupts enough to know that it is frowned upon to have the entire computation run in the interrupt, and it is frowned upon to call a function from an interrupt, as the "process" (forgive me, I can't think of the proper term right now) waits in the interrupt until the function is finished. What I'm looking for is something similar to the following:

configure_settings(void)
{
    //configure stuff
}

int main()
{
    //set up stuff
    _enable_interrupts();
    _low_power_mode();
}

#pragma vector = interrup_vector
__interrupt void check_signal(void)
{
    //receive byte
    //check for start signal
    if (start signal == received)
        function(void);
}

void function(void)
{
    //do all of the computing 
    //that I want to do in 
    //this function, rather
    //than the interrupt
}

I know that very little of the code above uses the correct syntax or keywords, but this is more of a conceptual question than a debugging one. The way the above pseudo-code will run will be that the "process" will run the function within the ISR, and then return to the ISR once the functions execution has ceased. Admitting this practice is bad, my setup would theoretically allow this as I can guarantee that no other external interrupts will arrive before the function is done. 

I was curious if the MSP architecture would allow for the process to look a little more like:

  1. ISR is entered
  2. Start signal is received
  3. Interrupts disabled/flags cleared
  4. ISR exited 
  5. Function called
  6. Reenter LPM once function is done

Is there any way to do this?

  • Hi Alex,

    Your description is fine.

    It is true that from within an ISR it is good practice not to call a function that takes a long time to execute.  Its fine if the function is short.  It really depends on what else is happening in the system and if there something else in the system that it timing critical.

    The recommended way is to set a flag in the ISR, then return to main.  In main check if the flag is set and call the function if true, else enter low power mode.

    configure_settings(void)
    {
        //configure stuff
    }

    int flag = false;

    int main()
    {
        //set up stuff
        _enable_interrupts();
        
        while(1)
        {
            // Enter sleep mode.
            __bis_SR_register(LPM3_bits + GIE);// _low_power_mode();
            
            // Interrupt happened so we are awake - check our flag
            if(flag == true)
                function();
            
        }//end while loop
    }

    #pragma vector = interrupt_vector
    __interrupt void check_signal(void)
    {
        //receive byte
        //check for start signal
        if (start signal == received)
            flag = true;
        
        // When we return from interrupt, we don't want to go back to sleep, we want to stay active
        __bic_SR_register_on_exit(LPM3_bits);
    }

    void function(void)
    {
        //do all of the computing
        //that I want to do in
        //this function, rather
        //than the interrupt
    }

  • Thanks for the reply Dennis! 

    I had no idea that you could enter a low power mode in a while loop, as I thought that LPMs "replaced" any form of infinite loops. This is a game changer.

    I'm not very familiar with the assembly-style coding (hence the low_power_mode_#() function), so can you give me a quick rundown or resource to read the following lines?

     __bis_SR_register(LPM3_bits + GIE);// _low_power_mode();
     __bic_SR_register_on_exit(LPM3_bits);

    I understand that is entering/altering the LPM states, but I wouldn't know enough to write those on my own. 

    Thanks again!

  • Hi Alex,

    These are macros that generate specific assembly code, but look more like a C-statement and are referred to as "intrinsics."  They are described in the MSP430 compiler guide section 6.8.1.

    These low power intrinsics modify certain bits in the SR register which control the CPU and clocking.   I would recommend looking at the MSP430FR6989 users guide, section 4.3.3, where it describes the CPU registers.  Here is a snippet:

    So here is how it works...

    1. The  instruction __bis_SR_register(LPM3_bits + GIE)  generates the assembly code code below which sets the GIE, SCG1, SCG0 and CPUOFF SR bits, effectively disabling the clock system and stopping the CPU.  You are now in LPM3.  Note, the extra NOP instructions are automatically inserted by the complier for other reasons.

    2. When an interrupt occurs, these bits are automatically cleared by the ISR hardware and the PC and SR are pushed onto the stack.

    3. In the ISR handler your application code does its job, then you decide what you want to do next. Go back to the LPM3 state waiting for the next interrupt or continue with the next instruction in main.c (this would be your while-loop)?

    5. If you simply return from the interrupt, the SR will get replaced with the SR value before the interrupt occurred and you go back into LPM3 waiting for the next interrupt to occur.

    6. But, if you use the __bic_SR_register_on_exit(LPM3_bits) instruction, the GIE, SCG0, SCG1 and CPUOFF bits are cleared allowing the CPU to continue executing.

    Does this help?

  • Yes, that helps substantially. Thank you for your time Dennis!

**Attention** This is a public forum