STM32 - Timers - Measuring Time

From Embedded Workshop
Revision as of 11:42, 11 June 2024 by JGMerkle (talk | contribs) (→‎Start The Timer)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Timers

Each of the STM32 parts has multiple timers, but some are better than others for measuring the duration of a function.

Profiling

I firmly believe until you actually measure the time a function takes, you are just guessing,
thinking "the function is working just fine"....
But, to measure the duration of many functions, you need a time base much finer than an OS Tick.
Micro-second resolution is often required.
Although I'd like a 32 bit timer, not all the STM32 parts have one.
I'm pretty sure all have at least a 16-bit timer.  Let's choose an unused timer, and get it
counting micro-second units of time.

Choose and Configure A Timer

Open STM32CubeIDE, <project>.ioc file to look at the timers and find one that's available
1) Click on "Pinout & Configuration" tab
2) Click on "Timers"
3) For STM32 devices without a 32-bit timer, like the STM32-F103RB, use TIM4
   (If your device has a 32-bit timer, like TIM5, use that)
4) Since we don't need an output pin for this timer, configure it as follows:
   Slave Mode: Disable
   Trigger Source: Disable
   □  Internal Clock - unchecked
   Channel1: PWM Generation No Output
5) In the Parameter Settings section, configure as follows:
   Prescaler (PSC -16 bits value): 72-1     This assumes the SYSCLK is 72MHz.  (Adjust accordingly)
   Counter Mode: Up
   Counter Period (AutoReload Register - 16 bits value): 65535
   Internal Clock Division (CKD): No Division
   auto-reload preload: Disable
   PWM Generation Channel 1
   Mode: PWM mode 1
   Pulse (16 bits value): 0
   Output compare preload Enable
   Fast Mode: Disable
   CH Polarity: High

The above selections will configure Timer4 to run as a 1us period timer

Start The Timer

In main.c, find the function, MX_TIM4_Init()
Insert HAL_TIM_Base_Start() function call between the comments as shown below:
 /* USER CODE BEGIN TIM4_Init 2 */
 // Start timer running
 HAL_TIM_Base_Start(&htim4);
 /* USER CODE END TIM4_Init 2 */

Use The Timer

Within the body of the code, where you wish to time something, like HAL_Delay(50), use something like the following:
volatile TIM_TypeDef *TIMx = TIM4; // Use data structure pointer to access TIM4 registers
uint32_t start_us = TIMx->CNT; // read us hardware timer
HAL_Delay(50); // delay 50us
uint32_t stop_us = TIMx->CNT; // read us hardware timer
// Report results
if(stop_us < start_us) stop_us += 1<<16; // roll-over, add 16-bit roll-over offset
printf("TIM4 time: %lu us\n",stop_us - start_us);