If I understand right, then when you comment the first (larger) bit out and uncomment the second bit it toggles at 0.7MHz?
The interrupt flag is not cleared so it will immediately jump back to the ISR. The second bit is not in an if statement so it will always be executed. So it will keep setting the pin in the interrupt_at_high_vector and clearing it in high_isr.
You need to make sure the flag is always cleared (if it is not cleared automatically)
What are you wanting it to do?
I don't know this specific MCU, but the question is fairly generic.
The obvious answer to all problems like these is to keep the ISRs as slim as possible. At most, they should stuff data into a ring buffer, which is later processed by the main program. (A MCU with DMA would have been even better, but I don't think you have DMA on MSP430?)
If the ISR is still too slow after such optimizations, then you have no other option but to do as you suggest: enable the global interrupt mask at the top of the UART ISR and let the higher priority interrupt take precedence. Be aware however, that when you allow more interrupts to come on top of an already executing ISR, you allow more stack depth.
Do I also need to unmask the serial RX interrupt at the end?
I assume that you have to do that from the ISR no matter the nature of the application? That's how most MCUs work. And yes, if you touch the global interrupt mask, you will have to clear the specific interrupt after you are done serving it, i.e. after you have copied the received data into local variables.
After the timer ISR returns, will the serial ISR continue, and then return to the main loop?
If you have changed the global interrupt mask, then yes.
Are there any potential race conditions I need to consider?
You always have to consider such whenever sharing data between an ISR and something else. It doesn't matter if the ISR only writes and the main program only reads etc, unless you can guarantee that each access is atomic, which you usually can't unless you write the code in assembler.
In a high level language, you may have to use some semaphore variable. How this is implemented is application-dependent. It particularly depends on if you can afford to miss out some data from the ISR or if you have to catch all data.
Is there a better solution?
DMA or a multi-core MCU.
Best Answer
Generally speaking, you really don't want to be wasting time in an ISR waiting for something to happen. Each ISR should do what it needs to do and exit quickly. Shared variables are used to keep track of state information and to communicate between ISRs.
In your case, you need to keep track of whether or not the timer has been started, and the number of RB0 events. You also need to know when to send a message, and what to put in the message. These become global variables:
You initialize those variable in your mainline code, before any interrupts have been enabled. Then you enable the interrupts and go into a loop that simply monitors whether a message needs to be sent:
In the RB0 ISR you check the timer_started flag and perform the desired action:
And in the timer ISR, you perform the actions required there:
Based on your comments, it seems that what you are implementing is basically a frequency counter. In that case, there's no need to start and stop the timer; just let it run continuously, generating interrupts at a fixed interval. Use the RB0 interrupts to increment a counter, and use the timer interrupt to capture the value of that counter. The captured value represents the frequency of the events on RB0.
Third try. As I understand it, you want to send a message if you've received at least 182 RB0 events in a row that never had more than 25 ms between them. Any gap longer than that resets the event counter.