2019-06-27 03:13 AM
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!
2019-06-27 04:35 AM
Isn't TIM2 on APB1 that you have in DIV4 mode? The TIM will be clocking at AHB/2, ie 2x APB1CLK
2019-06-27 05:37 AM
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?
2019-06-27 05:47 AM
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.
2019-06-27 07:04 AM
Use MCO output with proper division faktor or a timer output as PWM with know ARR.
2019-07-04 09:36 AM
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?
2019-07-04 11:17 AM
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.
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.
2019-07-05 03:29 AM
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.
2019-07-05 03:56 AM
The processor core is superscalar, i.e it can execute two arithmetic instructions at once.
JW