[BUG] CMSIS I2C Driver for STM32F4xx (v2.9)

Hello,

Memory overflow occurs when receiving 2 bytes using the driver.  Works fine for 1 byte.

Here is a code to simulate the problem:

ARM_DRIVER_I2C *I2Cdrv = &Driver_I2C1;
uint8_t buf[2];
uint32_t n;

I2Cdrv->MasterReceive(0x55, buf, 2, false);
osDelay(50);
n = I2Cdrv->GetDataCount(); // n = 544

I2C_STM32F4xx.c has an I2C Event Interrupt handler (I2C_EV_IRQHandler). Inside of this function there is a code to process such case (when 2 bytes remaining to receive):

          if (sr1 & I2C_SR1_RXNE) {
            /* End master receiver operation */
            if ((rx->num == 2U) || (rx->cnt == (rx->num - 2U))) {
              /* Two bytes remaining */
              if (tr->ctrl & XFER_CTRL_XPENDING) {
                i2c->reg->CR2 &= ~I2C_CR2_ITEVTEN;
              }
              else {
                i2c->reg->CR1 |= I2C_CR1_STOP;
              }

              /* Read data N-1 and N */
              rx->data[rx->cnt++] = (uint8_t)i2c->reg->DR;
              rx->data[rx->cnt++] = (uint8_t)i2c->reg->DR;

              tr->status.busy = 0U;
              tr->status.mode = 0U;

              i2c->reg->CR1 &= ~I2C_CR1_POS;

              if (tr->cb_event) {
                tr->cb_event (ARM_I2C_EVENT_TRANSFER_DONE);
              }
            }
            else {
              /* Three bytes remaining */
              i2c->reg->CR1 &= ~I2C_CR1_ACK;
              /* Read data N-2 */
              rx->data[rx->cnt++] = (uint8_t)i2c->reg->DR;
            }
          }

But it never executed. Instead this code (in I2C_EV_IRQHandler) executes again and again, causing memory overflow:

        if (sr1 & I2C_SR1_RXNE) {
          /* Master receiver */
          rx->data[rx->cnt++] = (uint8_t)i2c->reg->DR;

          if (rx->num == 1U) {
            /* Single byte transfer completed */
            i2c->reg->CR2 &= ~I2C_CR2_ITBUFEN;

            if (tr->ctrl & XFER_CTRL_XPENDING) {
              i2c->reg->CR2 &= ~I2C_CR2_ITEVTEN;
            }
            /* (STOP was already sent during ADDR phase) */

            tr->status.busy = 0U;
            tr->status.mode = 0U;

            if (tr->cb_event) {
              tr->cb_event (ARM_I2C_EVENT_TRANSFER_DONE);
            }
          }
          else {
            if (rx->cnt == (rx->num - 3U)) {
              /* N > 2 byte reception, begin N-2 data reception */
              i2c->reg->CR2 &= ~I2C_CR2_ITBUFEN;
              /* Wait for BTF */
            }
          }
        }

This driver comes with Keil STM32F4xx_DFP v2.14.0.

Best regards,

Eugene

More questions in this forum