cancel
Showing results for 
Search instead for 
Did you mean: 

GPIO timing issue in Timer ISR

RN
Senior
Posted on May 18, 2018 at 12:11

Hello ,

I am toggling a gpio inside the timer ISR . the timer ISR triggers for every 1 sec.

Actually i am not able to see perfect 1 sec of gpio toggling . it also differs at different AHB frequency . i have included 2 cases with snapshot. please help me understand why i can not get perfect 1 sec gpio toggling and why it is different at 2 different ahb frequencies .

In the ISR i am just doing GPIOC->ODR ^= 0x2000U;

case 1 : AHB = 16Mhz HSI, Prescaler of timer = 999, period = 15999  ( in the image there is a difference of 10ms)

0690X0000060KpzQAE.png

case 2 : AHB= 50Mhz, Timer clock = 50Mhz, Prescaler of timer = 999, period = 49999 ( in the image there is a difference of 25ms)

0690X0000060KqnQAE.png

In both case it is showing different output . 

8 REPLIES 8
Nigel Meijer
Associate II
Posted on May 18, 2018 at 12:51

A few things have effect on the crystal, Like temperature and supply voltage.

For example in the STM32L083CZ datasheet on page 87:

MSI oscillator frequency drift   0 °C ≤ TA ≤ 85 °C -  ±3

A temperature between 0 and 85 degrees could cause a frequency drift of plus minus 3%

Same happens with the supply voltage.

Dont know why with different settings you get a different timing..
Posted on May 18, 2018 at 14:25

Hard to replicate from screen shots. Define which STM32, and show code.

Using HSE clock source?

Can you try with a calibrated scope?

Can you output internal clocks (HSI, HSE, PLL, etc) via MCO pin PA8, and scope those?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on May 18, 2018 at 15:23

 ,

 ,

Hello Clive , ,

Thanks for the reply . ,

i am using stm32f446re nucleo board . , not using HSE. ,

i am using saleae logic usb logic analyzer . i dont have a calibrated scope.

HSI is 16Mhz verified using MCO. on MCO pin i can measure precisely ,

here is code i used. ,

int main(void)

 ,

{

 ,

 ,

HAL_Init(),

SystemClock_Config(SYS_CLOCK_FREQ_50_MHZ),

 ,

 ,

TIMER_Init(),

 ,

 ,

GPIO_Init(),

 ,

 ,

HAL_TIM_Base_Start_IT(&,htim6),

 ,

 ,

while(1),

 ,

 ,

return 0,

 ,

}

void GPIO_Init(void)

 ,

{

 ,

/* GPIO Ports Clock Enable */

 ,

__HAL_RCC_GPIOC_CLK_ENABLE(),

 ,

__HAL_RCC_GPIOH_CLK_ENABLE(),

 ,

__HAL_RCC_GPIOA_CLK_ENABLE(),

 ,

__HAL_RCC_GPIOB_CLK_ENABLE(),

 ,

 ,

GPIO_InitTypeDef gpio_button,

 ,

gpio_button.Mode = GPIO_MODE_OUTPUT_PP,

 ,

gpio_button.Pin = GPIO_PIN_13,

 ,

gpio_button.Pull = GPIO_NOPULL,

 ,

gpio_button.Speed = GPIO_SPEED_FREQ_LOW,

 ,

HAL_GPIO_Init(GPIOC,&,gpio_button),

 ,

}

void TIMER_Init(void)

 ,

{

TIM_MasterConfigTypeDef sMasterConfig,

 ,

htim6.Instance = TIM6,

 ,

htim6.Init.Prescaler = 999,

 ,

htim6.Init.CounterMode = TIM_COUNTERMODE_UP,

 ,

htim6.Init.Period = (50000-1),

 ,

htim6.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1,

 ,

if (HAL_TIM_Base_Init(&,htim6) != HAL_OK)

 ,

{

 ,

_Error_Handler(__FILE__, __LINE__),

 ,

}

 ,

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET,

 ,

sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE,

 ,

if (HAL_TIMEx_MasterConfigSynchronization(&,htim6, &,sMasterConfig) != HAL_OK)

 ,

{

 ,

_Error_Handler(__FILE__, __LINE__),

 ,

}

 ,

 ,

}

void SystemClock_Config(uint8_t clock_freq)

 ,

{

 ,

♯ if 1

 ,

RCC_OscInitTypeDef RCC_OscInitStruct,

 ,

RCC_ClkInitTypeDef RCC_ClkInitStruct,

 ,

 ,

/**Configure the main internal regulator output voltage

 ,

*/

 ,

__HAL_RCC_PWR_CLK_ENABLE(),

//__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3),

 ,

 ,

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI,

 ,

RCC_OscInitStruct.HSIState = RCC_HSI_ON,

 ,

RCC_OscInitStruct.HSICalibrationValue = 16,

 ,

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON,

 ,

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI,

switch(clock_freq)

 ,

{

 ,

case SYS_CLOCK_FREQ_50_MHZ:

 ,

RCC_OscInitStruct.PLL.PLLM = 8,

 ,

RCC_OscInitStruct.PLL.PLLN = 50,

 ,

RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2,

 ,

RCC_OscInitStruct.PLL.PLLQ = 2,

 ,

RCC_OscInitStruct.PLL.PLLR = 2,

 ,

 ,

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_DIV2,

 ,

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1,

 ,

break,

 ,

 ,

case SYS_CLOCK_FREQ_84_MHZ:

 ,

RCC_OscInitStruct.PLL.PLLM = 8,

 ,

RCC_OscInitStruct.PLL.PLLN = 84,

 ,

RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2,

 ,

RCC_OscInitStruct.PLL.PLLQ = 2,

 ,

RCC_OscInitStruct.PLL.PLLR = 2,

 ,

 ,

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_DIV2,

 ,

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1,

 ,

break,

 ,

 ,

case SYS_CLOCK_FREQ_120_MHZ:

 ,

RCC_OscInitStruct.PLL.PLLM = 8,

 ,

RCC_OscInitStruct.PLL.PLLN = 120,

 ,

RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2,

 ,

RCC_OscInitStruct.PLL.PLLQ = 2,

 ,

RCC_OscInitStruct.PLL.PLLR = 2,

 ,

 ,

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,

 ,

break,

 ,

 ,

default:

 ,

return ,

 ,

 ,

}

 ,

 ,

if (HAL_RCC_OscConfig(&,RCC_OscInitStruct) != HAL_OK)

 ,

{

 ,

_Error_Handler(__FILE__, __LINE__),

 ,

}

 ,

 ,

 ,

 ,

if (HAL_RCC_ClockConfig(&,RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)

 ,

{

 ,

_Error_Handler(__FILE__, __LINE__),

 ,

}

 ,

 ,

 ,

/**Configure the Systick interrupt time

 ,

*/

 ,

uint32_t hclk_freq = HAL_RCC_GetHCLKFreq(),

 ,

HAL_SYSTICK_Config(hclk_freq/1000),

/**Configure the Systick

 ,

*/

 ,

HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK),

/* SysTick_IRQn interrupt configuration */

 ,

HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0),

}

/**

 ,

* @brief This function handles TIM6 global interrupt and DAC1, DAC2 underrun error interrupts.

 ,

*/

 ,

void TIM6_DAC_IRQHandler(void)

 ,

{

 ,

/* USER CODE BEGIN TIM6_DAC_IRQn 0 */

 ,

 ,

//HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5),

 ,

//GPIOC->,ODR ^= 0x2000U,

 ,

GPIOC->,ODR ^= 0x2000U,

 ,

/* USER CODE END TIM6_DAC_IRQn 0 */

 ,

HAL_TIM_IRQHandler(&,htim6),

 ,

/* USER CODE BEGIN TIM6_DAC_IRQn 1 */

/* USER CODE END TIM6_DAC_IRQn 1 */

 ,

}
Posted on May 18, 2018 at 15:29

The Nucleo should be able to source an 8 MHz HSE via the ST-LINK

The TIM should be able to drive a pin in toggle mode directly

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on May 18, 2018 at 15:34

i can verify toggle mode . but before that i just want to know what exactly stopping in the code to get 1 sec precise gpio toggling. Do you mean HSI and PLLCLK is affecting this ? this may get better if i use HSE ? The first output is with HSI and second one using PLLCLK.

Posted on May 18, 2018 at 17:54

I would only expect a micro-second or less of latency, and jitter, of an interrupt based pin toggle from the TIM.

If the values are being measured wrong you have a couple of potential things going on, either the STM32 side time bases are wrong, or the equipment being used to measure is wrong, or has course granularity (based on sample buffer size and interval).

I'd start with a properly calibrated scope, or frequency counter.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on May 18, 2018 at 23:27

'

what exactly stopping in the code to get 1 sec precise gpio toggling.'

you generally don't get that much timing error when interrupts are used.

I would check the following:

1. you aren't polling;

2. disable as much other tasks as you can and shrink it to a minimalist configuration to pinpoint problems.

3. check your measurement equipment to make sure that you are really seeing what you think you are seeing.

...

John Craven
Senior
Posted on May 19, 2018 at 17:37

From the manual;

6.2.2 HSI clock

...

Calibration

RC oscillator frequencies can vary from one chip to another due to manufacturing process variations, this is why each device is factory calibrated by ST for 1% accuracy at TA= 25 °C.

Yor are getting results close to the factory specification.

Have you calibrated the HSI better than 1%?

Using HSE from ST-link on nucleo boards has always be much better than HSI in my experience (12-15 boards).