static int stm32_i2c_isr_process()

in arch/arm/src/stm32/stm32f40xxx_i2c.c [1152:1989]


static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
{
  uint32_t status;
#ifndef CONFIG_I2C_POLLED
  uint32_t regval;
#endif
#ifdef CONFIG_STM32_I2C_DMA
  uint16_t cr2;
#endif

  i2cinfo("I2C ISR called\n");

  /* Get state of the I2C controller (register SR1 only)
   *
   * Get control register SR1 only as reading both SR1 and SR2 clears the
   * ADDR flag(possibly others) causing the hardware to advance to the next
   * state without the proper action being taken.
   */

  status = stm32_i2c_getreg(priv, STM32_I2C_SR1_OFFSET);

  /* Update private version of the state */

  priv->status = status;

  /* Check if this is a new transmission so to set up the
   * trace table accordingly.
   */

  stm32_i2c_tracenew(priv, status);
  stm32_i2c_traceevent(priv, I2CEVENT_ISR_CALL, 0);

  /* Messages handling (1/2)
   *
   * Message handling should only operate when a message has been completely
   * sent and after the ISR had the chance to run to set bits after the last
   * written/read byte, i.e. priv->dcnt == -1. This is also the case in when
   * the ISR is called for the first time. This can seen in
   * stm32_i2c_process() before entering the stm32_i2c_sem_waitdone() waiting
   * process.
   *
   * Message handling should only operate when:
   *     - A message has been completely sent and there are still messages
   *       to send(i.e. msgc > 0).
   *     - After the ISR had the chance to run to set start bit or
   *       termination flags after the last written/read byte(after last byte
   *       dcnt=0, msg handling dcnt = -1).
   *
   * When the ISR is called for the first time the same conditions hold.
   * This can seen in stm32_i2c_process() before entering the
   * stm32_i2c_sem_waitdone() waiting process.
   */

#ifdef CONFIG_STM32_I2C_DMA
  /* If ISR gets called (ex. polling mode) while DMA is still in
   * progress, we should just return and let the DMA finish.
   */

  cr2 = stm32_i2c_getreg(priv, STM32_I2C_CR2_OFFSET);
  if ((cr2 & I2C_CR2_DMAEN) != 0)
    {
#ifdef CONFIG_DEBUG_I2C_INFO
      size_t left = stm32_dmaresidual(priv->rxdma);

      i2cinfo("DMA in progress: %ld [bytes] remainining. Returning.\n",
              left);
#endif
      return OK;
    }
#endif

  if (priv->dcnt == -1 && priv->msgc > 0)
    {
      /* Any new message should begin with "Start" condition
       * However there were 2 situations where that was not true
       * Situation 1:
       *    Next message continue transmission sequence of previous message
       *
       * Situation 2: If an error is injected that looks like a STOP the
       * interrupt will be reentered with some status that will be incorrect.
       * This will ensure that the error handler will clear the interrupt
       * enables and return the error to the waiting task.
       */

      if (((priv->msgv[0].flags & I2C_M_NOSTART) != 0 &&
           (status & I2C_SR1_TXE) == 0) ||
          ((priv->msgv[0].flags & I2C_M_NOSTART) == 0 &&
           (status & I2C_SR1_SB) == 0))
        {
#if defined(CONFIG_STM32_I2C_DMA) || defined(CONFIG_I2C_POLLED)
          return OK;
#else
          priv->status |= I2C_SR1_TIMEOUT;
          goto state_error;
#endif
        }

      i2cinfo("Switch to new message\n");

      /* Get current message to process data and copy to private structure */

      priv->ptr           = priv->msgv->buffer;   /* Copy buffer to private struct */
      priv->dcnt          = priv->msgv->length;   /* Set counter of current msg length */
      priv->flags         = priv->msgv->flags;    /* Copy flags to private struct */

      i2cinfo("Current flags %i\n", priv->flags);

      /* Decrease counter to indicate the number of messages left to
       * process
       */

      priv->msgc--;

      /* Decrease message pointer.
       * If last message set next message vector to null
       */

      if (priv->msgc == 0)
        {
          /* No more messages, don't need to increment msgv. This pointer
           * will be set to zero when reaching the termination of the ISR
           * calls, i.e.  Messages handling(2/2).
           */
        }
      else
        {
          /* If not last message increment to next message to process */

          priv->msgv++;
        }

      /* Trace event */

      stm32_i2c_traceevent(priv, I2CEVENT_MSG_HANDLING, priv->msgc);
    }

  /* Note the event where we are on the last message and after the last
   * byte is handled at the bottom of this function, as it terminates
   * the repeated calls to the ISR.
   */

  /* I2C protocol logic
   *
   * I2C protocol logic follows. It's organized in an if else chain such that
   * only one mode of operation is executed every time the ISR is called.
   */

  /* Address Handling
   *
   * Check if a start bit was set and transmit address with proper format.
   *
   * Note:
   * On first call the start bit has been set by stm32_i2c_waitdone()
   * Otherwise it will be set from this ISR.
   *
   * Remember that after a start bit an address has always to be sent.
   */

  if ((status & I2C_SR1_SB) != 0)
    {
      /* Start bit is set */

      i2cinfo("Entering address handling, status = %" PRIi32 "\n", status);

      /* Check for empty message (for robustness) */

      if (priv->dcnt > 0)
        {
          /* Set POS bit to zero (can be up from a previous 2 byte receive) */

          stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_POS, 0);

          /* ACK is the expected answer for N>=3 reads and writes */

          stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, 0, I2C_CR1_ACK);

          /* Send address byte with correct 8th bit set
           * (for writing or reading)
           * Transmission happens after having written to the data register
           * STM32_I2C_DR
           */

          stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET,
                           (priv->flags & I2C_M_TEN) ?
                           0 : ((priv->msgv->addr << 1) |
                           (priv->flags & I2C_M_READ)));

          i2cinfo("Address sent. Addr=%#02x Write/Read bit=%i\n",
                  priv->msgv->addr, (priv->flags & I2C_M_READ));

          /* Flag that address has just been sent */

          priv->check_addr_ack = true;

          stm32_i2c_traceevent(priv, I2CEVENT_SENDADDR, priv->msgv->addr);
        }
      else
        {
          /* TODO: untested!! */

          i2cwarn(" An empty message has been detected, "
                  "ignoring and passing to next message.\n");

          /* Trace event */

          stm32_i2c_traceevent(priv, I2CEVENT_EMPTY_MSG, 0);

          /* Set condition to activate msg handling */

          priv->dcnt = -1;

#ifndef CONFIG_I2C_POLLED
          /* Restart ISR by setting an interrupt buffer bit */

          stm32_i2c_modifyreg(priv,
                              STM32_I2C_CR2_OFFSET, 0, I2C_CR2_ITBUFEN);
#endif
        }
    }

  /* Address cleared event
   *
   * Check if the address cleared, i.e. the driver found a valid address.
   * If a NACK was received the address is invalid, if an ACK was
   * received the address is valid and transmission can continue.
   */

  /* Check for NACK after an address */

#ifndef CONFIG_I2C_POLLED
  /* When polling the i2c ISR it's not possible to determine when
   * an address has been ACKed(i.e. the address is valid).
   *
   * The mechanism to deal a NACKed address is to wait for the I2C
   * call to timeout (value defined in defconfig by one of the
   * following: CONFIG_STM32_I2C_DYNTIMEO, CONFIG_STM32_I2CTIMEOSEC,
   * CONFIG_STM32_I2CTIMEOMS, CONFIG_STM32_I2CTIMEOTICKS).
   *
   * To be safe in the case of a timeout/NACKed address a stop bit
   * is set on the bus to clear it. In POLLED operation it's done
   * stm32_i2c_process() after the call to stm32_i2c_sem_waitdone().
   *
   * In ISR driven operation the stop bit in case of a NACKed address
   * is set in the ISR itself.
   *
   * Note: this commentary is found in both places.
   */

  else if ((status & I2C_SR1_ADDR) == 0 && priv->check_addr_ack)
    {
      i2cinfo("Invalid Address. Setting stop bit and clearing message\n");
      i2cinfo("status %" PRIi32 "\n", status);

      /* Set condition to terminate msg chain transmission as address is
       * invalid.
       */

      priv->dcnt = -1;
      priv->msgc = 0;

      i2cinfo("dcnt %i , msgc %i\n", priv->dcnt, priv->msgc);

      /* Reset flag to check for valid address */

      priv->check_addr_ack = false;

      /* Send stop bit to clear bus */

      stm32_i2c_sendstop(priv);

      /* Trace event */

      stm32_i2c_traceevent(priv, I2CEVENT_ADDRESS_NACKED, priv->msgv->addr);
    }
#endif

  /* ACK in read mode, ACK in write mode is handled separately */

  else if ((priv->flags & I2C_M_READ) != 0 && (status & I2C_SR1_ADDR) != 0 &&
           priv->check_addr_ack)
    {
      /* Reset check addr flag as we are handling this event */

      priv->check_addr_ack = false;

      /* Note:
       *
       * When reading a single byte the stop condition has  to be set
       * immediately after clearing the state flags, which happens
       * when reading SR2(as SR1 has already been read).
       *
       * Similarly when reading 2 bytes the NACK bit has to be set as just
       * after the clearing of the address.
       */

      if (priv->dcnt == 1)
        {
          /* this should only happen when receiving a message of length 1 */

          i2cinfo("short read N=1: setting NACK\n");

          /* Set POS bit to zero (can be up from a previous 2 byte receive) */

          stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_POS, 0);

          /* Immediately set NACK */

          stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, 0);

#ifndef CONFIG_I2C_POLLED
          /* Enable RxNE and TxE buffers in order to receive one or multiple
           * bytes
           */

          stm32_i2c_modifyreg(priv,
                              STM32_I2C_CR2_OFFSET, 0, I2C_CR2_ITBUFEN);
#endif

          /* Clear ADDR flag by reading SR2 and adding it to status */

          status |= (stm32_i2c_getreg(priv, STM32_I2C_SR2_OFFSET) << 16);

          /* Send Stop/Restart */

          if (priv->msgc > 0)
            {
              stm32_i2c_sendstart(priv);
            }
          else
            {
              stm32_i2c_sendstop(priv);
            }

          i2cinfo("Address ACKed beginning data reception\n");
          i2cinfo("short read N=1: programming stop bit\n");

          /* Trace */

          stm32_i2c_traceevent(priv, I2CEVENT_ADDRESS_ACKED_READ_1, 0);
        }
      else if (priv->dcnt == 2)
        {
          /* This should only happen when receiving a message of length 2 */

          /* Set POS bit to zero (can be up from a previous 2 byte receive) */

          stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, 0, I2C_CR1_POS);

          /* Immediately set NACK */

          stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, 0);

          /* Clear ADDR flag by reading SR2 and adding it to status */

          status |= (stm32_i2c_getreg(priv, STM32_I2C_SR2_OFFSET) << 16);

          i2cinfo("Address ACKed beginning data reception\n");
          i2cinfo("short read N=2: programming NACK\n");

          /* Trace */

          stm32_i2c_traceevent(priv, I2CEVENT_ADDRESS_ACKED_READ_2, 0);
        }
      else
        {
          i2cinfo("Address ACKed beginning data reception\n");

          /* Clear ADDR flag by reading SR2 and adding it to status */

          status |= (stm32_i2c_getreg(priv, STM32_I2C_SR2_OFFSET) << 16);

          /* Trace */

          stm32_i2c_traceevent(priv, I2CEVENT_ADDRESS_ACKED, 0);

#ifdef CONFIG_STM32_I2C_DMA
          /* DMA only when not doing a short read */

          i2cinfo("Starting dma transfer and disabling interrupts\n");

          /* The DMA must be initialized and enabled before the I2C data
           * transfer.
           * The DMAEN bit must be set in the I2C_CR2 register before the
           * ADDR event.
           */

          stm32_dmasetup(priv->rxdma,
                         priv->config->base + STM32_I2C_DR_OFFSET,
                         (uint32_t)priv->ptr, priv->dcnt,
                         DMA_SCR_DIR_P2M |
                         DMA_SCR_MSIZE_8BITS |
                         DMA_SCR_PSIZE_8BITS |
                         DMA_SCR_MINC |
                         I2C_DMA_PRIO);

          /* Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is
           * used.
           */

          stm32_i2c_modifyreg(priv,
                              STM32_I2C_CR2_OFFSET, I2C_CR2_ITBUFEN, 0);

#ifndef CONFIG_I2C_POLLED
          /* Now let DMA do all the work, disable i2c interrupts */

          regval  = stm32_i2c_getreg(priv, STM32_I2C_CR2_OFFSET);
          regval &= ~I2C_CR2_ALLINTS;
          stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, regval);
#endif

          /* The user can generate a Stop condition in the DMA Transfer
           * Complete interrupt routine if enabled. This will be done in
           * the dma rx callback Start DMA.
           */

          stm32_dmastart(priv->rxdma, stm32_i2c_dmarxcallback, priv, false);
          stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, 0, I2C_CR2_DMAEN);
#else
#ifndef CONFIG_I2C_POLLED
          if (priv->dcnt > 3)
            {
              /* Don't enable I2C_CR2_ITBUFEN for messages longer than 3
               * bytes
               */

              stm32_i2c_modifyreg(priv,
                                  STM32_I2C_CR2_OFFSET, 0, I2C_CR2_ITBUFEN);
            }
#endif
#endif
        }
    }

  /* Write mode
   *
   * Handles all write related I2C protocol logic. Also handles the
   * ACK event after clearing the ADDR flag as the write has to
   * begin immediately after.
   */

  else if ((priv->flags & I2C_M_READ) == 0 &&
           (status & I2C_SR1_BTF) != 0 &&
            priv->dcnt == 0)
    {
      /* After last byte, check what to do based on next message flags */

      if (priv->msgc == 0)
        {
          /* If last message send stop bit */

          stm32_i2c_sendstop(priv);
          i2cinfo("Stop sent dcnt = %i msgc = %i\n", priv->dcnt, priv->msgc);

          /* Decrease counter to get to next message */

          priv->dcnt--;
          i2cinfo("dcnt %i\n", priv->dcnt);
          stm32_i2c_traceevent(priv, I2CEVENT_WRITE_STOP, priv->dcnt);
        }

      /* If there is a next message with no flags or the read flag
       * a restart sequence has to be sent.
       * Note msgv already points to the next message.
       */

      else if (priv->msgc > 0 &&
               (priv->msgv->flags == 0 ||
               (priv->msgv[0].flags & I2C_M_READ) != 0))
        {
          /* Send start */

          stm32_i2c_sendstart(priv);

          stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET);

          i2cinfo("Restart detected!\n");
          i2cinfo("Nextflag %i\n", priv->msgv[0].flags);

          /* Decrease counter to get to next message */

          priv->dcnt--;
          i2cinfo("dcnt %i\n", priv->dcnt);
          stm32_i2c_traceevent(priv, I2CEVENT_WRITE_RESTART, priv->dcnt);
        }
      else
        {
          i2cinfo("Write mode: next message has an unrecognized flag.\n");
          stm32_i2c_traceevent(priv,
                               I2CEVENT_WRITE_FLAG_ERROR, priv->msgv->flags);
        }

      status |= (stm32_i2c_getreg(priv, STM32_I2C_SR2_OFFSET) << 16);
    }
  else if ((priv->flags & I2C_M_READ) == 0 &&
           (status & (I2C_SR1_ADDR | I2C_SR1_TXE)) != 0 &&
            priv->dcnt != 0)
    {
      /* The has cleared(ADDR is set, ACK was received after the address)
       * or the transmit buffer is empty flag has been set(TxE) then we can
       * transmit the next byte.
       */

      i2cinfo("Entering write mode dcnt = %i msgc = %i\n",
              priv->dcnt, priv->msgc);

      /* Clear ADDR flag by reading SR2 and adding it to status */

      status |= (stm32_i2c_getreg(priv, STM32_I2C_SR2_OFFSET) << 16);

      /* Address has cleared so don't check on next call */

      priv->check_addr_ack = false;

      /* Check if we have transmitted the whole message or we are after
       * the last byte where the stop condition or else(according to the
       * msg flags) has to be set.
       */

#ifdef CONFIG_STM32_I2C_DMA
      /* if DMA is enabled, only makes sense to make use of it for longer
       * than 1 B transfers.
       */

      if (priv->dcnt > 1)
        {
          i2cinfo("Starting DMA transfer and disabling interrupts\n");

          /* The DMA must be initialized and enabled before the I2C data
           * transfer.  The DMAEN bit must be set in the I2C_CR2 register
           * before the ADDR event.
           */

          stm32_dmasetup(priv->txdma,
                         priv->config->base + STM32_I2C_DR_OFFSET,
                         (uint32_t) priv->ptr, priv->dcnt,
                         DMA_SCR_DIR_M2P |
                         DMA_SCR_MSIZE_8BITS |
                         DMA_SCR_PSIZE_8BITS |
                         DMA_SCR_MINC |
                         I2C_DMA_PRIO);

          /* Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is
           * used.
           */

          stm32_i2c_modifyreg(priv,
                              STM32_I2C_CR2_OFFSET, I2C_CR2_ITBUFEN, 0);

#ifndef CONFIG_I2C_POLLED
          /* Now let DMA do all the work, disable i2c interrupts */

          regval  = stm32_i2c_getreg(priv, STM32_I2C_CR2_OFFSET);
          regval &= ~I2C_CR2_ALLINTS;
          stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, regval);
#endif

          /* In the interrupt routine after the EOT interrupt, disable DMA
           * requests then wait for a BTF event before programming the Stop
           * condition. To do this, we'll just call the ISR again in
           * DMA tx callback, in which point we fall into the msgc==0 case
           * which ultimately sends the stop..TODO: but we don't explicitly
           * wait for BTF bit being set...
           * Start DMA.
           */

          stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, 0, I2C_CR2_DMAEN);
          stm32_dmastart(priv->txdma, stm32_i2c_dmatxcallback, priv, false);
        }
      else
#endif /* CONFIG_STM32_I2C_DMA */
        {
#ifndef CONFIG_I2C_POLLED
          if (priv->dcnt == 1 &&
              (priv->msgc == 0 || (priv->msgv->flags & I2C_M_NOSTART) == 0))
            {
              stm32_i2c_modifyreg(priv,
                                  STM32_I2C_CR2_OFFSET, I2C_CR2_ITBUFEN, 0);
            }
#endif

          /* Transmitting message.
           * Send byte == write data into write register
           */

          stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET, *priv->ptr++);

          /* Decrease current message length */

          stm32_i2c_traceevent(priv, I2CEVENT_WRITE_TO_DR, priv->dcnt);
          priv->dcnt--;

          if ((status & I2C_SR1_ADDR) != 0 && priv->dcnt > 0)
            {
              /* Transmitting message.
               * ADDR -> BTF & TXE - Send one more byte
               */

              stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET, *priv->ptr++);

              /* Decrease current message length */

              stm32_i2c_traceevent(priv, I2CEVENT_WRITE_TO_DR, priv->dcnt);
              priv->dcnt--;
            }

#ifndef CONFIG_I2C_POLLED
          if (((status & I2C_SR1_ADDR) != 0 && priv->dcnt > 0) ||
              (priv->msgc > 0 && (priv->msgv->flags & I2C_M_NOSTART) != 0))
            {
              stm32_i2c_modifyreg(priv,
                                  STM32_I2C_CR2_OFFSET, 0, I2C_CR2_ITBUFEN);
            }
#endif

          if (priv->dcnt == 0 &&
              priv->msgc > 0 && (priv->msgv->flags & I2C_M_NOSTART) != 0)
            {
              /* Set condition to get to next message */

              priv->dcnt = -1;
              stm32_i2c_traceevent(priv,
                                   I2CEVENT_WRITE_NO_RESTART, priv->dcnt);
            }
        }
    }

  /* Read mode
   *
   * Handles all read related I2C protocol logic.
   *
   * * * * * * * WARNING STM32F1xx HARDWARE ERRATA * * * * * * *
   *
   * source: https://github.com/hikob/openlab/blob/master/drivers/stm32/i2c.c
   *
   * RXNE-only events should not be handled since it sometimes
   * fails. Only BTF & RXNE events should be handled (with the
   * consequence of slowing down the transfer).
   *
   * It seems that when a RXNE interrupt is handled 'around'
   * the end of the next byte reception, the DR register read
   * is ignored by the i2c controller: it does not flush the
   * DR with next byte
   *
   * Thus we read twice the same byte and we read effectively
   * read one byte less than expected from the i2c slave point
   * of view.
   *
   * Example:
   * + we want to receive 6 bytes (B1 to B6)
   * + the problem appear when reading B3
   * -> we read B1 B2 B3 B3 B4 B5(B3 twice)
   * -> the i2c transfer was B1 B2 B3 B4 B5(B6 is not sent)
   */

  else if ((priv->flags & (I2C_M_READ)) != 0 &&
           (status & (I2C_SR1_RXNE | I2C_SR1_BTF)) != 0)
    {
      /* When read flag is set and the receive buffer is not empty
       * (RXNE is set) then the driver can read from the data register.
       */

      status |= (stm32_i2c_getreg(priv, STM32_I2C_SR2_OFFSET) << 16);

      i2cinfo("Entering read mode dcnt = %i msgc = %i, "
              "status 0x%04" PRIx32 "\n",
              priv->dcnt, priv->msgc, status);

      /* Byte #N-3W, we don't want to manage RxNE interrupt anymore, bytes
       * N, N-1, N-2 will be read with BTF:
       */

#ifndef CONFIG_I2C_POLLED
      if (priv->dcnt < 5)
        {
          stm32_i2c_modifyreg(priv,
                              STM32_I2C_CR2_OFFSET, I2C_CR2_ITBUFEN, 0);
        }
#else
      if (priv->dcnt == 1 ||
          priv->dcnt > 3 || (status & I2C_SR1_BTF) != 0)
#endif
        {
          /*  BTF: N-2/N-1, set NACK, read N-2 */

          if (priv->dcnt == 3)
            {
              stm32_i2c_modifyreg(priv,
                                  STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, 0);
            }

          /*  BTF: N-1/N, STOP/START, read N-1, N */

          else if (priv->dcnt == 2)
            {
              if (priv->msgc > 0)
                {
                  stm32_i2c_sendstart(priv);
                }
              else
                {
                  stm32_i2c_sendstop(priv);
                }

              /* Read byte #N-1 */

              *priv->ptr++ = stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET);
              priv->dcnt--;
            }

          /* Read last or current byte */

          *priv->ptr++ = stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET);
          priv->dcnt--;

          if (priv->dcnt == 0)
            {
              priv->dcnt = -1;
            }
        }
    }

  /* Empty call handler
   *
   * Case to handle an empty call to the ISR where it only has to
   * Shutdown
   */

  else if (priv->dcnt == -1 && priv->msgc == 0)
    {
      /* Read rest of the state */

      status |= (stm32_i2c_getreg(priv, STM32_I2C_SR2_OFFSET) << 16);
      i2cinfo("Empty call to ISR: Stopping ISR\n");
      stm32_i2c_traceevent(priv, I2CEVENT_ISR_EMPTY_CALL, 0);
    }

  /* Error handler
   *
   * Gets triggered if the driver does not recognize a situation(state)
   * it can deal with.
   * This should not happen in interrupt based operation(i.e. when
   * CONFIG_I2C_POLLED is not set in the defconfig file).
   * During polled operation(i.e. CONFIG_I2C_POLLED=y in defconfig)
   * this case should do nothing but tracing the event that the
   * device wasn't ready yet.
   */

  else
    {
#ifdef CONFIG_I2C_POLLED
      stm32_i2c_traceevent(priv, I2CEVENT_POLL_DEV_NOT_RDY, 0);
#else
      /* Read rest of the state */

      status |= (stm32_i2c_getreg(priv, STM32_I2C_SR2_OFFSET) << 16);

      /* No any error bit is set, but driver is in incorrect state, signal
       * it with "Bus error" bit.
       */

      if ((status & I2C_SR1_ERRORMASK) != 0)
        {
          priv->status |= I2C_SR1_BERR;
        }

      i2cinfo(" No correct state detected(start bit, read or write)\n");
      i2cinfo(" state %" PRIi32 "\n", status);

      /* Set condition to terminate ISR and wake waiting thread */

      priv->dcnt = -1;
      priv->msgc = 0;
      stm32_i2c_traceevent(priv, I2CEVENT_STATE_ERROR, 0);
#endif
    }

  /* Messages handling(2/2)
   *
   * Transmission of the whole message chain has been completed. We have to
   * terminate the ISR and wake up stm32_i2c_process() that is waiting for
   * the ISR cycle to handle the sending/receiving of the messages.
   */

  /* First check for errors */

  if ((status & I2C_SR1_ERRORMASK) != 0)
    {
      stm32_i2c_traceevent(priv, I2CEVENT_ERROR, status & I2C_SR1_ERRORMASK);

      /* Clear interrupt flags */

#if !defined(CONFIG_STM32_I2C_DMA) && !defined(CONFIG_I2C_POLLED)
state_error:
#endif
      stm32_i2c_putreg(priv, STM32_I2C_SR1_OFFSET, 0);

      priv->dcnt = -1;
      priv->msgc = 0;
    }

  if (priv->dcnt == -1 && priv->msgc == 0)
    {
      i2cinfo("Shutting down I2C ISR\n");

      stm32_i2c_traceevent(priv, I2CEVENT_ISR_SHUTDOWN, 0);

      /* Clear internal pointer to the message content.
       * Good practice + done by last implementation when messages are
       * finished (compatibility concerns)
       */

      priv->msgv = NULL;

#ifdef CONFIG_I2C_POLLED
      priv->intstate = INTSTATE_DONE;
#else
      /* Clear all interrupts */

      regval  = stm32_i2c_getreg(priv, STM32_I2C_CR2_OFFSET);
      regval &= ~I2C_CR2_ALLINTS;
      stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, regval);

      /* Is there a thread waiting for this event(there should be) */

      if (priv->intstate == INTSTATE_WAITING)
        {
          /* Yes.. inform the thread that the transfer is complete
           * and wake it up.
           */

          nxsem_post(&priv->sem_isr);
          priv->intstate = INTSTATE_DONE;
        }
#endif
    }

  return OK;
}