Skip to main content
jean
Senior
June 27, 2019
Question

Timers frequency divided by 2

  • June 27, 2019
  • 5 replies
  • 1276 views

Hello everybody!

I try to configure TIM2 to interrupt in the range of 100Hz ... 1kHz. Strangely, the actual frequency I set is divided by 2: if I configure the timer to run at 1000Hz, it will run at 500Hz

TIM2 configuration:

void System::InitTimers() 
{
 htim2.Instance = TIM2;
 htim2.Init.Prescaler = 0;
 htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
 htim2.Init.Period = (HAL_RCC_GetHCLKFreq()/1000)-1;
 htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
 htim2.Init.RepetitionCounter = 0;
 htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
 if (HAL_TIM_Base_Init(&htim2) != HAL_OK) __DEBUG_BKPT();
}

I'm using a STM32F69 with a 25 MHz cristal.

My clock configuration:

/* Initializes the CPU, AHB and APB busses clocks */
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
 RCC_OscInitStruct.HSEState = RCC_HSE_ON;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
 RCC_OscInitStruct.PLL.PLLM = 25;
 RCC_OscInitStruct.PLL.PLLN = 432;
 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
 RCC_OscInitStruct.PLL.PLLQ = 9;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) __DEBUG_BKPT(); 
 
 /* Activate the Over-Drive mode */
 if (HAL_PWREx_EnableOverDrive() != HAL_OK) __DEBUG_BKPT(); 
 
 /* Initializes the CPU, AHB and APB busses clocks */
 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK) __DEBUG_BKPT(); 
const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
#if !defined (HSE_VALUE) 
 #define HSE_VALUE ((uint32_t)25000000U) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */

Maybe my STM32 is not running at 216Mhz, but at 108Mhz, causing my timer to be divided?

Thanks for reading me, have a nice day!

This topic has been closed for replies.

5 replies

Tesla DeLorean
Guru
June 27, 2019

Isn't TIM2 on APB1 that you have in DIV4 mode?​ The TIM will be clocking at AHB/2, ie 2x APB1CLK

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
jean
jeanAuthor
Senior
June 27, 2019

Thanks @Community member​ and sorry for the amateur question, I should have figured it by myself!

I have an other question, maybe a stupid one, how to be sure that my uC is running at its maximum frequency of 216 Mhz ? (and its 462DMIPS)

Is there a simple test that can be done with an oscilloscope, or with a debug tool?

Tesla DeLorean
Guru
June 27, 2019

Tend to print these things out

printf("\n\nCore=%d, %d MHz\n", SystemCoreClock, SystemCoreClock / 1000000);

 printf("HCLK=%d\n", HAL_RCC_GetHCLKFreq());

 printf("APB1=%d\n", HAL_RCC_GetPCLK1Freq());

 printf("APB2=%d\n", HAL_RCC_GetPCLK2Freq());

But you can output some of the internal clocks via the MCO pin PA8 and scope those.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
jean
jeanAuthor
Senior
July 4, 2019

Thanks a lot, indeed I get the right frequency when I watch SystemCoreClock (216000000)

Somebody advised me to use this method:

__OSCILLO_1(true); // high level on a GPIO pin
for(i=0; i<1000;i++) __NOP();
__OSCILLO_1(false); // low level on a GPIO pin

My results are:

With GCC optimisation O4

1000 __NOP() = 10us on my oscilloscope

so 1 cycle = 10ps = 100MHz

Without optimisation

cycle of 1000 __NOP() = 32us on my oscilloscope

so 1 cycle = 32ps = 31MHz

The first thing that strikes me is that the optimisation really works on the __NOP() instruction, that should take always one cycle.

Secondly, with optimisation, it looks like I have something running around 100DMIPS, far from the 462DMIPS expected.

But maybe I have a naive point of view?

Piranha
Principal III
July 4, 2019

NOP does nothing. NOP is not necessarily a time-consuming NOP. The processor might remove it from the pipeline before it reaches the execution stage.

Use NOP for padding, for example to place the following instruction on a 64-bit boundary.

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0646a/CHDJJGFB.html

It can execute load and store operations in parallel with arithmetic operations with zero overhead on loops.

https://www.st.com/content/ccc/resource/training/technical/product_training/group0/84/37/18/81/04/b7/40/b3/STM32F7_System_Core/files/STM32F7_System_Core.pdf/jcr:content/translations/en.STM32F7_System_Core.pdf

Pages 2 and 6.

Your loop doesn't include loads or stores, so in this case IPC (instructions per clock) will be 1, which means 216 MIPS. And if the loop contains 2 instructions (not counting NOP), that's what You get - 108 M loop iterations per second. But for real data processing MIPS will be higher, because loads and stores will be executed in parallel with other instructions.

jean
jeanAuthor
Senior
July 5, 2019

Thanks a lot for your answer @Piranha​ , it's clearer to me now.

One more question: how is it possible for the uC to reach the 462 MIPS announced? That is more than twice the clock frequency.

waclawek.jan
Super User
July 5, 2019

The processor core is superscalar, i.e it can execute two arithmetic instructions at once.

JW