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.

Call NMI ISR more than one time?



Presently I am using a push-button to pull-down the RST/NMI/SBWTDIO port to call the vector=NMI_VECTOR  ISR routine.  

The catch is that I need to call the ISR more than one time, that is, each push of the button calls the NMI ISR.

I have experimented, and found that I can call the ISR more than one time by clearing the interrupt flag, and enabling the NMI interrupt, and _GID_SR(GIE), all in the for(;;).

The catch is, I have to repeatedly push the button, say 10-20 times to call the NMI ISR.  I can see with an o-scope the signal is correct on the port.  

Working without debugger is hard, has any one solved this dilemma?  Or, have I over looked something in the documentation, such as the NMI ISR can only be called once per reset of the controller?  

Thank you in advance! 

  • What is the Target MSP430 device?

    Usually when you have a debugger (i.e the FET UIF Tool) attached to the MSP430 device, during a debug session the RST/NMI pin is fully under the control of the debugger. So the external reset / interrupt  on the RST/NMI pin will not work.

    If you need to generate a NMI interrupt during a debug session, you can just manually set the NMIIFG Flag in the IFG Register.

    NMI interrupts are not masked by the GIE bit, so it is enough just to enable the NMIIE bit in the code. When a NMI interrupt is accepted, all NMI interrupt enable bits are automatically reset. User software must set the NMIIE interrupt enable bit for the interrupt to be re-enabled. In order to prevent nested NMI interrupts, the  NMIIE enable bit should not be set inside of an NMI ISR! But you also need to clear the NMIIFG Flag. This can be done inside the NMI ISR as shown in the below Figure:

    Hope this helps,

    BR,

    Mo.

  • Thank you very much,

    I did not know I could activate the NMI ISR from the debugger register setting!  I am no longer working in the dark, previously I did it the hard way -- program the NMI, disconnect the debugger, then test to see how good I am :)

    I now know that there is another bug in my program with this new trick, 

    Thanks Mo, you are my hero of the day!

  • Now another problem,

    I am setting a flag on power up, in the MAIN part of the program, before the for(;;), that is dependent on wether a push button is pressed or not.

    When I set the flag to call the NMI, in the debugger, the above mentioned flag is set properly, and all of my tests preform as expected.

    When I disconnect the debugger, and free run the MSPAFE, I can tell that the flag mentioned is becoming reset, or my tests just quit working after running through the NMI ISR routine.  

    Does the NMI ISR call reset things like flags that were previously set?  I can not understand why the debugger setting of the NMI flag works just fine, and without the debugger things are not working?

  • MAC Engineering said:
    Presently I am using a push-button to pull-down the RST/NMI/SBWTDIO port to call the vector=NMI_VECTOR  ISR routine.  

    Actually, using the RST pin as NMI is a bad idea. (the whole NMI pin is a bad idea). If oyu reconfigure the RST to NMI, and then your applicaiton crashes, the FET cannot reset the MSP for uploading another firmware. YOu may lock yourself out. Since after a power cycle, your software executes and therefore RST is turned again into NMI, this lock-out might be permanently, because you then are unable to enter BSL too for a mass erase.

    Also, if a PUC occurs while your button is pushed, NMI turns into RST pinand the pushed button acts as reset button.

    Unless you're really desperate in finding one mroe I/O pin, you should leave the NMI signal where it initially is: disabled.

    However, NMI is a bit different from normal interrupts. First, GIE is ignored. NMI is triggered whether GIE is set or not.
    Then (depending on device family), your ISR might be interrupted by a different NMI source, so the code needs to be re-entrant.
    On 1x, 2x and 4x  family, an NMI will clear ALL NMI enable bits (NMIIE etc.). So at the and of your ISR, you'll have to enable all of your NMI sources again. This is to avoid the ISR being interrupted by another NMI (remember, GIE is ignored). But when you re-enable them, this means you might get another NMI while you're still inside the ISR. Also, you'll have to manually clear the IFG bits after servicing the interrupt.

    On 5x family, there are two levels of NMI sources. As far as I understand the users guide, there is sort of an internal global NMI enable bit (or rather a state) that blocks user level NMIs when the NMI ISR is entered by a user NMI, and all NMIs when a system NMI occurred. The state is set back when RETI is executed.
    It means that a system NMI can always interrupt a user NMI. i only hope this state machine is smart enough to not enable user NMIs when the system NMI ISR exits with RETI.
    However, on 5x family, the IE bits of NMI sources are not reset and don't need to be set again by the ISR after handling the interrupt. moreover, both NMI types have an interrupt vector register that provides priorities and also automatically clears the IFG bit of the reported source when read.

    MAC Engineering said:
    Or, have I over looked something in the documentation, such as the NMI ISR can only be called once per reset of the controller?  

    If you're using a 1x to 4x family MSP, you might have overlooked that you will only get one NMI and then have to set all NMIIE bits again.

  • Thanks for your input, but, my former question was answered in following post:

    http://e2e.ti.com/support/microcontrollers/msp43016-bit_ultra-low_power_mcus/f/166/p/217385/766093.aspx#766093

    To help others, I will state here that I need a delay in my MAIN before the test that would set flags for testing in the NMI ISR.

    I blew it!  I put one too many zeros in the delay, thus the delay was 10 seconds long rather than 1 second, thus I did not give enough time to set the flag.

    Once I set the delay to 1 second, all was well and on to further programming thanks to community member 'OCY'  help!

  • Jens-Michael Gross said:
    So at the and of your ISR, you'll have to enable all of your NMI sources again. This is to avoid the ISR being interrupted by another NMI (remember, GIE is ignored). But when you re-enable them, this means you might get another NMI while you're still inside the ISR.

    therefore the NMI source should not be enabled inside of the NMI ISR, even not at the end of the ISR. This should be done outside of the NMI ISR.

    Regards,

    Mo.

  • Thanks MO, this is the way my NMI ISR routine was and is written, it is working fine now, thanks for your help on this matter, let's close this blog out.  I re-enable the NMI ISR in the f(;;) after reseting the NMI ISR flag in the NMI ISR routine. 

    FYI, the former mentioned post (link) has -some- of the code. 

  • Mo. said:
    therefore the NMI source should not be enabled inside of the NMI ISR, even not at the end of the ISR. This should be done outside of the NMI ISR.

    Problem is: interrupts are transparent. The main code doesn't know and doesn't care for an interrupt.
    From the main thread point of view, at some place and at some time, all enabled NMI sources are suddenly and magically disabled.
    Sure you can do a cyclic check or re-enable them every now and then, but this either costs you a lot of CPu power for constantly checking, or you'll have a gap after an NMI where NMI is disabled, until main re-enables it.

    However, if you continuously get an NMI while you are still inside the NMI ISR, then you have a way more fundamental problem in your applcation design. So if you don't, it is best to re-enable the NMI whiel still inside the ISR. Youst be aware of teh possible implications, especially while still in the development (bug-producing) phase.

**Attention** This is a public forum