cancel
Showing results for 
Search instead for 
Did you mean: 

I2C Repeated start generates interrupt, but SR1 == 0

OKatk
Associate II

I'm using i2c to connect MPU6050 in asynchronous mode (means interrupt driven).

I've implemented dfa for that. Everything works fine, but there is strange interrupt right after Re-Start.

SR1 == 0.

Right after second read of SR1 there is right value (SB flag set).

If I don't read SR1 second time and just ignore this interrupt - everything works fine.

Just strange behavior.

I can provide source if it's necessary.

4 REPLIES 4
Danish1
Lead II

You don't say which stm32 you're using. There are differences between the I2C modules in different families.

A lot of people don't use repeated-start (I suppose it's only necessary in multi-master systems) and I think it isn't well supported in the documentation or the libraries.

For stm32f405, I found that I would get an early interrupt on sending the repeated-start.

And I found that reading I2Cn->DR in the interrupt handler immediately prior to setting I2C_CR1_ACK | I2C_CR1_START seemed to solve the problem.

But stm32f767 didn't have this problem.

Hope this helps,

Danish

OKatk
Associate II

Oh, sorry.

It's stm32f100rbt6. I'm using re-start condition because mpu6050 requires it (I read 14 bytes from it) .

What is "early interrupt" ?

Thank you for reply 🙂

uint8_t DFASignal(I2C_TypeDef *i2c) {
#define ERR_MASK (I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_OVR | I2C_SR1_PECERR | I2C_SR1_TIMEOUT | I2C_SR1_SMBALERT | I2C_SR1_AF)
  volatile uint16_t sr1, sr2 = 0;
  sr1 = i2c->SR1;
 
  if (sr1 & I2C_SR1_SB)
    return I2CEV_StartBitSent;
 
  if (sr1 & I2C_SR1_ADDR) {
    sr2 = i2c->SR2; //clear addr register if set
    return I2CEV_AddresSent;
  }
 
  if (sr1 & I2C_SR1_BTF)
    return I2CEV_DataByteTransferFinished;
 
  if (sr1 & I2C_SR1_RXNE)
    return I2CEV_ReceiveBufferNotEmpty;
 
  if (sr1 & I2C_SR1_TXE)
    return I2CEV_TransmitBufferEmpty;
 
  if (sr1 & ERR_MASK)
    return I2CER_ErrClass;
 
  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  //we here because there is no known interrupt flag set.
  //actually sr1 == 0 here.
  //after re-reading of I2C1->SR1 - SB flag is set. strange behavior
  //only after repeat start condition.
  //as I understand - some interrupt is happened, flag isn't set and
  //isn't cleared after end of interrupt.
  //so next time interrupt happened we read sr1 = i2c->SR1
  //and now SB flag is set.
  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  return 0xff;
}

Danish1
Lead II

What I meant by an "early" interrupt was that the interrupt-service-routine was being called with nothing to do because I2Cn->SR1 didn't have any of the expected bits set.

stm32f100 is afaik even older than stm32f4xx. So I'd think it even less likely to support repeated-start.

I'd be surprised if mpu6050 needs the repeated start. I would expect it to work just as well if you do a write to set up the register address, followed by a read.

(I know the data sheet doesn't mention this, but then you get the same with memory devices like EEPROMs, and then the official ST example does a separate write then read).

The downside to separate write followed by read is that in a multi-master I2C system, a second master might get hold of the bus between your write and your read, and it might change the register address before you get a chance to do your read!

Danish

OKatk
Associate II

Thank you. 🙂