@@ -219,17 +219,21 @@ macro_rules! wait_for_flag {
219
219
( $i2c: expr, $flag: ident) => { {
220
220
let sr1 = $i2c. sr1. read( ) ;
221
221
222
+ // Writing 1s in order to only clear the flag we spotted even
223
+ // if the register gets modified externally
224
+ // NOTE(unsafe): Writing 1 to registers which are cleared by 0 has no effect.
225
+ // Similarly, writing to read-only registers has no effect
222
226
if sr1. berr( ) . bit_is_set( ) {
223
- $i2c. sr1. modify ( |_r , w| w . berr( ) . clear_bit( ) ) ;
227
+ $i2c. sr1. write ( | w| unsafe { w . bits ( 0xffff ) } . berr( ) . clear_bit( ) ) ;
224
228
Err ( Other ( Error :: Bus ) )
225
229
} else if sr1. arlo( ) . bit_is_set( ) {
226
- $i2c. sr1. modify ( |_r , w| w . arlo( ) . clear_bit( ) ) ;
230
+ $i2c. sr1. write ( | w| unsafe { w . bits ( 0xffff ) } . arlo( ) . clear_bit( ) ) ;
227
231
Err ( Other ( Error :: Arbitration ) )
228
232
} else if sr1. af( ) . bit_is_set( ) {
229
- $i2c. sr1. modify ( |_r , w| w . af( ) . clear_bit( ) ) ;
233
+ $i2c. sr1. write ( | w| unsafe { w . bits ( 0xffff ) } . af( ) . clear_bit( ) ) ;
230
234
Err ( Other ( Error :: Acknowledge ) )
231
235
} else if sr1. ovr( ) . bit_is_set( ) {
232
- $i2c. sr1. modify ( |_r , w| w . ovr( ) . clear_bit( ) ) ;
236
+ $i2c. sr1. write ( | w| unsafe { w . bits ( 0xffff ) } . ovr( ) . clear_bit( ) ) ;
233
237
Err ( Other ( Error :: Overrun ) )
234
238
} else if sr1. $flag( ) . bit_is_set( ) {
235
239
Ok ( ( ) )
@@ -347,6 +351,9 @@ where
347
351
348
352
/// Generate START condition
349
353
fn send_start ( & mut self ) {
354
+ // Clear all pending error bits
355
+ // NOTE(unsafe): Writing 0 clears the r/w bits and has no effect on the r bits
356
+ self . i2c . sr1 . write ( |w| unsafe { w. bits ( 0 ) } ) ;
350
357
self . i2c . cr1 . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
351
358
}
352
359
0 commit comments