I am trying to achieve 32-bit resolution using 16-bit timer on STM32F103. I found that ST provides an application note AN2592, however, I have two concerns regarding it:
1) I don't understand why are they multiplying MSB by 65535 (see 3.1). Shouldn't it be 65536 instead (assuming I use period of 65535)?
2) In 3.2 they say that you should process update interrupt first (to update MSB), to account for possible race between update and capture happens. I think, this is not correct.
In my understanding, two races are possible: capture after overflow and overflow after capture. They might happen for various reasons, the simplest one is that interrupts are disabled and both flags are raised before handler begins executing. Or handler starts handling one of them and before code gets to process the event, another event happens.
Depending on which race happened, you either need to update MSB before processing capture event or after. So, the way I think it should be done is to check the captured value first. If it is "pretty low" (less than, let's say, 10, 100, 1000, doesn't really matter as it will either be very low or very high to race to happen) and overflow is pending, then your overflow event happened before the capture. Otherwise, overflow happened after the capture.
This is my interrupt handler:
if (tim->SR & TIM_FLAG_CC1) {
tim->SR = ~TIM_FLAG_CC1;
uint32_t lsb = TIM2->CCR1;
// Captured value is very low and overflow is pending -- need to account for "msb" increment, as it happened
// before the capture event. Otherwise, we don't care -- if overflow interrupt is pending, we will handle
// it on the next handler invocation.
if (lsb < 1000 && (tim->SR & TIM_FLAG_UPDATE)) {
tim->SR = ~TIM_FLAG_UPDATE;
// Capture happened just after the overflow: need to increment upper "msb"
msb++;
}
msb_captured = msb;
lsb_captured = lsb;
msb = 0;
} else if (tim->SR & TIM_FLAG_UPDATE) {
tim->SR = ~TIM_FLAG_UPDATE;
msb++;
}
I haven't tested it yet (need to figure out the best way to test race handling...).
Does it look plausible?