I am trying to get I2C (with interrupts) on an F411RE to work. I dived into the HAL library code and found this tid bit...

static HAL_StatusTypeDef I2C_SlaveTransmit_TXE(I2C_HandleTypeDef *hi2c)
  /* Declaration of temporary variables to prevent undefined behavior of  volatile usage */
  uint32_t CurrentState = hi2c->State;

  if(hi2c->XferCount != 0U)
    /* Write data to DR */
    hi2c->Instance->DR = (*hi2c->pBuffPtr++);

    if((hi2c->XferCount == 0U) && (CurrentState ==          HAL_I2C_STATE_BUSY_TX_LISTEN))
      /* Last Byte is received, disable Interrupt */
      __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF);

      /* Set state at HAL_I2C_STATE_LISTEN */
      hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX;
      hi2c->State = HAL_I2C_STATE_LISTEN;

      /* Call the Tx complete callback to inform upper layer of the end of receive process */
  return HAL_OK;

I am little confused. I was expecting to see while loop go through the transfer count. Instead, it is if statements. So, my question is, am I understanding this correctly? The way that HAL treats a slave transmits on interrupt is that it relies on an interrupt to be generated for each byte of the transfer instead of one interrupt for transferring all the bytes at once?

  • 1
    \$\begingroup\$ Perhaps HAL is non-blocking code. "While" statements hold up the processor from anything other than another higher-priority interrupt. \$\endgroup\$
    – glen_geek
    Mar 21, 2017 at 13:41
  • 1
    \$\begingroup\$ Of course the peripheral will generate an interrupt per byte, i.e. whenever the HW is ready to accept another byte of data. More advanced techniques use DMA where indeed the CPU only needs to handle one interrupt per DMA transfer of arbitrary size. \$\endgroup\$
    – JimmyB
    Mar 21, 2017 at 16:30

1 Answer 1


Yes I think you understood that correctly.

And if you think about it, that's the whole point of interrupts. You don't need interrupts when you simply loop over the array and wait for each byte.

The interrupts allow your program to do stuff while the I²C transaction is ongoing.

The other thing with only one interrupt would be using DMA to feed the data to the I²C peripheral.

From the implementation work I've done on an own HAL for the F401, I'd recommend you to use the interrupt capability only for the bulk transmission or reception. I encountered strange interrupts with no source (no bits set in the registers) while trying to implement a purely interrupt driven approach for the I²C.

  • \$\begingroup\$ interesting to hear about the strange interrupts. Was there anything in the errata? ST is usually pretty good with noting HW bugs. \$\endgroup\$
    – Jon
    Mar 21, 2017 at 14:21
  • \$\begingroup\$ @Jon nope, I haven't seen anything about them while I was implementing that. And I'm pretty sure I wasn't fooled by the debugger. After doing only the RX and TX interrupts I haven't seen strange interrupts again. But maybe I did something wrong as the I²C peripheral is a small hell with double buffer dual use registers and stuff. The newer incarnation (F051, L4xx) is much nicer. \$\endgroup\$
    – Arsenal
    Mar 21, 2017 at 14:27
  • \$\begingroup\$ We you using a push button and interrupts, by and chance? I got the same issue, but it was fixed when I just chose a different method of starting I2C transmissions for testing. \$\endgroup\$
    – Verosity
    Mar 27, 2017 at 15:02
  • \$\begingroup\$ @Verosity we had an external interrupt, but it was not triggering our I²C transmission. I'm not 100% sure but I think I implemented the I²C without other interrupts activated. \$\endgroup\$
    – Arsenal
    Mar 28, 2017 at 21:06
  • \$\begingroup\$ @Arsenal I have seen some funky stuff with interrupts on the ST micros. With I2C, when there are other interrupts, I see some weird things like interrupting again, when I am done, for no known reason. I am going to assume it is because I am just not doing something properly. \$\endgroup\$
    – Verosity
    Mar 29, 2017 at 13:16

Your Answer

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

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