cancel
Showing results for 
Search instead for 
Did you mean: 

Timer frequency is way off

NRumm.1
Associate III

My STM32F303RE is running with an 8MHz crystal feeding into HSE:

NRumm1_0-1705434819174.png

Using TIM4 I want to generate 700 interrupts per second, but I only get 318.

As can be seen TIM4 runs at 64MHz and the following configuration should trigger about 318 interrupts:

NRumm1_1-1705434933781.png

NRumm1_2-1705434959841.png

Using the following formula:

(edit note - had a typo in the formula)

interrupts_per_second := clock_frequency / (prescaler + 1) / (counter_period + 1)

64 MHz / 3 / 30476 = 700

The 318 interrupts are way off the expected 700 and I just can't figure why. Any ideas are highly appreciated.

Thx in advance !

Woyzeck

 

1 ACCEPTED SOLUTION

Accepted Solutions
NRumm.1
Associate III

*** me - it was a bug. Deep in my code I disabled the interrupt and restarted the timer.

Thx for your support, guys - I learned a lot !

View solution in original post

13 REPLIES 13
AScha.3
Chief II

64M /3 / 30476 = 700 --- seem ok.

+ How you check the rate then ?

try -> set a led toggle in timer int and look with a scope at the pin.

If you feel a post has answered your question, please click "Accept as Solution".
TDK
Guru

> Using TIM4 I want to generate 700 interrupts per second, but I only get 318.

How are you monitoring this exactly?

Try clocking from internal HSI to rule out any HSE issues.

Your math (sort of) and expectations check out.

> 64 MHz / 2 / 30475 = 700

Think you made a typo here. Should be 3 instead of 2. Result is the same.

64 MHz / 3 / 30476 = 700.0043750273439 Hz

If you feel a post has answered your question, please click "Accept as Solution".
NRumm.1
Associate III

Thx for your support - I fixed the typo.

Replacing HSE with HSI for the whole board didn't fix the issue - now I get 320 interrupts per second (which is close to 318 and probably caused by the inaccuracy of HSI).

One thing that I observed is that the interrupt pulses are somehow irregular, meaning that the time between interrupts is varying by a single digit percentage, which is rather strange. Perhaps that's a hint to interrupt priority ?

So I'm still not making any progress here.

What I tried so far:

 

  • used MCO to output the HSI and HSE clock on pin PA8 - the measured frequency is 8MHz which is exactly what it should be, so the hardware setup is correct
  • used MCO to output LSI with a measured result of 37,9 kHz - everything ok here

Interestingly I was unable to output PLLCLK and SYSCLK using MCO. Once I use HSE as the clock source for SYSCLK I measure 8MHz which is ok. In my clock setup SYSCLK is generated from PLLCLK so I wonder if there's something wrong with my setup of PLLCLK, but I can't see what it is.

NRumm1_0-1705610225785.png

 

NRumm.1
Associate III

Some progress here - the issue with the lacking MCO signal for SYSCLK and PLLCLK was caused by the default speed setting of the MCO output pin PA8 as GPIO_SPEED_FREQ_LOW. Once set to GPIO_SPEED_FREQ_HIGH there's a signal on that pin and I can measure the expected 64 MHz.

So now I know that all clocks are working as expected, just the timer isn't.

TDK
Guru

What else is going on in your program? Feels like there is competition for cpu resources and/or an interrupt which is blocking for too long. Change frequency to say 10 Hz, do you get all of them?

If you feel a post has answered your question, please click "Accept as Solution".

I don't recall what the preference is on the F3 for PLL comparison frequency. For the F2/F4 it was 1-2 MHz

You should be able to get PLLCLK/2 out of MCU, and SYSCLK regardless of it's source / generation method.

Unpacking the RCC PLL settings might be more instructive of what's happening internally than Cube clock charts. Perhaps also the generated code.

Assuming this is a NUCLEO board, is that correct, or is this a custom board?

 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
/**
  * @brief  PLL source HSE bypass, and select the PLL as SYSCLK
  *         source.
  *         The system Clock is configured as follows :
  *            System Clock source            = PLL (HSE bypass)
  *            SYSCLK(Hz)                     = 64000000
  *            HCLK(Hz)                       = 64000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 2
  *            APB2 Prescaler                 = 1
  *            HSE Frequency(Hz)              = 8000000
  *            HSE PREDIV                     = 1
  *            PLLMUL                         = 8
  *            Flash Latency(WS)              = 2
  * @PAram  None
  * @retval None
  */
static void SystemClockConfig(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};

  /* Enable HSE bypass Oscillator, select it as PLL source and finally activate the PLL */
  RCC_OscInitStruct.OscillatorType        = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState              = RCC_HSE_BYPASS; // ST-LINK CMOS CLOCK
  RCC_OscInitStruct.PLL.PREDIV            = RCC_PREDIV_DIV1;

  RCC_OscInitStruct.PLL.PLLSource         = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLState          = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLMUL            = RCC_PLL_MUL8;

  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }

  /* Select the PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
  RCC_ClkInitStruct.ClockType       = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource    = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider   = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider  = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider  = RCC_HCLK_DIV1;
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }

  /* Optional: Disable HSI Oscillator (if the HSI is no more needed by the application)*/
  RCC_OscInitStruct.OscillatorType  = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState        = RCC_HSI_OFF;
  RCC_OscInitStruct.PLL.PLLState    = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }
}
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
NRumm.1
Associate III

I changed the timer config to get 100 Hz, but only measure 44.3 Hz. The factor between the expected and the actual frequency is constant over a wide range of timer settings - it stays around 2.2, so the expected frequency is 2.2 times the actual frequency.