Solo lee un Registro

Estoy usando un STM32F103CBT6 como maestro I2C. Después de enviar la dirección I2C del esclavo, necesito borrar el bit Addr en el registro SR1. La hoja de datos dice:

"ADDR: dirección enviada (modo maestro)/coincidente (modo esclavo) Este bit se borra mediante la lectura del registro SR1 del software seguido de la lectura SR2"

Por lo tanto, tengo dos líneas después del bucle de espera ocupado buscando un bit como este:

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

Esto funciona bien y el compilador no optimizará las lecturas, porque los registros se declaran como volatile, pero me advierte que las dos variables nunca se leen y, por lo tanto, son inútiles. Me gustaría deshacerme de estas advertencias. ¿Está garantizado que funcione, cuando cambio las líneas de esta manera:

I2C1->SR1;
I2C1->SR2;

¿O debería borrar el bit manualmente sin leer SR2 nunca?

Gracias de antemano

Esta es más o menos una pregunta de StackOverfow. Pero sí, si estos son volátiles, debería funcionar. Alternativamente, puede poner (void)a; (void)b;el cuerpo de la función para silenciar las advertencias.
En realidad no. Parece que no funciona como propones: arm.godbolt.org/z/vljOTL . Probablemente porque p;no implica el tipo de acceso a p(lectura o escritura).
Cuando agrego un Asterix enfrente de la p, genera una instrucción ldr.
Hm. Sí, debería probarse de esta manera. Todavía no estoy seguro de si se garantiza que se traducirá a una instrucción de lectura. Una pregunta válida y probablemente buena para SO, si se formula correctamente.

Respuestas (2)

La forma habitual de hacer esto, de forma segura y portátil:

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

Esto suele funcionar incluso en compiladores disfuncionales. Si el compilador sigue advirtiendo, debe enviar un informe de error al proveedor del compilador.

Si puede borrar el bit manualmente, hacerlo hará que su código sea más claro. Si la única forma de borrar el bit es leer los registros, entonces una buena manera de hacerlo es:

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

lo que hace que sea obvio para los futuros lectores que realmente desea leer la variable e ignorar su valor. Siempre que I2C1 sea un puntero a una estructura volátil (que lo es), el compilador hará lo que espera.

No recomendaría esto: el estándar C es bastante vago aquí y muchos compiladores también se comportan mal cuando solo se les da un identificador volátil en una sola línea.