cancel
Showing results for 
Search instead for 
Did you mean: 

the mcu stuck with external interrupt

mfcirill
Associate II
Posted on August 30, 2012 at 13:02

Hello, sorry for my bad English. I'm developing an application for a STM32F103ZE that reads the value from three sensor via I2C bus, use the SysTick timer, use USART1 to communicate with the pc, generates four pwm signal with TIM3, use TIM2 to measure the width of four pulse that generates on rising and falling edge an interrupt. IfI disable the external interrupt the fw works well but if I enable it the mcu stopthe softwareexecution after some seconds.

This is the Interrupt configuration:

void EXTI_Conf(void) 
{ 
EXTI_InitTypeDef EXTI_InitStructure; 
GPIO_InitTypeDef GPIO_InitStructure; 
NVIC_InitTypeDef NVIC_InitStructure; 
// Enable GPIOD clock 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); 
// Configure PD8-12 pins as input floating 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 
GPIO_Init(GPIOD, &GPIO_InitStructure); 
// Enable AFIO clock 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 
// Connect EXTI Lines to PD8-12 pins 
GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource8); 
GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource9); 
GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource10); 
GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource11); 
GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource12); 
// Configure EXTI lines 
// PD8-11 Get Counter; 
EXTI_InitStructure.EXTI_Line = EXTI_Line8; 
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 
EXTI_InitStructure.EXTI_LineCmd = ENABLE; 
EXTI_Init(&EXTI_InitStructure); 
EXTI_InitStructure.EXTI_Line = EXTI_Line9; 
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 
EXTI_InitStructure.EXTI_LineCmd = ENABLE; 
EXTI_Init(&EXTI_InitStructure); 
EXTI_InitStructure.EXTI_Line = EXTI_Line10; 
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 
EXTI_InitStructure.EXTI_LineCmd = ENABLE; 
EXTI_Init(&EXTI_InitStructure); 
EXTI_InitStructure.EXTI_Line = EXTI_Line11; 
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 
EXTI_InitStructure.EXTI_LineCmd = ENABLE; 
EXTI_Init(&EXTI_InitStructure); 
// PD12 Get Counter, calculate, reset timer2 
EXTI_InitStructure.EXTI_Line = EXTI_Line12; 
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; 
EXTI_InitStructure.EXTI_LineCmd = ENABLE; 
EXTI_Init(&EXTI_InitStructure); 
// Enable and set EXTI9_5 Interrupt to the lowest priority 
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; 
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03; 
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
NVIC_Init(&NVIC_InitStructure); 
// Enable and set EXTI15_10 Interrupt to the lowest+1 priority 
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; 
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03; 
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
NVIC_Init(&NVIC_InitStructure); 
}

And this is the interrupt ISR:

void EXTI9_5_IRQHandler(void) 
{ 
if(EXTI_GetITStatus(EXTI_Line8) != RESET) 
{ 
tGetCnt[0] = TIM2->CNT; 
EXTI_ClearITPendingBit(EXTI_Line8); 
} 
else if(EXTI_GetITStatus(EXTI_Line9) != RESET) 
{ 
tGetCnt[1] = TIM2->CNT; 
EXTI_ClearITPendingBit(EXTI_Line9); 
} 
else while(1); 
} 
void EXTI15_10_IRQHandler(void) 
{ 
if(EXTI_GetITStatus(EXTI_Line10) != RESET) 
{ 
tGetCnt[2] = TIM2->CNT; 
EXTI_ClearITPendingBit(EXTI_Line10); 
} 
else if(EXTI_GetITStatus(EXTI_Line11) != RESET) 
{ 
tGetCnt[3] = TIM2->CNT; 
EXTI_ClearITPendingBit(EXTI_Line11); 
} 
else if(EXTI_GetITStatus(EXTI_Line12) != RESET) 
{ 
tGetCnt[4] = TIM2->CNT; 
if (tGetCnt[4] != 0) 
{ 
inputCommand[0] = tGetCnt[0]; 
inputCommand[1] = tGetCnt[1] - inputCommand[0]; 
inputCommand[2] = tGetCnt[2] - inputCommand[0] - inputCommand[1]; 
inputCommand[3] = tGetCnt[3] - inputCommand[0] - inputCommand[1] - inputCommand[2]; 
} 
else 
{ 
printf(''Errore...\r\n''); 
} 
TIM_SetCounter(TIM2, 0); 
EXTI_ClearITPendingBit(EXTI_Line12); 
} 
else while(1); 
}

Thank you for any suggestions. #exti #iterrupt #stm32 #timer #nvic
6 REPLIES 6
frankmeyer9
Associate II
Posted on August 30, 2012 at 16:22

If I disable the external interrupt the fw works well but if I enable it the mcu stop the software execution after some seconds.

 

In this case, I would enable the ext. interrupts and start the code in the debugger. When it got stuck, halt the CPU, and set a preakpoint in the interrupt handler(s), and continue.

Especially watch for the interrupt flags when you exit the handler routine(s).

If you did not reset all flag, you are back in immediately.

That would be a rather common mistake...

mfcirill
Associate II
Posted on August 30, 2012 at 16:41

ok in debug mode I found the problem. The mcu stop the execution on this instruction:

while(!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

that I use to communicate with the sensor. The problem doesn't exist if I disable the external interrupt. I tried to change the interrupt priority but

the problem gets worse

... Maybe the ext interrupt creates an interference with the functionality of i2c port... What can i do?
mfcirill
Associate II
Posted on August 30, 2012 at 19:45

I tried to deactive the ext interrupt before read the sensor data via I2C bus and to active it after the operation: the mcu doesn't stuck, but the measure of the pulse width with the external interrupt doesn't work well. How can I resolve the problem? Please help me... I should finish the project for the next week.

frankmeyer9
Associate II
Posted on August 30, 2012 at 19:46

I can only say that I try to avoid the i2c peripheral whenever possible...

What can i do?

 

Maybe use a scope to see what happens in reality.

Somehow this smells like a race condition. You might check how your code and interrupts are related and interdependent. Possibly some prioritisation helps.

mfcirill
Associate II
Posted on August 30, 2012 at 21:14

I can use only this type of sensor. The problem is the i2c bus that stucks with all kind of interrupt, also with USART interrupt. I think that the interrupt desinchronizes the mcu with the i2c slave and the mcu stop itself on the common instruction for i2c operations. This isthe routine to read the sensor data:

void MPU6050_I2C_BufferRead(u8 slaveAddr, u8* pBuffer, u8 readAddr, u16 NumByteToRead) 
{
/* While the bus is busy */ 
while(I2C_GetFlagStatus(MPU6050_I2C, I2C_FLAG_BUSY)); 
/* Send START condition */ 
I2C_GenerateSTART(MPU6050_I2C, ENABLE); 
/* Test on EV5 and clear it */ 
while(!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_MODE_SELECT)); 
/* Send MPU6050 address for write */ 
I2C_Send7bitAddress(MPU6050_I2C, slaveAddr, I2C_Direction_Transmitter); 
/* Test on EV6 and clear it */ 
while(!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); 
/* Clear EV6 by setting again the PE bit */ 
I2C_Cmd(MPU6050_I2C, ENABLE); 
/* Send the MPU6050's internal address to write to */ 
I2C_SendData(MPU6050_I2C, readAddr); 
/* Test on EV8 and clear it */ 
while(!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); 
/* Send STRAT condition a second time */ 
I2C_GenerateSTART(MPU6050_I2C, ENABLE); 
/* Test on EV5 and clear it */ 
while(!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_MODE_SELECT));<---------- MCU stucks here 
/* Send MPU6050 address for read */ 
I2C_Send7bitAddress(MPU6050_I2C, slaveAddr, I2C_Direction_Receiver); 
/* Test on EV6 and clear it */ 
while(!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); <---------- MCU stucks here 
/* While there is data to be read */ 
while(NumByteToRead) 
{ 
if(NumByteToRead == 1) 
{ 
/* Disable Acknowledgement */ 
I2C_AcknowledgeConfig(MPU6050_I2C, DISABLE); 
/* Send STOP Condition */ 
I2C_GenerateSTOP(MPU6050_I2C, ENABLE); <---------- MCU stucks here 
} 
/* Test on EV7 and clear it */ 
if(I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED)) <---------- MCU stucks here 
{ 
/* Read a byte from the MPU6050 */ 
*pBuffer = I2C_ReceiveData(MPU6050_I2C); 
/* Point to the next location where the byte read will be saved */ 
pBuffer++; 
/* Decrement the read bytes counter */ 
NumByteToRead--; 
} 
}

frankmeyer9
Associate II
Posted on September 02, 2012 at 19:38

If you do a search for i2c related problems on this site, you will find a lot of them. Take it as a sign that this peripheral is, say, somehow problematic. I avoid it whenever possible.

Apart from that, you will probably need the check the bus with a scope or a logic analizer. You might as well have violated some point in the spec. of the i2c slave.

I remember having had some issues to get another Invensense part working, an IMU3000. These composite units are not particular simple.

And, as I remember, there was a point in the errata sheet, regarding i2c and repeated start conditions, which seems to match your case. At least worth to check for.