cancel
Showing results for 
Search instead for 
Did you mean: 

Trouble catching overflow interrupt (Period Elapsed) on TIM3 while doing input capture

HForr.1
Associate II

I'm using STM32CubeMX and HAL functions.

I've gotten interrupt capture working for Timer 3 Channel 3. However, my input frequency is low and the 16-bit capture value is overflowing multiple times. I've solved this many times in the past with a different manufacturer microcontroller, so I know what to do. I'm trying to capture an interrupt for when Timer 3 itself overflow, so that I can count those overflows and thus logically extend the 16-bit capture value.

HOWEVER, I can't seem to catch the overflow interrupt (Period Elapsed). I do find that there's pretty much ZERO comprehensive doc for how all the HAL functions work. So I find myself poking around at many examples, and looking inside HAL code, trying to figure out what to do. It's just not working.

Please note that my main function has a definition of HAL_TIM_PeriodElapsedCallback() that was put there by the Cube and includes an "if(htim->Instance == TIM1) HAL_IncTick();". So I tried adding an "if(htim->Instance == TIM3) CallMyIncrement();" but CallMyIncrement() seems to never be called.

I have an early call to HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_3) to configure the input capture, just because an example did this. I also have NVIC Settings TIM3 global interrupt enabled in the Cube. I've had those since the beginning, and the input capture has worked since the beginning. But not the overflow (period elapsed) interrupt. I tried adding a call to HAL_TIM_Base_Init(&htim3); and HAL_TIM_Base_Start(&htim3); but that doesn't help.

CAN I IN FACT GET TWO TYPES OF INTERRUPTS out of Timer 3? I need both the input capture interrupt and the overflow (period elapsed) interrupt.

Another thing, the Cube for TIM3 has a config for "Clock Source" that is currently "Disable". No clue what that does. I could joke about how does this timer work if it has a clock source. Changing this to Internal, without perhaps doing some other magic, didn't help my overflow interrupts either.

Help!!!! Thanks very much.

23 REPLIES 23
gbm
Lead III

If you fancy to spare yourself the torture of using HAL for timer programming, you could easily achieve the effect you need in like 10 lines of C code. You should enable Update interrupt in TIM3 and TIM3 interrupt in NVIC. No idea how to do it in HAL as I don't use HAL for timer programming, but should be pretty easy with CubeIDE. Just make sure to enable the interrupts at both levels.

Note that HAL timer interrupt architecture significantly increases the time needed to handle the interrupt, as the same general routine is used to handle interrupts from many timers, which are already separated at NVIC level. So: TIM3 interrupt routine calls general HAL timer interrupt routine passing the TIM3 handle as argument, then the HAL routine in turn calls your TIM3-specific routine.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
HForr.1
Associate II

Thanks, @gbm​ .

Can I mix HAL and direct?

Please note that I didn't ever explicitly "choose" to use HAL. No, instead I just ran the CubeIDE from the beginning, it set up all the HAL includes/links and I moved forward from there.

Note that I'm currently using the HAL rtc (which had a particular bug so I made a renamed custom copy of one HAL source and fixed that bug). That rtc usage goes pretty deep. I'd rather not have to rewrite it all to not use HAL. This gets me to the question of can I use Timer 1 and rtc from HAL, yet use Timer 3 directly?

Thanks again.

Which STM32?

+1 to what gbm wrote: if you can't click it in CubeMX, there's no point in wasting time with Cube/HAL for this.

Note, that even if you get two interrupts working, you have to resolve the troublesome case when capture occurs close to overflow, based on the captured value and on the exact way how you write the ISR. Draw yourself a timing diagram and try to consider all possible cases.

JW

HForr.1
Associate II

Thanks to @Community member​ as well.

I'm using STM32F105RCT6TR.

I hear you about "if you can't click it in CubeMX", but the doc for CubeMX is so thin that I can't even tell if I can not click it. It has a checkbox for global interrupts. Also, BTW, I found one reference that claims to do this with HAL, and it's doing in essence what I'm doing. However, it's simplified and not checking for other interrupt sources. Perhaps it doesn't work on my STM32 (maybe why you asked) or doesn't work with multiple interrupt sources. I use these searches just to get the darned function names for HAL, LOL. Here's the link in the clear: https://deepbluembedded.com/stm32-input-capture-frequency-measurement-example-timer-input-capture-mode/

Regarding using both HAL and direct interrupts, I'm guessing that I could simply do my own direct setup after the HAL setup is done. This might even work for my Timer 1 & RTC via HAL vs Timer 3 direct question.

Finally, thanks sincerely @Community member​ for the interrupt race condition warning. I have been doing this kind of thing for multiple decades, however, so those kinds of issues are easy for me. I do sincerely appreciate the reminder, however. I've solved this one before. I forget the details of the solution but will be able to reconstruct them. The basis of the solution is that if the captured register value is beyond half, then a racing overflow interrupt must have occurred after the capture, and vice versa. Rephrased, it can't be the case that a capture occurs with a small register value and a racing overflow interrupt occurred after that capture. This, of course, assumes the overflow time period is large compared to the interrupt latency, and that's definitely the case (and almost always is the case whenever using any microprocessor to capture rpm). Determining if it's a potential race condition requires more than trivial thinking, and I'll go refresh my thoughts on how to do that. (Yes, I too think in pictures and will draw it out.)

Bottom line, however, the questions in my reply to @gbm​ remain.

raptorhal2
Lead

The answer is available in ST literature, but you have to connect a few dots yourself.

Look in the F1 HAL library STM3210E_EVAL examples for TIM TIM_InputCapture and TIM_TimeBase. You have to combine the examples and activate both an input capture interrupt and time base interrupt and process the related callbacks. The time base interrupt is the counter overflow event. Based on your experience, you probably know how to handle counter overflows.

Cheers, Hal

Cube/HAL is open source, so you can work backwards, from normal register usage to the Cube/HAL functions, to get understanding of them.

As you might've guessed, I am not a proponent of Cube/CubeMX. As a seasoned programmer, you really should consider getting rid of it once for all. I doubt RTC in 'F1 to be that hard to master.

JW

HForr.1
Associate II

Thanks @raptorhal2​ and again @Community member​ .

I'm gonna take it easy for a couple days, letting the thoughts roll around in my head. Normally, I read the proc register detail and diagrams first, but not yet with STM32 and HAL. I already figured I'd go take a look at those, then use my Atollic GUI to help hunt backwards through the open source library code, to confirm registers and bits. (Yes, this is what you said, @Community member​ .)

In doing so, I might also look at the EVAL again. I believe your suggestion, @raptorhal2​ meant to stick with HAL. Since HAL isn't working for me right now, I need to either use it better (correctly) or bypass/override settings and go direct. Either way, going through that code is a common step. I'm a short-timer on this project, so whichever falls in my lap the easiest at this point is the way I'll go.

One more thing, if somebody can confirm. If I go direct, or even if I find another error in HAL for my case, do you agree that I ought to be able to run all the HAL stuff and then just follow up with direct override of some things, such as the capture control register (whatever it's named), control bits, and maybe interrupt vector if it can be unique for Timer 3?

HForr.1
Associate II

...I already find something with a quick look. It seems the CubeMX is using a 16-bit auto-reload and therefore the capture value is 16 bits. But this pdf link page suggests 32 bits. That's a WORLD of difference in frequency measuring capability. At 32 bits per overflow, I would never have more than one counter wrap, and so adjusting for it is back to the simple add-one-if-negative solution. Is this true? The CubeMX only implements 16-bits but the hardware can do 32-bits? (That's "Stupid" with a capital "K". Yes, I invented that saying and I love it. No, "Stupid" doesn't have a "K" in it, so if it's "'Stupid' with a capital 'K'" then it's *really* *really* stupid.) There's example code in that pdf and I'll try to track down the #defines using the Atollic GUI for finding refs in my existing project.

I'll stop now and take my time off...

TIM3 is 16-bit.

There are 32-bits in most STM32 (perhaps the only exception is the 'L0 family), usually they are TIM2, TIM5 and sometimes TIM20.

Read AN4013.

JW

[EDIT] OK looked into AN4013 myself and it appears there is no 32-bit in the 'F1 either.