1
\$\begingroup\$

I am having problems with interrupt handlers on an STM32L052C8T microcontroller. Every program that I try to run hangs forever after an interrupt is fired. This holds for SysTick interrupts, other timer interrupts (TIM2), and EXTI interrupts (EXTI6). I haven't tried other types of interrupt.

I suspect that the program is getting trapped in an infinite loop within some system code that is meant to pick the correct interrupt handler. Unfortunately, my debugger lets me access this system code only as assembly.

For simplicity, I attach a very basic program that hangs after a SysTick interrupt. The exact point where the program starts hanging depends on the value of the SysTick->LOAD register. Small values of this register cause the program to hang within HAL_Init() itself, higher values within SystemClock_Config() or even further.

#include "main.h"

void SystemClock_Config(void);

int main(void)
{
  HAL_Init();

  SystemClock_Config();

  int count;
  while (1)
  {
      HAL_Delay(3000);
      count++;
  }
}

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSICalibrationValue = 0;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

void Error_Handler(void)
{
  __disable_irq();
  while (1)
  {
  }
}

#ifdef  USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif /* USE_FULL_ASSERT */

I am using STM32CubeIDE with default settings for the compiler, linker, and debugger. These same settings worked perfectly (i.e., no hanging) on a different microcontroller, STM32L051K8T.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ If that's your entire program then what you're missing is the actual SysTick interrupt handler function. What code are you expecting to be executed when the SysTick interrupt fires? \$\endgroup\$
    – brhans
    Jan 27, 2021 at 18:29
  • \$\begingroup\$ SysTick_Handler() is defined in another file and has a default definition. However, it is not entered by the program. \$\endgroup\$
    – drebaz
    Jan 27, 2021 at 19:55
  • 1
    \$\begingroup\$ Your project should have an assembler 'startup' file, probably named something like 'startup_stm32lxxx.s' with a __vector_table section near the beginning. In that vector table should be an entry for the SysTick Handler. Make sure the name there exactly matches that SysTick_Handler() function you have. \$\endgroup\$
    – brhans
    Jan 27, 2021 at 20:11
  • \$\begingroup\$ I do have that file. However, the vtable section starts with ".section .isr_vector", not "__vector_table". In it I see the names of interrupt handlers, including "SysTick_Handler". \$\endgroup\$
    – drebaz
    Jan 28, 2021 at 7:41
  • \$\begingroup\$ The problem is now solved. It was enough to uncomment one line in "system_stm32l0xx.c": /* #define USER_VECT_TAB_ADDRESS */. This allows SCB->VTOR to be assigned the correct vector table address in SystemInit(). \$\endgroup\$
    – drebaz
    Jan 28, 2021 at 11:03

1 Answer 1

2
\$\begingroup\$

Uncommenting the line #define USER_VECT_TAB_ADDRESS in system_stm32wlxx.c solved the problem for me with STM32WLE5C8U6. Will update if I discover any unintended side effects.


UPDATE:
It would appear that the problem in my case was the OPTION BYTES not being correctly set for my STM32WLE5C8. The option bytes are used to configure the flash areas to be used by the MCU at boot. The option bytes can be set by using the STM32CubeProgrammer utility (easy way) or in firmware using the HAL_FLASH tools (hard way - probably required for production programming). In my case uncommenting the #define USER_VECT_TAB_ADDRESS line worked as long as I was debugging but failed in normal runtime.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.