Skip to main content
OKatk
Associate
May 9, 2019
Question

I2C Repeated start generates interrupt, but SR1 == 0

  • May 9, 2019
  • 4 replies
  • 1059 views

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.

This topic has been closed for replies.

4 replies

Danish1
Lead III
May 9, 2019

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
OKatkAuthor
Associate
May 9, 2019

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 III
May 9, 2019

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
OKatkAuthor
Associate
May 10, 2019

Thank you. :)