cancel
Showing results for 
Search instead for 
Did you mean: 

Iterrupt handlers don't compile

Podkovirin.Anton
Associate II
Posted on July 09, 2016 at 00:10

I'm writing code for STM32F4.

I'm trying to set interrupt handler for TIM1 which is configured as PWM1 output.

The timer itself works, but I'm unable to configure the interrupt handler

 

static void initTimer(void){

TIM_TimeBaseInitTypeDef TIM_BaseStruct;

RCC_APB2PeriphClockCmd(MOTOR_TIM_CLK, ENABLE);

TIM_BaseStruct.TIM_Prescaler = (APBx_FREQ/CNT_FREQ) - 1;

    TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_BaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;

    TIM_BaseStruct.TIM_RepetitionCounter = 0;

    TIM_TimeBaseInit(MOTOR_TIM, &TIM_BaseStruct);

}

static void initPWM(void)

{

    TIM_OCInitTypeDef TIM_OCStruct;

    /* PWM mode 1 = Set on compare match */

    TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM1;

    TIM_OCStruct.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCStruct.TIM_OutputNState = TIM_OutputNState_Enable;

    TIM_OCStruct.TIM_OCPolarity = TIM_OCPolarity_High;

    TIM_OCStruct.TIM_OCNPolarity = TIM_OCNPolarity_Low;

    TIM_OCStruct.TIM_OCIdleState = TIM_OCIdleState_Set;

    TIM_OCStruct.TIM_OCNIdleState = TIM_OCNIdleState_Reset;

    TIM_OC1Init(MOTOR_TIM,&TIM_OCStruct);

    

}

static void initInterrupt(void){

    NVIC_InitTypeDef nvic_init;

    TIM_ITConfig(MOTOR_TIM, TIM_IT_Update, DISABLE);

    nvic_init.NVIC_IRQChannel                   = TIM1_UP_TIM10_IRQn;

    nvic_init.NVIC_IRQChannelPreemptionPriority = 0;

    nvic_init.NVIC_IRQChannelSubPriority        = 1;

    nvic_init.NVIC_IRQChannelCmd                = ENABLE;

    NVIC_Init(&nvic_init);/* enables the device and sets interrupt priority */

    TIM_ClearITPendingBit(MOTOR_TIM, TIM_IT_Update);

    TIM_ITConfig(MOTOR_TIM, TIM_IT_Update, ENABLE);

}

void MotorDriver_Init(void){

RCC_ClocksTypeDef rccClocks;

RCC_GetClocksFreq(&rccClocks);

APBx_FREQ = rccClocks.PCLK2_Frequency * 2;

initGpio();

initTimer();

initPWM();

initInterrupt();

}

void MotorDriver_Isr(void)

{

    if (TIM_GetITStatus(MOTOR_TIM, TIM_IT_Update) != RESET)  {

if (number_of_steps > 0) {

number_of_steps--;

if(number_of_steps == 0){

TIM_ITConfig(MOTOR_TIM,TIM_IT_Update, DISABLE);

stopMotor();

}

}

TIM_ClearITPendingBit(MOTOR_TIM, TIM_IT_Update);

    }

}

void TIM1_UP_TIM10_IRQHandler(void)

{

MotorDriver_Isr();

}

When I run the code it executes without any errors/warnings, but I'm unable to set breakpoints in the handler or Driver_Isr. After all the configurations it jumps to the HardFault handler. If I disable the interrupt configuration, everything else works fine. It seems to me like the firmware is just unable to jump to the handler code.

I also cannot see anything about the handler in the map file. I re verified that the vector address and handler definitions are correct in the startup and stm32f4xx.h files.

The systick interrupt seems to be working fine. Any other handler I tried to configure introduced similar behavior 

What am I doing wrong/missing?
6 REPLIES 6
Posted on July 09, 2016 at 02:10

Parameters missing, and you don't enable timer

TIM_BaseStruct.TIM_Prescaler = 0;
TIM_BaseStruct.TIM_Period = (APBx_FREQ/CNT_FREQ) - 1;
TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_BaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_BaseStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_BaseStruct);
...
/* TIM enable counter */
TIM_Cmd(TIM1, ENABLE);
/* Main Output Enable, and Input */
TIM_CtrlPWMOutputs(TIM1, ENABLE);

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Podkovirin.Anton
Associate II
Posted on July 09, 2016 at 02:23

Sorry, forgot the function that starts the timer.

void MotorDriver_Start(MotorDirection_t direction, uint32_t speed, MotorDuty_t duty, uint32_t steps){

setDirection(direction);

number_of_steps = steps;

TIM_SetAutoreload(MOTOR_TIM, CNT_FREQ/speed - 1);

TIM_SetCompare1(MOTOR_TIM, ((CNT_FREQ/speed - 1) * duty) / 100);

    TIM_Cmd(MOTOR_TIM,ENABLE);

    TIM_CtrlPWMOutputs(MOTOR_TIM,ENABLE);

}

As I said, the timer itself works as expected. The issue is only with the interrupt and it seems like it is not only that interrupt. 

In addition, optimization is disabled.

Posted on July 09, 2016 at 02:51

Are you using a .CPP file?

Does the name exactly match the one in the startup.s file's vector table?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Podkovirin.Anton
Associate II
Posted on July 10, 2016 at 15:52

No, I'm using a .c file.

Yes, the name matches exactly the name in the startup.s file.

Posted on July 10, 2016 at 22:12

Perhaps you can present this as a complete and concise project. I don't want to have to play 20 questions to figure out what's wrong.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on July 10, 2016 at 23:34

I'd start with this...

// STM32F4-Discovery TIM1 40KHz PWM, modulating 1 second ON, 10 seconds OFF (PA.08 TIM1_CH1) - sourcer32@gmail.com
#include ''stm32f4_discovery.h''
/**************************************************************************/
void RCC_Configure(void)
{
/* GPIOA clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* TIM1 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
}
/**************************************************************************/
void NVIC_Configure(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the TIM1 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**************************************************************************/
void GPIO_Configure(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOA Configuration: TIM1 CH1 (PA8) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Connect TIM1 pins to AF */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_TIM1);
}
/**************************************************************************/
uint32_t Period;
void TIM1_Configure(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
Period = SystemCoreClock / 40000; // 40 KHz, from APB2 clock *2, nominally 168 MHz
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_Period = Period - 1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_Pulse = Period / 2; // 50/50 duty
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
/* TIM Interrupts enable */
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
/* Main Output Enable, and Input */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
/* TIM enable counter */
TIM_Cmd(TIM1, ENABLE);
}
/**************************************************************************/
void TIM1_UP_TIM10_IRQHandler(void) // 40KHz
{
static int modulatingcount = 0;
// 1 Second On - 40000 ticks
// 10 Seconds Off - 400000 ticks
// full cycle 440000 ticks
if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) // Validate source
{
TIM_ClearITPendingBit(TIM1, TIM_IT_Update); // Clear source
modulatingcount = (modulatingcount + 1) % 440000;
if (modulatingcount > 40000)
TIM1->CCR1 = 0; // Off
else
TIM1->CCR1 = Period / 2; // 50/50 duty
}
}
/**************************************************************************/
int main(void)
{
RCC_Configure();
NVIC_Configure();
GPIO_Configure();
TIM1_Configure();
while(1); // Do not exit
}
/**************************************************************************/
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d

'', file, line) */
while (1)
{}
}
#endif
/**************************************************************************/

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