cancel
Showing results for 
Search instead for 
Did you mean: 

Timers frequency divided by 2

jean
Senior

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!

8 REPLIES 8

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 Venmo
Up vote any posts that you find helpful, it shows what's working..
jean
Senior

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?

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 Venmo
Up vote any posts that you find helpful, it shows what's working..

Use MCO output with proper division faktor or a timer output as PWM with know ARR.

jean
Senior

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?

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
Senior

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.

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

JW