2016-10-09 04:34 PM
I was hoping to get some clarification on a topic that has me confused with the STM32F4. I'm wanting to use all four channels of Timer2 for measuring period and the number of events for four different incoming signals. For the most part I’ve got my head wrapped around this; calculating deltas for both the captured times and number of timer overflows for each channel. The goal is to avoid having to use four different timers for the four signals.
In my application I need to both capture the value of the timer at the rising edge of an incoming signal and count the number of these events that have happened. Because of this the input capture will need to trigger an interrupt. As I understand it the STM32 only has one interrupt for everything related to a timer, and that interrupt handler will need to sort out what caused the interrupt (overflow, input capture/channel) and respond accordingly. So, if enabled, the setting of any of these bits will trigger the single timer 2 interrupt handler: TIM_SR.UIF (overflow), TIM2_SR.CC1IF (capture on channel 1) … TIM2_SR.CC4IF (capture on channel 4). Am I correct in my understanding of this?
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?
Here is a version of the interrupt handler I wrote that only deals with one capture channel and the timer overflow. This is not exactly representative of the question I asked. It resets the overflow counter, but for the multi-channel approach the overflow counter will continue running and a delta will be calculated instead. But it should give an idea of the approach I’m trying to take.
// Interrupt handler for Timer 2
void timer2_ISR() iv IVT_INT_TIM2 {
// NVIC_IntDisable(IVT_INT_TIM2); // ** UNUSED** Disable timer 2 interrupts
// Timer 2 Overflow
if(TIM2_SR.UIF == 1) {
TIM2_SR.UIF = 0; // Clear timer 2 interrupt bit
overflowCount++; // Increment overflow counter
}
// Input Capture Event
if (TIM2_SR.CC1IF == 1) {
TIM2_SR.CC1IF = 0; // Clear input capture event bit
endTime = TIM2_CCR1; // Read stored input capture time
overflowCountTemp = overflowCount; // Store overflow count for use in main
overflowCount = 0; // Reset the overflow counter to 0
inputEventCounter++; // Increment total input capture event counter
}
NVIC_IntEnable(IVT_INT_TIM2); // **UNUSED** Re-enable timer 2 interrupt
}
I hope this question isn’t too scatterbrained; I’m having a difficult time phrasing it.
Thank you,
Matthew
2016-10-10 12:44 AM
You're almost correct about how the various interrupt sources for the timer are handled.
TIM2->DIER.UIE is used to enable the update interrupt (Update Interrupt Enable) TIM2->SR.UIF is used flag that the update interrupt has occurred (Update Interrupt Flag) Similar for the CC1..4IE and CC1..4IF bits of course. If multiple interrupts happen in quick succession, e.g. CC1 fires and CC2 fires on the next clock cycle, then you will see multiple interrupt flags set when you check TIM2->SR in the interrupt handler. If another timer interrupt fires during the interrupt handler after you've already polled TIM2->SR then some additional flags may be set. When the interrupt exits the handler, if any of the flags are still set, the interrupt will fire again immediately. To make sure that any new flags are still set, don't clear the entire TIM2->SR register, clear only the bits that were set when you polled it. I suggest that you look at using DMA to capture the CC events instead of interrupts. Using DMA will reduce your CPU workload, minimize the risk of losing closely-spaced capture events, and give you a somewhat automated mechanism for counting the events.