Hello, apologies for the long post, I tried to be as clear and concise as possible while still providing enough context to my question.
I'm writing a simple program on my Arduino Nano to handle pulse train generation for a stepper motor. Without leaving the scope of the question and getting into specific details, I need 3 key components to function as intended (see example code for a better picture):
- A quick, lightweight TIMER2 ISR to run at 10kHz
- A presumably slower TIMER1 ISR to run at 1kHz
- Enough processor space for real-time receiving and processing of incoming serial data
The issue I have is that I need both ISRs to process as tightly to their schedule as possible and from my understanding of how interrupts are processed, this may be difficult. Assuming my TIMER1 ISR takes longer than 200 microseconds (lets say 500us), after 100us, TIMER2 will flag an interrupt. Every following 100us, TIMER2 will try flag an interrupt (which has already been flagged) until the TIMER1 ISR is completed, at which point the TIMER2 ISR will be processed (once). In this way, won't I lose interrupts from TIMER2 during the processing time of TIMER1 ISR?
Furthermore, even if my TIMER1 ISR takes more than just 100us to process, my TIMER2 ISR will be delayed at best.
I have considered enabling interrupts during the TIMER1 ISR but am unclear how instruction resumes after completing the nested interrupt. If while in my TIMER1 ISR I enter into TIMER2 ISR and then complete, do I resume back into TIMER1 ISR or back into normal instruction (ending TIMER1 ISR prematurely)? If the latter is the case, would that also mean that the Rx ISR would also break my TIMER1 ISR if I happen to get serial data during that time?
Overall, I would like my fast TIMER2 ISR to process as close to 10kHz as possible, and my slower TIMER1 ISR to process as close to 1kHz as possible while still giving priority to TIMER2 ISR. Is this possible? I would appreciate any design suggestions to get at close to this functionality as possible.
Thanks in advance!
General program layout:
void setup() {
Serial.begin(115200);
cli();
// set TIMER1 compare match interrupt to 1kHz
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 249;
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS11) | (1 << CS10);
TIMSK1 |= (1 << OCIE1A);
// set TIMER2 compare match interrupt to 10kHz
TCCR2A = 0;
TCCR2B = 0;
TCNT2 = 0;
OCR2A = 199;
TCCR2A |= (1 << WGM21);
TCCR2B |= (1 << CS21);
TIMSK2 |= (1 << OCIE2A);
sei();
}
ISR (TIMER1_COMPA_vect) { // 1kHz
// slow math here
}
ISR (TIMER2_COMPA_vect) { // 10kHz
// very quickly set pins here here
}
void loop() {
// parse incoming serial messages
}