Loading...
 
Skip to main content

System Workbench for STM32


Timer Interrupt Not Working

I am using STM32F103C8 with STM32CubeMX and SW4STM32. The CPU is running at 64 MHz and I have verified it with PWM frequency.

I am trying to generate an update interrupt from timer 4 so I generated a CubeMX project and copied all its files into a SW4STM32 project.

The code hangs (or sticks in a never ending loop) when the function HAL_TIM_Base_Start_IT(&htim4) is called. If I change that function to HAL_TIM_Base_Start(&htim4) then the rest of the code runs but obviously the interrupts aren't generated.

What I think, either some assert is failing or there is some problem in interrupt handling.

Can anyone point out what I am doing wrong?

Copy to clipboard
#include "stm32f1xx_hal.h" TIM_HandleTypeDef htim2; TIM_HandleTypeDef htim4; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_TIM2_Init(void); static void MX_TIM4_Init(void); int main(void) { HAL_Init(); /* Configure the system clock */ SystemClock_Config(); HAL_MspInit(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_TIM2_Init(); MX_TIM4_Init(); /* USER CODE BEGIN 2 */ HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2); HAL_TIM_Base_Start_IT(&htim4); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET); // controller doesn't reach here while (1) { /* USER CODE END WHILE */ HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET); // HAL_Delay(1950); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET); HAL_Delay(150); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET); HAL_Delay(100); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET); HAL_Delay(150); /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** System Clock Configuration */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_PeriphCLKInitTypeDef PeriphClkInit; 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_DIV2; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16; HAL_RCC_OscConfig(&RCC_OscInitStruct); RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2); PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV8; HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); /* SysTick_IRQn interrupt configuration */ HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); } /* TIM2 init function */ void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig; TIM_MasterConfigTypeDef sMasterConfig; TIM_OC_InitTypeDef sConfigOC; htim2.Instance = TIM2; htim2.Init.Prescaler = 1; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 1024; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_Base_Init(&htim2); sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig); HAL_TIM_PWM_Init(&htim2); sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig); sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 128; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2); } /* TIM4 init function */ void MX_TIM4_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig; TIM_MasterConfigTypeDef sMasterConfig; htim4.Instance = TIM4; htim4.Init.Prescaler = 8000; htim4.Init.CounterMode = TIM_COUNTERMODE_UP; htim4.Init.Period = 8000; htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_Base_Init(&htim4); sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig); sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig); } /** Configure pins as * Analog * Input * Output * EVENT_OUT * EXTI */ void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; /* GPIO Ports Clock Enable */ __GPIOC_CLK_ENABLE(); __GPIOA_CLK_ENABLE(); /*Configure GPIO pin : PC13 */ GPIO_InitStruct.Pin = GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /*Configure GPIO pin : PCA13 */ GPIO_InitStruct.Pin = GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) { GPIO_InitTypeDef GPIO_InitStruct; if(htim_base->Instance==TIM2) { /* USER CODE BEGIN TIM2_MspInit 0 */ /* USER CODE END TIM2_MspInit 0 */ /* Peripheral clock enable */ __TIM2_CLK_ENABLE(); /**TIM2 GPIO Configuration PA1 ------> TIM2_CH2 */ GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN TIM2_MspInit 1 */ /* USER CODE END TIM2_MspInit 1 */ } else if(htim_base->Instance==TIM4) { /* USER CODE BEGIN TIM4_MspInit 0 */ /* USER CODE END TIM4_MspInit 0 */ /* Peripheral clock enable */ __TIM4_CLK_ENABLE(); /* Peripheral interrupt init*/ HAL_NVIC_SetPriority(TIM4_IRQn, 0, 1); HAL_NVIC_EnableIRQ(TIM4_IRQn); /* USER CODE BEGIN TIM4_MspInit 1 */ /* USER CODE END TIM4_MspInit 1 */ } } void TIM4_IRQHandler(void) { /* USER CODE BEGIN TIM4_IRQn 0 */ /* USER CODE END TIM4_IRQn 0 */ HAL_TIM_IRQHandler(&htim4); /* USER CODE BEGIN TIM4_IRQn 1 */ HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); /* USER CODE END TIM4_IRQn 1 */ }

Did you compile this a C or C++. If you used c++ you need to put an 'extern "C"' wrapper around the ISR.

Randy

Thanks very much @RandallStockberger. I have been pulling my hair over this for the last 4 days.

There is already an extern C around the void TIM4_IRQHandler(void) declaration in stm32f1xx_it.h

  1. ifdef __cplusplus

extern "C" {

  1. endif


/* Includes ----------------------*/
/* Exported types --------------------*/
/* Exported constants --------------------*/
/* Exported macro --------------------*/
/* Exported functions ------------------- */

void SysTick_Handler(void);
void TIM4_IRQHandler(void);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);

  1. ifdef __cplusplus

}

  1. endif

Someone on another forum has pointed out to check the startup_stm32.s . When I did, it had the following contents in in a particular table. Following lines and all zeros below. There is no mention of TIM4_IRQHandler . I think there is a problem here. Can anyone share some insight on where TIM4_IRQHandler should be located in this table and what might have caused it to miss out??


g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0


When I created the project, SW4STM32 should have included the startup file for the controller I am using, i.e. STM32F103C8. However, it has included the generic STM32f startup file startup_stm32.s . When I searched for the startup file startup_stm32f103x8 in the Firmware folder, it had the startup for every other controller in the series, (stm32f103x6, xb, xc, xg) but not x8.

So what's everyone's verdict?? Am I doomed??


IT'S WORKING!!


I just made a new project in the SW4STM32 and it includes the correct startup file with all the interrupt vectors. The firmware still doesn't have startup_stm32f103x8.s file and the name of the file in startup folder is startup_stm32.s but now it has all the interrupt vectors and other definitions.

The problem has vanished now and the interrupt is working like a charm. 🙄

But I am still skeptic of why the startup file was missed in the first try.

The startup_stm32.s file has the following comment in the beginning, so I am relieved.

/**
******************************************************************************
* @file startup_stm32.s dedicated to STM32F103C8Tx device
* @author Ac6
* @version V1.0.0
* @date 2018-04-05
******************************************************************************
*/