0
\$\begingroup\$

With the following code to handshake an EEPROM

 STM_enableRCCAPB1PeriphClock( RCC_APB1Periph_I2C1, ENABLE );
 STM_resetRCCAPB1PeriphCmd( RCC_APB1Periph_I2C1, DISABLE );
 I2C_Cmd( m_pEE_I2C_TYPE, ENABLE );
 I2C_ITConfig( m_pEE_I2C_TYPE, I2C_IT_ERR, ENABLE );
 I2C_InitStructure.I2C_Mode        = EE_I2C_MODE;
 I2C_InitStructure.I2C_DutyCycle      = EE_I2C_DUTY_CYCLE;
 I2C_InitStructure.I2C_OwnAddress1     = EE_I2C_OWN_ADDRESS;
 I2C_InitStructure.I2C_Ack         = EE_I2C_ACK;
 I2C_InitStructure.I2C_AcknowledgedAddress = EE_I2C_ACK_ADDR;
 I2C_InitStructure.I2C_ClockSpeed     = EE_I2C_CLOCK_SPEED;
 GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6 BITOR GPIO_Pin_7;
 GPIO_InitStructure.GPIO_Speed  = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_OD;


  /* Generate the START condition */
  I2C1->CR1 |= I2C_CR1_START;

  /* wait until START condition is set */
  while ( NOT ( I2C1->SR1  BITAND  I2C_SR1_SB ) )
  {
  }

  /* send the address of the EEPROM with r/w-bit reset */
  address = EE_EXT_ADDRESS;
  address |= 1u; // read / receiver
  I2C1->DR = address;

  /* wait for either ADDR (ACK) oder AF (NACK) to be set */
  u16StatusRegister = 0x00u;
  while ( NOT ( ( u16StatusRegister  BITAND  I2C_SR1_ADDR )  BITOR  ( 
u16StatusRegister  BITAND  I2C_SR1_AF ) ) )
  {
    u16StatusRegister = I2C1->SR1;
  }

I see the rising of either AF or ADDR in the debugger's register view after executing
I2C1->DR = address, but as soon as I execute u16StatusRegister = 0x00u, all bits in SR1 are reset.

Could anybody guess why that's happening?

I'm using IAR workbench 7.50 and IAR I-jets debugger on a STM32f103, and there are no interrupt routines coded.


I re-coded it a bit:

 /* Generate the START condition */

 I2C1->CR1 |= I2C_CR1_START;



 /* wait until START condition is set */

 while ( NOT ( I2C1->SR1 & I2C_SR1_SB ) ) { }



 /* send the address of the EEPROM with r/w-bit reset */

 address = EE_EXT_ADDRESS | 1u; // read / receiver     

 I2C1->DR = address;          



 /* wait for either ADDR (ACK) oder AF (NACK) to be set */

 u8Timeout = MaxWaitForACK;

 while ( ! ( ( I2C1->SR1 & ( I2C_SR1_AF | I2C_SR1_ADDR | I2C_SR1_BTF | I2C_SR1_TXE | I2C_SR1_RXNE ) ) || ( u8Timeout == 0u ) ) ) {

     u8Timeout--;

 }



 if ( I2C1->SR1 & ( I2C_SR1_ADDR | I2C_SR1_BTF | I2C_SR1_TXE | I2C_SR1_RXNE ) ) {

     /* BTF set <-- EEPROM send ACK */ /* ADDR set <-- EEPROM send ACK */

     bRetVal = TRUE;

 }

 else {

     /* BTF not set <-- Timeout <-- EEPROM send NACK */ /* AF set <-- NACK read */

     bRetVal = FALSE;

 }

This works always (single step, debugging context, and live) in the case the EEPROM is missing, but in the case the EEPROM exists, it only works when stepping or debugging, not live.

And even more curious: when breaking after the evaluation, see AF set in the fail case, which I don't do when stepping through.

Any thoughts?

\$\endgroup\$
1
  • \$\begingroup\$ Please ask a specific question. \$\endgroup\$ – Voltage Spike May 18 at 21:32
1
\$\begingroup\$

Most bits in status register SR1 will get cleared when they have been set to 1 and the MCU reads them as being set to 1, so you don't have to do anything at all to clear them. This behaviour is explained in the manual.

\$\endgroup\$
3
  • \$\begingroup\$ Thanks. But I used the same config in another pice of code in the same software an there I could read this bit before they were reset. Additionally, this code is from a "how to mplement I²C"-tutorial and ist expected that you have to wait for this bits to be sets. How can I implement reading them in that case? \$\endgroup\$ – Knut S. May 7 at 10:44
  • \$\begingroup\$ No, sorry, that's not it. even without a debugger the behavior is still the same. On a further note, when ADDR gets reset in an read access, BTF and RxNE get set and stay set even after many reads of SR1. \$\endgroup\$ – Knut S. May 7 at 14:47
  • \$\begingroup\$ I said most. Not all. \$\endgroup\$ – Justme May 7 at 14:53
0
\$\begingroup\$

My guess (as I struggled with it for a while myself):

Note: Reading I2C_SR2 after reading I2C_SR1 clears the ADDR flag, even if the ADDR flag was set after reading I2C_SR1. Consequently, I2C_SR2 must be read only when ADDR is found set in I2C_SR1 or when the STOPF bit is cleared.

This happens when you use the debugger and try to see which bits are set. The debugger reads those registers and with this action it resets the ADDR flag. The AF flag should not be reset by this however. But that indicates an error.

So if you are debugging your code in the I²C section, do not use the debugger to view the I²C registers at the same time (or only when you are sure that no flag will be reset which your code cares about.

\$\endgroup\$
6
  • \$\begingroup\$ <facepalm> Of course, that's the way this could happen It doesn't apply to the other code, though, but here it might be the case. Thanks a lot. \$\endgroup\$ – Knut S. May 7 at 11:17
  • \$\begingroup\$ No, sorry, that's not it. even without a debugger the behavior is still the same. On a further note, when ADDR gets reset in a read access, BTF and RxNE get set and stay set even after many reads of SR1; and if I'm using wrtite access, its only TxE (and TRA on SR2) which stay set. \$\endgroup\$ – Knut S. May 10 at 8:47
  • \$\begingroup\$ @KnutS. I'm not quite sure I understand correctly - when ADDR gets set, you are supposed to advance to the next step of your transmission, which is either reading something (that's why RXnE is set) or write something (TxE set) from or into the DR register. Reading the SR1 will not clear those bits. \$\endgroup\$ – Arsenal May 10 at 9:28
  • \$\begingroup\$ Yes, that's how I understand it and what I#m trying to do. But those bits are reset before I can read them; I only see them set when stepping through the code. I see ADDR (or AF) set just as after I've written DR, but with the very next action I take I see it (in the IDEs register view) being reset again. But I expect them to say set until I reinit den I²C Master or read SR1 & SR2. \$\endgroup\$ – Knut S. May 10 at 13:20
  • \$\begingroup\$ @KnutS. okay, as you have checked that it also happens without the debugger (and the register view), I'm a bit lost right now why the bits might get reset without anyone reading the status registers. Just a dumb suggestion: instead of u16StatusRegister = 0x00u; read the SR1 directly. \$\endgroup\$ – Arsenal May 10 at 15:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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