cancel
Showing results for 
Search instead for 
Did you mean: 

I2C1 Interrupt Handler Never Called

AWies.1
Associate III

I am using an STM32H753. I2C1 (for an EEPROM) and I2C3 (for a touchscreen) are set up in the same way. Interrupt priority 10 for both, 400kHz. I can transfer data via I2C3 using interrupts, but when I try the same with I2C1, the interrupt handler is never called. The I2C1 interrupt is listed as pending. I have already lost several days on this issue, with no solution is sight. What can be wrong? I can see on the oscilloscope that the memory address is correctly transferred and the first byte of data received. When using DMA instead of interrupt driven, then all 6 bytes are transferred, but also the transfer complete interrupt is never generated.

Snippet of my code (including a lot of debug code), including values.

uint8_t *I2CMemGetMACAddress(void)

{

   irqenable1 = NVIC_GetEnableIRQ(I2C1_EV_IRQn); // returns 1

   irqenable2 = NVIC_GetEnableIRQ(I2C1_ER_IRQn); // returns 1

   irqpending1 = NVIC_GetPendingIRQ(I2C1_EV_IRQn); // returns 0

   irqpending2 = NVIC_GetPendingIRQ(I2C1_ER_IRQn); // returns 0

   prio = NVIC_GetPriority(I2C1_EV_IRQn); // returns 10

   acti = NVIC_GetActive(I2C1_EV_IRQn); // returns 0

   NVIC_ClearPendingIRQ(I2C1_EV_IRQn);

   NVIC_ClearPendingIRQ(I2C1_ER_IRQn);

   itflags  = READ_REG(hi2c1.Instance->ISR); // returns 0x01

   pm = __get_PRIMASK(); // returns 0

   bp = __get_BASEPRI(); // returns 0x50

   I2CReadComplete = 0;

   HAL_I2C_Mem_Read_IT(&hi2c1, MEMI2CADDR, MAC48_OFFSET, I2C_MEMADD_SIZE_16BIT, MAC48Address, 6);

   while(!I2CReadComplete)

   {

      irqenable1 = NVIC_GetEnableIRQ(I2C1_EV_IRQn); // returns 1

      irqenable2 = NVIC_GetEnableIRQ(I2C1_ER_IRQn); // returns 1

      irqpending1 = NVIC_GetPendingIRQ(I2C1_EV_IRQn); // returns 1

      irqpending2 = NVIC_GetPendingIRQ(I2C1_ER_IRQn); // returns 0

      prio = NVIC_GetPriority(I2C1_EV_IRQn); // returns 10

      acti = NVIC_GetActive(I2C1_EV_IRQn); // returns 0

      cr1 = READ_REG(hi2c1.Instance->CR1); // returns 0xF5

      cr2 = READ_REG(hi2c1.Instance->CR2); // returns 0x20604a0

      itflags  = READ_REG(hi2c1.Instance->ISR); // returns 0x8005

      pm = __get_PRIMASK(); // returns 0x00

      bp = __get_BASEPRI(); // returns 0x50

   }

   return MAC48Address;

}

5 REPLIES 5
KnarfB
Principal III

Where is I2CReadComplete set to !0 ?

AWies.1
Associate III

That’s supposed to happen inside the interrupt routine. But since I do not get any interrupt, it does not happen.

Eventually, the code will be spit apart and the check for the completion of the transfer will happen elsewhere.

KnarfB
Principal III

Doublecheck that there a "raw" interrupt handler was generated in stm32h7xx_it.c dispatching to HAL. Like here (for another chip, names do not match):

void I2C1_EV_IRQHandler(void)
{
  /* USER CODE BEGIN I2C1_EV_IRQn 0 */
 
  /* USER CODE END I2C1_EV_IRQn 0 */
  HAL_I2C_EV_IRQHandler(&hi2c1);
  /* USER CODE BEGIN I2C1_EV_IRQn 1 */
 
  /* USER CODE END I2C1_EV_IRQn 1 */
}

Check that the "raw" interrupt handler name matches the entry in the interrupt vector table g_pfnVectors in the startup .s file.

Set a breakpoint in the "raw" interrupt handler and follow the code. Check also that your interrupt is enabled in NVIC.

hth

KnarfB

Running in context with same/higher priority? RTOS?

Try to strip down to bare minimum, or write a minimal code from scratch.

JW

AWies.1
Associate III

I had a break point on the interrupt handler (the one in stm32h7xx_it.c, and it is never called. The name matches what is in the interrupt table, and if it wan not, the compiler would call the default handler, causing the execution to stop. I am using RTOS, and the code is not being called from within another interrupt handler. So it should work. The weird thing is that the other I2C interface, which uses the same interrupt priority is working just fine. But that one is called from within an interrupt handler for an external interrupt (interrupt line from a touchscreen interface controller).