STM32 - Timers - Measuring Time
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);