My real confusion is with how the chip will handle multiple concurrent events, or events that happen in very quick succession. Since, as I understand it, the single timer interrupt is needed to handle all of these situations there is no prioritization. As an example, say the interrupt handler is executing due to a channel 1 input capture event. While this is still going on the timer overflows. Since the two events are both part of the same interrupt, what will happen? Currently I’m using a series of if statements in the handler which should work if things came in order. But if they come in out of order will the interrupt interrupt itself, will it put the new event into a queue and handle them as a FIFO, will the second event just be lost, or will something altogether different happen?
Yes, you guessed it. Something slightly different from all the options you enumerated.
Let's check your (more than reasonable!) guesses one by one:
- As the new interrupt has the same exact priority and sub-priority as the one being handled, there's no reason for the current interrupt routine to be preempted.
- The FIFO idea could be good, but there's a major problem: how deep should the (hardware) FIFO to be sure we do not to lose interrupts?
- Losing interrupts is definitely a simple solution. But it's not a very helpful one, as you can imagine.
What will happen is simply that as long as there are active event flags (e.g. the CCxIF ones), with the matching interrupt enable flag set (e.g. the CCxIE ones), the interrupt will continue to be pending.
So the interrupt routine will be entered again as soon as it returns and the process will repeat as long as there are pending flags.
Moreover, there won't even be a real return from interrupt: the stacked registers won't be popped and pushed again, the control will pass directly to the beginning of the pending ISR (good for latency); from the F4 programming guide, chapter 2.3.7:
Tail-chaining
This mechanism speeds up exception servicing. On completion of an
exception handler, if there is a pending exception that meets the
requirements for exception entry, the stack pop is skipped and control
transfers to the new exception handler.
If an higher priority request comes, the ISR will be preempted, as expected.
If sub-priorities are defined, a request with higher sub-priority but same priority group will be served at the end of the current one (no preemption).
Edited to add:
Your approach in the code is then the correct one: check and act on each flag sequentially, without "else if"s.
Also, if you read the TIMn_CCRx register the corresponding CCxIF will automatically be cleared, so no need to do that in your code.