Author Topic: STM32 32 bit chain timer missing MSB  (Read 3540 times)

0 Members and 1 Guest are viewing this topic.

Offline rvalenteTopic starter

  • Frequent Contributor
  • **
  • Posts: 726
  • Country: br
STM32 32 bit chain timer missing MSB
« on: October 28, 2018, 10:00:20 pm »
Dear mates,

I`m using a STM32F103C8T6 (bluepill board) for two input capture (frequency meter), for 4 to 600Hz, square wave from a VR sensor.

I chained TIM3 as master to TIM2 as slave, used ST AN2592 as guide https://www.st.com/resource/en/application_note/cd00165509.pdf
The frequency is being fed to CH1 and CH2 of both timers, so I`m feeding the signal in two IO pins per channel.

Used STM32CubeMX for configs, and Atollic as IDE.

TIM3 and TIM2 is configured this way:





Basically, whenever I have a input capture interruption, I read tim2 channel and tim3 channel (wherever channel 1 or 2, depends on the interrupt) as two 16 bit and assemble them as 32 bit. Doing that twice I get the frequency period and the frequency is them 10MHz(APB1 Timer clock)/frequency period.

It works like a charm for capturing two channels but, every 5s or so a glitch happen in the capture (both channels). The glitch is the delta capture (second capture minus the first) is around 65536. So, the TIM2 (slave) sometimes is counting one unit plus and others one unit less.

Attached, a small sample from STM Studio (the signal is capture delta).


Am I missing any thing to correctly chain this timers?

Greetings!
 

Offline bson

  • Supporter
  • ****
  • Posts: 2270
  • Country: us
Re: STM32 32 bit chain timer missing MSB
« Reply #1 on: October 28, 2018, 10:40:39 pm »
Are you sure the lower half timer isn't simply rolling over between the two 16 bit reads?

Since you're not ticking at very high frequencies you might be able to read timer H, then L, then H again, repeating this song and dance until the two H readings match, indicating there was no rollover.
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1719
  • Country: se
Re: STM32 32 bit chain timer missing MSB
« Reply #2 on: October 28, 2018, 11:12:35 pm »
I chained TIM3 as master to TIM2 as slave, used ST AN2592 as guide https://www.st.com/resource/en/application_note/cd00165509.pdf
[...]
Am I missing any thing to correctly chain this timers?

Are you sure you followed all the indications in the AN?
The description there is frankly confusing, partly contradictory, and the formulae look fishy... :-//
Though, from the pictures you attached I noticed the following differences:
  • The Master Slave Mode bit (MSM) is not set, the AN states: "Enable the Master/Slave mode."
  • TIM2 slave mode is set to "Trigger Mode", the AN states: "Use the external clock mode 1 as the Slave mode" - with this mode, the prescaler should be set to 0, not to 0xFFFF

Explanation:
  • The MSM bit will make sure the clocks are correctly synchronized in a master slave configuration
  • Using the external clock mode, TIM2 will step once every time the TIM3 rolls over, with your setting of "Trigger Mode" TIM" will simply be started when TIM3 rolls over (so, quite the same thing with a 216 prescaling, but not exactly...)
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline rvalenteTopic starter

  • Frequent Contributor
  • **
  • Posts: 726
  • Country: br
Re: STM32 32 bit chain timer missing MSB
« Reply #3 on: October 29, 2018, 12:09:06 pm »
Are you sure the lower half timer isn't simply rolling over between the two 16 bit reads?

Since you're not ticking at very high frequencies you might be able to read timer H, then L, then H again, repeating this song and dance until the two H readings match, indicating there was no rollover.


I dont think the problem is the rollover, I`m reading the capture registers, not the timer. As soon the timer 2 and 3 pins goes from low to high, the capture register latchs the timer value, freezing it. Right?
 

Offline rvalenteTopic starter

  • Frequent Contributor
  • **
  • Posts: 726
  • Country: br
Re: STM32 32 bit chain timer missing MSB
« Reply #4 on: October 29, 2018, 12:22:30 pm »
I chained TIM3 as master to TIM2 as slave, used ST AN2592 as guide https://www.st.com/resource/en/application_note/cd00165509.pdf
[...]
Am I missing any thing to correctly chain this timers?

Are you sure you followed all the indications in the AN?
The description there is frankly confusing, partly contradictory, and the formulae look fishy... :-//
Though, from the pictures you attached I noticed the following differences:
  • The Master Slave Mode bit (MSM) is not set, the AN states: "Enable the Master/Slave mode."
  • TIM2 slave mode is set to "Trigger Mode", the AN states: "Use the external clock mode 1 as the Slave mode" - with this mode, the prescaler should be set to 0, not to 0xFFFF

Explanation:
  • The MSM bit will make sure the clocks are correctly synchronized in a master slave configuration
  • Using the external clock mode, TIM2 will step once every time the TIM3 rolls over, with your setting of "Trigger Mode" TIM" will simply be started when TIM3 rolls over (so, quite the same thing with a 216 prescaling, but not exactly...)


I do not followed every step as AN stated, found the AN confusing ans well (the provided code diverges from the AN).

I changed the TIM3 to not to reset mode, since I`m using 2 channels capture, it will bother me.

The TIM3 slave mode is not set (pinout window) and in the configuration window, the TRGO enabled ou disabled makes no difference.

As you are explain-me I believe my timers were not chained, but the TIM2 is used in prescaller mode, counting 2^16 less them the TIM3.

So, I followed your suggestions, the TIM2 is prescalled to zero, tim3 TRGO enabled, update event, TIM2 slave mode as external clock mode 1.

The glitches behave much much better now, but from time to time I still can see a small glitch couting up (as the TIM2 is couting twice).




 
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1719
  • Country: se
Re: STM32 32 bit chain timer missing MSB
« Reply #5 on: October 29, 2018, 08:28:03 pm »
I see the error looks now 32768 (well, around 33000...), it would seem strange that this is caused by the HW capture.

Could you check the correctness of the code for reassembling the 32bit values from the 16bit ones (or post it here!)?
I would rather suspect some unsigned vs signed mishap.

If I have time later tonight, I might even try to reproduce your configuration... :=\
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline rvalenteTopic starter

  • Frequent Contributor
  • **
  • Posts: 726
  • Country: br
Re: STM32 32 bit chain timer missing MSB
« Reply #6 on: October 30, 2018, 12:41:57 am »
I see the error looks now 32768 (well, around 33000...), it would seem strange that this is caused by the HW capture.

Could you check the correctness of the code for reassembling the 32bit values from the 16bit ones (or post it here!)?
I would rather suspect some unsigned vs signed mishap.

If I have time later tonight, I might even try to reproduce your configuration... :=\

Thanks by helping me, this is driving me nuts...

The file tim.c was generated by cube32mx, has tem the TIM2 and TIM3 init.

The main.c, I was obliged to add the tim3 init call, I don't know why cube generated the TIM3 init, but did no called it on main.

Also, i did add the Input capture enable and start (lines 113 to 123 of main.c)

The file IO.c, there is a function call captureInputCompare, this function is called by TIM3_IRQHandler from the stm32fxxx_it.c (also generated by cubemx).

On captureInputCompare I did some tests, but basically was reading the two input captures through __HAL_TIM_GET_COMPARE, shifting the htim2 (msb) << 16 and OR (||) to tim3, in 32 bit integer, thats all.

Thanks by your help!!!

 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1719
  • Country: se
Re: STM32 32 bit chain timer missing MSB
« Reply #7 on: October 31, 2018, 08:48:57 am »
Quite a lot of code!
Sorry, I did not have much time to go through it (I probably was not clear, I expected a code snippet, not the whole shebang  ;)), and to experiment/read until yesterday night  :=\

Now, since you you showed me yours, I'll show you mine: it's a bit shorter, but works as intended :-DD

Code: [Select]
static volatile uint32_t oldCapture = 0;
static volatile uint32_t period = 0;
static volatile bool captured = false;

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    uint16_t newLSB = TIM3->CCR1;
    uint16_t newMSB  = TIM2->CCR1;
    uint32_t newCapture = (newMSB << 16) | newLSB;
    period = newCapture - oldCapture;
    oldCapture = newCapture;     // Save the last captured value
    captured = true;             // Signal main loop
}

Now some explanations and comments:
  • I used another timer to generate a jittered signal, the captured periods were always correct (in the jitter boundaries), I tried with many different ones with and without "carry" to TIM2.
  • I see you are calling your own routine from the TIM3 ISR, I instead used the callback facility provided by the HAL: just declare a function with the right name and it will be used (instead of the default, empty, weak one)
  • There's no reason CubeMX should not generate the right inits, it's more or less the only good thing going for it  :-//. Now I see it: you just forgot to check "Internal Clock" on TIM3!
  • You don't need to enable interrupt manually with __HAL_TIM_ENABLE_IT(), that's taken care of by the HAL with HAL_TIM_IC_Start_IT().
  • There's no need to enable interrupts on TIM2: the TIM3 interrupt will take care of both captures: AFAICS, you did not add any code, but the HAL basic ISR overhead is already quite high, and that will be called as you used HAL_TIM_IC_Start_IT().
  • If you are capturing at the maximum possible rate in STMStudio, bad things will happen: check the capture properties and set a sane sampling rate, I used a couple of ms; the check for correct capture values was in the code.
  • I was not able to make the TIM3 auto reset (as suggested in the AN) work reliably when using a master slave configuration: probably the HAL ISR overhead is too high, but I did not investigate further (since you are not using it). It works with a single timer, though.
  • Check carefully your captureInputCompare() function, I see duplicate lines, and checking CC2 flags, then clearing CC1 ones. Of course, all this flag checking and clearing is not needed if you rely on the HAL callbacks.
  • You used a two step approach to calculating the period, I just store the new reading in the old one after calculation (no need for additional state and if, to the cost of a borked initial reading).
  • Also, make sure that the Systick ISR (and other interrupts you might be using) is always shorter than the period to be measured, or, alternatively, define a clear interrupt priority hierarchy.

HTH
Nandemo wa shiranai wa yo, shitteru koto dake.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf