cancel
Showing results for 
Search instead for 
Did you mean: 

In the STM32MP157 I am trying to program an interrupt every 100 us using timer 14. It looks like the code generated is correct, but the result is not correct. It looks like the DiV4 has no effect. The timing is the same as no divide.

KiptonM
Lead

Looking at the clock in the MX Device Configuration Tool it says 204 to APB1 Timer Clocks (MHz).

To get to 10000 Hz I have to divide 204 MHz by 20400.

Fortunately there are a bunch of ways to do this. But on the first try I tried

Prescaler 51

Counter Period 100

Internal Clock Division Division by 4

The reason I did it this way is that I suspected 10000 Hz will be too fast and they will eventually go to 1000 Hz or something between 1000 Hz and 10000 Hz and it would be easy to change the counter period for the new value.

I saved it and generated new code.

static void MX_TIM14_Init(void)
{
 
  /* USER CODE BEGIN TIM14_Init 0 */
 
  /* USER CODE END TIM14_Init 0 */
 
  TIM_OC_InitTypeDef sConfigOC = {0};
 
  /* USER CODE BEGIN TIM14_Init 1 */
 
  /* USER CODE END TIM14_Init 1 */
  htim14.Instance = TIM14;
  htim14.Init.Prescaler = 51;
  htim14.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim14.Init.Period = 100;
  htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV4;
  htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim14) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_OC_Init(&htim14) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_TIMING;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_OC_ConfigChannel(&htim14, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM14_Init 2 */
  /* USER CODE END TIM14_Init 2 */
 
}

The generated code looks good.

The interrupt would toggle a GPIO and I can see the timing.

My USB logic Analyzer was set to sample at 25 Msamples/sec

And I was reading 25.72 and 25.76 microseconds (us) when I expected 100 us.

It was off by a factor of 4.

It made me think it was the divide by 4.

So I went back to MX Device Configuration Tool and changed the Divide by 4 to No Division.

The result was:

Prescaler 51

Counter Period 100

Internal Clock Division No Division

I saved and it generated the code

static void MX_TIM14_Init(void)
{
 
  /* USER CODE BEGIN TIM14_Init 0 */
 
  /* USER CODE END TIM14_Init 0 */
 
  TIM_OC_InitTypeDef sConfigOC = {0};
 
  /* USER CODE BEGIN TIM14_Init 1 */
 
  /* USER CODE END TIM14_Init 1 */
  htim14.Instance = TIM14;
  htim14.Init.Prescaler = 51;
  htim14.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim14.Init.Period = 100;
  htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim14) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_OC_Init(&htim14) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_TIMING;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_OC_ConfigChannel(&htim14, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM14_Init 2 */
  /* USER CODE END TIM14_Init 2 */
 
}

Looking at the logic analyzer I got the exact same result. An interrupt every 25.72 and 25.76 us, when it should have been 1/4 that.

Like I said there multiple ways to do this, so I changed the prescaler from 51 to 204.

Prescaler 204

Counter Period 100

Internal Clock Division No Division

Saved and generated new code.

static void MX_TIM14_Init(void)
{
 
  /* USER CODE BEGIN TIM14_Init 0 */
 
  /* USER CODE END TIM14_Init 0 */
 
  TIM_OC_InitTypeDef sConfigOC = {0};
 
  /* USER CODE BEGIN TIM14_Init 1 */
 
  /* USER CODE END TIM14_Init 1 */
  htim14.Instance = TIM14;
  htim14.Init.Prescaler = 204;
  htim14.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim14.Init.Period = 100;
  htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim14) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_OC_Init(&htim14) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_TIMING;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_OC_ConfigChannel(&htim14, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM14_Init 2 */
  /* USER CODE END TIM14_Init 2 */
 
}

This time I got the interrupt every 101.48 to 101.52 us which I was expecting.

I have not dug into your code to find out why the Divide by 4 it is not working. I am just saying it is not working.

The about says I am running:

Version: 1.8.0

Build: 11526_20211125_0815 (UTC)

1 ACCEPTED SOLUTION

Accepted Solutions
PatrickF
ST Employee

Hi @KiptonM​ ,

at first look, the

htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

relate to

0693W00000Hr37TQAR.pngwhich is not related to counting clock, but rather the clock used for input capture filtering.

I agree CubeMx might be confusing (as my understanding is that CKD is useless except in capture mode).

Reference Manual should always be used whenever there is uncertainty (timers offers so many options that it is always complex to set up).

I think to achieve your required interrupt rate, you should just play with .Prescaler and .Period values.

Regards.

In order to give better visibility on the answered topics, please click on 'Select as Best' on the reply which solved your issue or answered your question. See also 'Best Answers'

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.

View solution in original post

3 REPLIES 3
KiptonM
Lead

In stm32mp1xx_hal_tim.c

around line 5959

is the code

 if (IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx))
  {
    /* Set the clock division */
    tmpcr1 &= ~TIM_CR1_CKD;
    tmpcr1 |= (uint32_t)Structure->ClockDivision;
  }

I have no idea what IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx) does, but it returns false.

So it does not do anything to change the Divide by.

Found it in stm32mp157axx_cm4.h around line 38907

/****************** TIM Instances : supporting clock division *****************/
#define IS_TIM_CLOCK_DIVISION_INSTANCE(INSTANCE)\
  (((INSTANCE) == TIM1)    || \
   ((INSTANCE) == TIM2)    || \
   ((INSTANCE) == TIM3)    || \
   ((INSTANCE) == TIM4)    || \
   ((INSTANCE) == TIM5)    || \
   ((INSTANCE) == TIM8)    || \
   ((INSTANCE) == TIM15)   || \
   ((INSTANCE) == TIM16)   || \
   ((INSTANCE) == TIM17))

It does not have TIM14 -- Timer 14

PatrickF
ST Employee

Hi @KiptonM​ ,

at first look, the

htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

relate to

0693W00000Hr37TQAR.pngwhich is not related to counting clock, but rather the clock used for input capture filtering.

I agree CubeMx might be confusing (as my understanding is that CKD is useless except in capture mode).

Reference Manual should always be used whenever there is uncertainty (timers offers so many options that it is always complex to set up).

I think to achieve your required interrupt rate, you should just play with .Prescaler and .Period values.

Regards.

In order to give better visibility on the answered topics, please click on 'Select as Best' on the reply which solved your issue or answered your question. See also 'Best Answers'

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.
KiptonM
Lead

Thanks that is what I did and it is working now.