2
\$\begingroup\$

I am using a STM32F103CBT6 as I2C Master. After sending the I2C Adress of the Slave I need to clear the Addr bit in the SR1 register. The Datasheet states:

"ADDR: Address sent (master mode)/matched (slave mode) This bit is cleared by software reading SR1 register followed reading SR2"

Therefore i have two lines after the busy wait loop checking for the bit like this:

uint16_t a = I2C1->SR1;
uint16_t b = I2C1->SR2;

This works fine and the compiler won't optimize the reads, because the Registers are declared as volatile, but it warns me as the two variables are never read and therefore useless. I would like to get rid of these warnings. Is it guaranteed to work, when i change the lines like this:

I2C1->SR1;
I2C1->SR2;

Or should i clear the bit manually without reading SR2 ever ?

Thanks in Advance

\$\endgroup\$
  • 1
    \$\begingroup\$ This is pretty much an StackOverfow question. But yes, if these are volatile it should work. Alternatively you can put (void)a; (void)b; in the body of the function to silence the warnings. \$\endgroup\$ – Eugene Sh. Dec 6 '18 at 19:23
  • \$\begingroup\$ Actually no. Looks like it is not working as you propose: arm.godbolt.org/z/vljOTL . Probably because p; does not imply the access type to p (read or write). \$\endgroup\$ – Eugene Sh. Dec 6 '18 at 19:28
  • \$\begingroup\$ When I add an Asterix infront of the p it generates a ldr instruction. \$\endgroup\$ – user5675428 Dec 6 '18 at 19:33
  • \$\begingroup\$ Hm. Yeah, it should be tested this way. Still not sure about if it is guaranteed to translate to a read instruction. A valid, and probably a good question for SO, if formulated properly. \$\endgroup\$ – Eugene Sh. Dec 6 '18 at 19:35
  • \$\begingroup\$ See here: stackoverflow.com/questions/53658582/… \$\endgroup\$ – Eugene Sh. Dec 6 '18 at 19:44
1
\$\begingroup\$

The usual way to do this, safely and portably:

volatile uint16_t dummy = I2C1->SR1;
(void)dummy;

This usually works even on dysfunctional compilers. If the compiler still warns, you need to file a bug report to the compiler vendor.

\$\endgroup\$
0
\$\begingroup\$

If you can clear the bit manually, doing so would make your code clearer. If the only way to clear the bit is to read the registers, then a good way to do it is:

//Reading SR1 and SR2 automatically clears the ADDR bit
(void)I2C1->SR1;
(void)I2C1->SR2;

which makes it obvious for future readers that you really do want to read the variable and ignore its value. As long as I2C1 is a pointer to a volatile structure (which it is), the compiler will do what you expect.

\$\endgroup\$
  • \$\begingroup\$ I wouldn't recommend this - the C standard is quite vague here and many compilers also behave badly when just given a volatile identifier on a single line. \$\endgroup\$ – Lundin Dec 7 '18 at 9:06

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.