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.

nested interrupt for MSP430



Dear all,

I'm working on nested interrupt at the moment using MSP430

My code is organized as follows: Basically the ISR of interrupt 1 will go to the ISR of interrupt 2.

main(){

code for initialization

__bis_SR_register(GIE);

do{code for LED }

while(1)}

interrupt 1{

code 1 which will enter the ISR of interrupt 2

code 2 which will enter the ISR of interrupt 2}

interrupt 2{

code}

I have found out that i need to disable the interrupt 1 when inside the ISR of interrupt 1, then enable it at the end of the ISR of interrupt 1, otherwise the controller will only reach code 1 then go back to the beginning of ISR of interrupt 1 and will not go further to code 2.  

interrupt 1{

disable interrupt 1

code 1 which will enter the ISR of interrupt 2

code 2 which will enter the ISR of interrupt 2

enable interrupt 1}

Just wondering whether or not my approach is right. Or you have some other way to run the nested interrupt.

Thanks in advance

Rui

  • Hi,

    the GIE bit is not set at the beginning of INT1 and therefore you dont have to clear it with your disable interrupt 1 instruction. It is however correct to set the GIE after code 2. If INT2 has a higher priority than INT1 then it will be run right after the enable interrupt instruction otherwise after the RETI, which seems to be basically more or less the same result in your code. If INT1 is triggered too early then it would be called again before INT2 if it has a higher priority. Therefore you should disable INT1 before the end of the INT1 ISR and enable it at the end of INT2.

  • Thanks for the reply mark. Actually i have __bis_SR_register(GIE) before the code 1 and code 2, which i forgot to write in the thread. Now i changed the code as shown below, Is there anything still can be improved? Besides, i still dont get it why the controller jumps from the last line of the ISR 2 to the beginning of ISR 1, if i dont use __bic_SR_register_on_exit(GIE) in ISR 2. Besides, if i write __bis_SR_register(GIE) at the beginning of ISR 1, then it will stuck there and will not go further. It seems that the trigger of ISR 1 is still there.

    main(){

    code for initialization

    __bis_SR_register(GIE);

    do{code for LED }

    while(1)}

    interrupt 1 (Port interrupt){

    some codes ....

    __bis_SR_register(GIE);  //enable GIE 1

    code 1 which will enter the ISR of interrupt 2

    __bis_SR_register(GIE);  //enable GIE 2

    code 2 which will enter the ISR of interrupt 2

    enable interrupt 1 or  __bis_SR_register(GIE); }

    interrupt 2 (timer interrupt){

    code

    __bic_SR_register_on_exit(GIE);}

  • The port interrupt is an interrupt vector and the INT flag is only reset if you read the interrupt vector or clear the flag "manually".

    u8 portSource = P1IV;

    or P1IFG &= ~BITX



  • Possessed said:
    My code is organized as follows: Basically the ISR of interrupt 1 will go to the ISR of interrupt 2.

    That's a very, very strange setup.

    Why is the code in interrupt 2 placed in an ISR at all? You cannot (!) call an ISR directly. Never. Because an ISR requires the status register placed on stack after the return address. This is mandatory for the RETI instruction at the end of an ISR to work.
    And you cannot do it in software. At least not without some rather complex hand-tweaked assembly code hack.

    You can, however, call a normal funciton from inside an ISR. It is not recommended, however, since it means a huge impact on execution time and stack space requirements for the ISR. And ISRs have to be short, ast interruptions of main, not separate parallel tasks. (use an RTOS with task switching for this kind of code)

    Nevertheless, your setup is not what nested interrupts are about. "Nested interrupts" means that you allow your current ISR to be interrupted by another interrupt. You do not call a different ISR, you allow a different ISR to be executed if a second (different!) interrupt occurs while you are still busy working on the current one. Which may or may not happen and is independent fron the first ISRs code.
    Somethimes this is necessary (e.g. if you have an ISR that does some work before done, and a timer ISR that needs to always be executed as fast as possible when a timer interrupt aoccurs), but you need to exactly know what you're doing, as the kind of problems that may arise from this are almost not debuggable. It's highly advanced expert stuff.

  • I am just guessing. You connected a push button to one of the pins to generate an interrupt. And you want to use a timer to avoid sensing the bounces of that button.

    If that is more or less what you intend to do, you do not need to “nest” your ISR. Instead, you could “chain” the ISR as follows:

    main()
    {
      ...
      set up pin interrupt;
      ...
      enable GIE;
      ... // do whatever
    }

    pin_interrupt_isr()
    {
      disable pin interrupt;
      ... // do whatever you need to do
      set up timer interrupt;
    }

    timer_interrupt_isr()
    {
      disable timer interrupt;
      enable pin interrupt; // again
    }

  • Jens-Michael Gross said:

    My code is organized as follows: Basically the ISR of interrupt 1 will go to the ISR of interrupt 2.

    That's a very, very strange setup.

    Why is the code in interrupt 2 placed in an ISR at all? You cannot (!) call an ISR directly. Never. Because an ISR requires the status register placed on stack after the return address. This is mandatory for the RETI instruction at the end of an ISR to work.
    And you cannot do it in software. At least not without some rather complex hand-tweaked assembly code hack.

    You can, however, call a normal funciton from inside an ISR. It is not recommended, however, since it means a huge impact on execution time and stack space requirements for the ISR. And ISRs have to be short, ast interruptions of main, not separate parallel tasks. (use an RTOS with task switching for this kind of code)

    Nevertheless, your setup is not what nested interrupts are about. "Nested interrupts" means that you allow your current ISR to be interrupted by another interrupt. You do not call a different ISR, you allow a different ISR to be executed if a second (different!) interrupt occurs while you are still busy working on the current one. Which may or may not happen and is independent fron the first ISRs code.
    Somethimes this is necessary (e.g. if you have an ISR that does some work before done, and a timer ISR that needs to always be executed as fast as possible when a timer interrupt aoccurs), but you need to exactly know what you're doing, as the kind of problems that may arise from this are almost not debuggable. It's highly advanced expert stuff.

    [/quote]

    Thanks for your kind reply. Perhaps my description leads some misunderstanding, but what i want to do just you allow your current ISR to be interrupted by another interrupt, as you said. I also know that normally the interrupt should be kept as short as possible, however, in my case, i need to use buttom to send some signal, which need lots of coding, i can not shorten my code inside the interrupt 1.  My second timer interrupt is used to monitor the the behavior of interrupt 1, if the interrupt 1 stuck somewhere, the timer interrupt will be enabled.

  • Thanks for your code and your guess is very close :), I tried your code, and it works fine. The big difference between yours and mine is that you move the line enable pin_interrupt into the timer_interrupt_isr() from the end of pin_interrupt_isr(). Am i right that this is the reason my code is nested?

    Beside, GIE will be disable after interrupt has been triggered, but why enable pin_interrupt is still set when it jumps back from timer_interrupt_isr() to pin_interrupt_isr()?

    Thanks in advance

  • Possessed said:
    in my case, i need to use buttom to send some signal, which need lots of coding, i can not shorten my code inside the interrupt 1

    In most cases, you can. The ISR can set a global flag and exit, and main detects the flag and does the time-consuming code. And of course can be interrupted by the second interrupt.

    The problem with nested interrupts is that your ISR can be interrupted by itself, so it mus tbe reentrant. And the cause for the interrupt must be cleard, or it will immediately interrupt itself. Causing a stack overflow faster than the eye can blink.

    However, if you disabled the interrupt that triggered the ISR, you may set GIE (enable itnerrupts) again inside the ISR and allow it to be interrupted by a different ISR.

    Note that intrruption of an already running ISR has nothing to do with interrupt priorities. Those are only important if two interrupts compete for being executed. E.g. if both are pending while interrupts are disabled (like during ISR execution woth whiel GIE is clear) and then you enable interrupts globally (set GIE or exit the current ISR).

**Attention** This is a public forum