cancel
Showing results for 
Search instead for 
Did you mean: 

Understanding SysTick_Handler()

Omar Suárez
Senior
Posted on August 28, 2017 at 13:46

Hello everyone,

I am setting up a project to make some tests with an STM32F7 MCU. I am using the STM32Cube HAL and the idea is to configure some timers and their interrupts using this HAL. The board is equipped with and 25MHz HSE so in the code I am configuring the HSE and disabling the PLL.

The problem is that if I don't write the SysTick_Handle() function inside my code the MCU and the interrupts don't work. The PC goes to the SysTick_Handler() defined inside 'startup_stm32f769xx.s'.

I am trying to understand why is it a must to define the SysTick_Handler() in the code so you can use the HAL properly but I am not sure whether I really understand why.

In the FAQs of the HAL manual the third step of the sequence to use the HAL drivers is:

'Add HAL_IncTick() function under SysTick_Handler() ISR function to enable polling process when using HAL_Delay() function'

But I am not using the HAL_Delay() function, so why I need to define it?

Anyone can help with this?

This is my code :

&sharpinclude <stm32f7xx_hal.h>

static TIM_HandleTypeDef s_TimerInstance;

void SysTick_Handler(void){

    HAL_IncTick();

    HAL_SYSTICK_IRQHandler();

}

/**

* @brief  This function initializes the SystemClock as HSE

* @param  None

* @retval None

*/

void initClock(){

    RCC_ClkInitTypeDef RCC_ClkInitStruct;

    RCC_OscInitTypeDef RCC_OscInitStruct;

    HAL_StatusTypeDef ret = HAL_OK;

    

    /* Enable Power Control clock */

    __HAL_RCC_PWR_CLK_ENABLE();

    

    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    

    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

    RCC_OscInitStruct.HSEState = RCC_HSE_ON;

    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_OFF;

    

    ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);

    

    if(ret  != HAL_OK){

    

        while(1){;}

    }

    

    /* Select HSE as system clock source */

    RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);

    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;

    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

    

    ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7);

    if(ret != HAL_OK){

    

        while(1){;}

    }

}

void InitializeTimer(){

    __TIM6_CLK_ENABLE();

    

    s_TimerInstance.Init.Prescaler = 512;

    s_TimerInstance.Init.CounterMode = TIM_COUNTERMODE_UP;

    s_TimerInstance.Init.Period = 65535;

    s_TimerInstance.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

    

    s_TimerInstance.Instance = TIM6;

    

    HAL_TIM_Base_Init(&s_TimerInstance);

    HAL_TIM_Base_Start_IT(&s_TimerInstance);

}

void GPIO_Init(){

    GPIO_InitTypeDef GPIO_InitStructure;

    

    __GPIOB_CLK_ENABLE();

    __GPIOJ_CLK_ENABLE();

    GPIO_InitStructure.Pin = GPIO_PIN_8;

    

    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;

    GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;

    GPIO_InitStructure.Pull = GPIO_NOPULL;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_InitStructure.Pin = GPIO_PIN_13;

    

    HAL_GPIO_Init(GPIOJ, &GPIO_InitStructure);

}

void TIM6_DAC_IRQHandler(){

    HAL_TIM_IRQHandler(&s_TimerInstance);

}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim){

    HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_8);

    HAL_GPIO_TogglePin(GPIOJ, GPIO_PIN_13);

}

int main(void){

    HAL_Init();

    initClock();

    GPIO_Init();

    InitializeTimer();

    HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 0, 0);

    HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);

    

    

    while(1){    }

}

Thanks in advanced,

Omar

#stm32f7 #interrupts #timer-interrupt #systick_handler
1 ACCEPTED SOLUTION

Accepted Solutions
Posted on August 28, 2017 at 14:19

Hello!

'But I am not using the HAL_Delay() function, so why I need to define it?

Anyone can help with this?'

SYSTICK  is not only used by HAL_Delay function.

Lot of HAL functions have internal timeouts based on this functionality.

HAL_IncTick() must be called every millisecond not necesarily from systick but from any other timer IRQ Handler (with hi priority ofcourse).

You have the right to redefine theese weak functions to control a different timer than systick.

HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)

void HAL_SuspendTick(void)

void HAL_ResumeTick(void)

Regards

vf

View solution in original post

5 REPLIES 5
Posted on August 28, 2017 at 14:19

Hello!

'But I am not using the HAL_Delay() function, so why I need to define it?

Anyone can help with this?'

SYSTICK  is not only used by HAL_Delay function.

Lot of HAL functions have internal timeouts based on this functionality.

HAL_IncTick() must be called every millisecond not necesarily from systick but from any other timer IRQ Handler (with hi priority ofcourse).

You have the right to redefine theese weak functions to control a different timer than systick.

HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)

void HAL_SuspendTick(void)

void HAL_ResumeTick(void)

Regards

vf

Posted on August 28, 2017 at 15:38

The use of the ticker is systemic to the HAL implementation, dangerously so, there are a vast number of blocking loops.

It is critical that the SysTick interrupt has the highest preemption level as your callback functions are occurring in interrupt context. Even for timeout loops one has to be skeptical of a design that can block in interrupt context for >1ms for no useful purpose.

There are some HAL/BSP implementation that use the RTC, HW counters, or TIM to generate the time base.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Omar Suárez
Senior
Posted on August 28, 2017 at 17:20

Thanks both for your fast replies.

Those were the answers I was looking for.

Paul Hankins
Associate II
Posted on August 28, 2017 at 18:45

Also notice that many of the timeouts in the HAL read the timer tick count at the entry into the HAL call. And like the USART code, when calling it as a blocking call, checks for the timeout delta at the end of each byte being written. If you get interrupted away, the tick count keep going while interrupted away. When you return the output of the data my have worked on time, but the function will return a timeout error because the delta was larger than the timeout value passed in.

Posted on November 14, 2017 at 17:52

 s_TimerInstance.Init.Prescaler = 512; // Divide by 513 ? Value here is N-1 for N states, ie 0..N-1

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..