Problem wirh TIM12 in STM32F4

First of all, thanks in advance for your help !

I’m using a STM32F4Discovery board with the Cerberus firmware, and everything works fine, except for one timer i’m using to count pulses. I’ve tested the counter with TIM3 successfully, but when i use TIM12, the whole board “speeds up”.

You probably would be asking why not to use another timer instead, well, the answer is that i have already a few custom boards where this signal is mapped to TIM12 (i’ve never expected this wierd behavior)

I have a few threads with “sleeps”, and if i don’t apply pulses to the external input the delays are ok, but as soon as signal is detected the “sleep’s” stop waiting the correct amount of time.

The blinking led goes faster, also the date & time of the board goes faster, so i’m quite sure that this timer is used by the framework. I not sure if the cerb source code is available to check if that timer is in use, i couldn’t find it.

According to the ST reference manual, this timer is fully independent,

The most confusing part is that only happens when signal is connected, and not after the timer inicialization. If this pin is tied to GND the board still works fine. And the same code for TIM3 works just fine.

This is the code i’m using…

static private void thread_T12_PULSECOUNTER()
            uint CCR1 = 0; uint CCR2;

            const UInt32 PERIPH_BASE = 0x40000000;
            const UInt32 APB1PERIPH_BASE = PERIPH_BASE;
            const UInt32 AHB1PERIPH_BASE = PERIPH_BASE + 0x00020000;

            const UInt32 TIM12_BASE = APB1PERIPH_BASE + 0x1800;
            const UInt32 RCC_BASE = AHB1PERIPH_BASE + 0x3800;
            const UInt32 GPIOB_BASE = AHB1PERIPH_BASE + 0x0400;

            Register RCC_APB1ENR = new Register(RCC_BASE + 0x40);
            Register RCC_AHB1ENR = new Register(RCC_BASE + 0x30);

            Register GPIOB_MODER = new Register(GPIOB_BASE + 0x00);
            Register GPIOB_AFRH = new Register(GPIOB_BASE + 0x24);

            Register TIM12_CR1 = new Register(TIM12_BASE + 0x00);   //TIM control register 1
            Register TIM12_SMCR = new Register(TIM12_BASE + 0x08);  //TIM slave mode control register
            Register TIM12_CCMR1 = new Register(TIM12_BASE + 0x18); //TIM capture/compare mode register 1
            Register TIM12_CCER = new Register(TIM12_BASE + 0x20);  //TIM capture/compare enable register
            Register TIM12_CNT = new Register(TIM12_BASE + 0x24);   //TIM Counter
            Register TIM12_CCR1 = new Register(TIM12_BASE + 0x34);  //TIM capture/compare register 1
            Register TIM12_CCR2 = new Register(TIM12_BASE + 0x38);  //TIM capture/compare register 2
            RCC_APB1ENR.SetBits(0x40);                              //TIM12 clock enabled (BIT 6)
            RCC_AHB1ENR.SetBits(0x02);                              //GPIOB enabled

            GPIOB_MODER.SetBits(0x80000000);                        //PB15 as Alternate function mode

            GPIOB_AFRH.SetBits(0x90000000);                         //PB15 Alternative function 9

            TIM12_CCMR1.Value = 0x02;                               //CC1 channel as input, IC1 is mapped on TI2

            TIM12_SMCR.Value = 0x67;                                //SMS=111 External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter
                                                                    //TS=110 Filtered Timer Input 2 (TI2FP2)
            TIM12_CCER.Value = 0x03;                                //CC2E=1 / CC1E=1  BOTH CAPTURE FALLIN' EDGE
            TIM12_CCR1.Value = 0;                                   //Clear CCR
            TIM12_CCR2.Value = 0;                                   //Clear CCR
            TIM12_CNT.Value = 0;                                      //Clear Counter

            TIM12_CR1.Value=0x01;                                   //Counter enabled

            pulseCounter = 0;

            while (true)
                CCR1 = TIM12_CCR1.Value;

                CCR2 = TIM12_CCR2.Value;


I don’t know what port you’re using on the DISCO board (I assume STMs?) but you will find that some timers are used internally by the framework. The 4.4 source on github might be a place you can / should look to see what is intended to bring forward into the 4.4 stream.

I believe the framework uses only one. It would make a lot of sense for this to use SysTick, but I don’t believe it does. It could very well use TIM12.

thanks for the info, i found de source code in Github, i’d been looking for it in Codeplex, my mistake.

i’ve also believed that TIM12 could be used by the framework, but what confusses me the most is that if i STOP de timer (setting CR1=0), the app running in the board still works fine.

So apparently is not this timer the one used by the framework, but the effect is so wierd, only fails with pulses.

i have a simple thread with a blinking led, this signal is connected to the external input of the timer (PB15), as soon as the signal appears the board becomes crazy, but if i stop it, everything works fine again.

I’m thinking in some problem with interrupts or the timer updates, i’ll try to see if the problem is in that way.

The STM port uses two timers which are cascaded to act like a higher resolution timer . It has been awhile since I looked at the code, but if I recall correctly the first is a 32 bit timer and the second a 16 bit timer cascaded and depending on the build configuration TIM12 is one of the options for the second timer.

That would explain what you are experiencing, because TIM12 will normally impact the system once the first timer ?TIM5? (32 bit timer) overflows and triggers TIM12, until then if TIM12 is disabled it has no effect. Now, if you asynchronously start triggering TIM12 that throws the system out of wack since the timer value now increases much faster.

The STM port uses two timers which are cascaded to act like a higher resolution timer .[/quote]
Correct. See also slide 64 here:’Horizon+V20140122.pdf?t=1408434774

1 Like


Described here: microcontroller - High resolution system timer in STM32 - Electrical Engineering Stack Exchange is a method for getting 64-bit resolution out of SysTick. I’m not an expert here, so it might be talking about something completely different.

Is this used simply for timestamping interrupts?