11use core:: ops:: Deref ;
22
33use crate :: gpio;
4- use crate :: i2c :: { Error , NoAcknowledgeSource } ;
4+
55use crate :: pac:: fmpi2c1 as i2c1;
66use crate :: pac:: { self , RCC } ;
77use crate :: rcc:: { BusClock , Enable , Reset } ;
88use fugit:: { HertzU32 as Hertz , RateExtU32 } ;
99
10+ #[ path = "i2c/common.rs" ]
11+ mod common;
12+ pub use common:: { Address , Error , NoAcknowledgeSource } ;
13+ use common:: { Hal02Operation , Hal1Operation } ;
14+
1015// Old names
1116pub use I2c as FmpI2c ;
1217pub use Mode as FmpMode ;
1318
19+ #[ path = "i2c/hal_02.rs" ]
1420mod hal_02;
21+ #[ path = "i2c/hal_1.rs" ]
1522mod hal_1;
1623
1724pub trait Instance :
@@ -222,6 +229,83 @@ impl<I2C: Instance> I2c<I2C> {
222229 Ok ( ( ) )
223230 }
224231
232+ /// Sends START and Address for writing
233+ #[ inline( always) ]
234+ fn prepare_write ( & self , addr : Address , datalen : usize ) -> Result < ( ) , Error > {
235+ // Set up current slave address for writing and disable autoending
236+ self . i2c . cr2 ( ) . modify ( |_, w| {
237+ match addr {
238+ Address :: Seven ( addr) => {
239+ w. add10 ( ) . clear_bit ( ) ;
240+ w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
241+ }
242+ Address :: Ten ( addr) => {
243+ w. add10 ( ) . set_bit ( ) ;
244+ w. sadd ( ) . set ( addr) ;
245+ }
246+ }
247+ w. nbytes ( ) . set ( datalen as u8 ) ;
248+ w. rd_wrn ( ) . clear_bit ( ) ;
249+ w. autoend ( ) . clear_bit ( )
250+ } ) ;
251+
252+ // Send a START condition
253+ self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
254+
255+ // Wait until address was sent
256+ while {
257+ let isr = self . i2c . isr ( ) . read ( ) ;
258+ self . check_and_clear_error_flags ( & isr)
259+ . map_err ( Error :: nack_addr) ?;
260+ isr. txis ( ) . bit_is_clear ( ) && isr. tc ( ) . bit_is_clear ( )
261+ } { }
262+
263+ Ok ( ( ) )
264+ }
265+
266+ /// Sends START and Address for reading
267+ fn prepare_read (
268+ & self ,
269+ addr : Address ,
270+ buflen : usize ,
271+ first_transaction : bool ,
272+ ) -> Result < ( ) , Error > {
273+ // Set up current address for reading
274+ self . i2c . cr2 ( ) . modify ( |_, w| {
275+ match addr {
276+ Address :: Seven ( addr) => {
277+ w. add10 ( ) . clear_bit ( ) ;
278+ w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
279+ }
280+ Address :: Ten ( addr) => {
281+ w. add10 ( ) . set_bit ( ) ;
282+ w. head10r ( ) . bit ( !first_transaction) ;
283+ w. sadd ( ) . set ( addr) ;
284+ }
285+ }
286+ w. nbytes ( ) . set ( buflen as u8 ) ;
287+ w. rd_wrn ( ) . set_bit ( )
288+ } ) ;
289+
290+ // Send a START condition
291+ self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
292+
293+ // Send the autoend after setting the start to get a restart
294+ self . i2c . cr2 ( ) . modify ( |_, w| w. autoend ( ) . set_bit ( ) ) ;
295+
296+ Ok ( ( ) )
297+ }
298+
299+ fn write_bytes ( & mut self , bytes : impl Iterator < Item = u8 > ) -> Result < ( ) , Error > {
300+ // Send bytes
301+ for c in bytes {
302+ self . send_byte ( c) ?;
303+ }
304+
305+ // Fallthrough is success
306+ Ok ( ( ) )
307+ }
308+
225309 fn send_byte ( & self , byte : u8 ) -> Result < ( ) , Error > {
226310 // Wait until we're ready for sending
227311 while {
@@ -251,72 +335,38 @@ impl<I2C: Instance> I2c<I2C> {
251335 Ok ( value)
252336 }
253337
254- pub fn read ( & mut self , addr : u8 , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
255- // Set up current address for reading
256- self . i2c . cr2 ( ) . modify ( |_, w| {
257- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
258- w. nbytes ( ) . set ( buffer. len ( ) as u8 ) ;
259- w. rd_wrn ( ) . set_bit ( )
260- } ) ;
261-
262- // Send a START condition
263- self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
264-
265- // Send the autoend after setting the start to get a restart
266- self . i2c . cr2 ( ) . modify ( |_, w| w. autoend ( ) . set_bit ( ) ) ;
267-
268- // Now read in all bytes
269- for c in buffer. iter_mut ( ) {
338+ fn read_bytes ( & mut self , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
339+ // Receive bytes into buffer
340+ for c in buffer {
270341 * c = self . recv_byte ( ) ?;
271342 }
272343
273- self . end_transaction ( )
344+ Ok ( ( ) )
274345 }
275346
276- pub fn write ( & mut self , addr : u8 , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
277- // Set up current slave address for writing and enable autoending
278- self . i2c . cr2 ( ) . modify ( |_, w| {
279- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
280- w. nbytes ( ) . set ( bytes. len ( ) as u8 ) ;
281- w. rd_wrn ( ) . clear_bit ( ) ;
282- w. autoend ( ) . set_bit ( )
283- } ) ;
284-
285- // Send a START condition
286- self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
287-
288- // Send out all individual bytes
289- for c in bytes {
290- self . send_byte ( * c) ?;
291- }
347+ pub fn read ( & mut self , addr : impl Into < Address > , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
348+ self . prepare_read ( addr. into ( ) , buffer. len ( ) , true ) ?;
349+ self . read_bytes ( buffer) ?;
292350
293351 self . end_transaction ( )
294352 }
295353
296- pub fn write_read ( & mut self , addr : u8 , bytes : & [ u8 ] , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
297- // Set up current slave address for writing and disable autoending
298- self . i2c . cr2 ( ) . modify ( |_, w| {
299- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
300- w. nbytes ( ) . set ( bytes. len ( ) as u8 ) ;
301- w. rd_wrn ( ) . clear_bit ( ) ;
302- w. autoend ( ) . clear_bit ( )
303- } ) ;
354+ pub fn write ( & mut self , addr : impl Into < Address > , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
355+ self . prepare_write ( addr. into ( ) , bytes. len ( ) ) ?;
356+ self . write_bytes ( bytes. iter ( ) . cloned ( ) ) ?;
304357
305- // Send a START condition
306- self . i2c . cr2 ( ) . modify ( |_ , w| w . start ( ) . set_bit ( ) ) ;
358+ self . end_transaction ( )
359+ }
307360
308- // Wait until the transmit buffer is empty and there hasn't been any error condition
309- while {
310- let isr = self . i2c . isr ( ) . read ( ) ;
311- self . check_and_clear_error_flags ( & isr)
312- . map_err ( Error :: nack_addr) ?;
313- isr. txis ( ) . bit_is_clear ( ) && isr. tc ( ) . bit_is_clear ( )
314- } { }
315-
316- // Send out all individual bytes
317- for c in bytes {
318- self . send_byte ( * c) ?;
319- }
361+ pub fn write_read (
362+ & mut self ,
363+ addr : impl Into < Address > ,
364+ bytes : & [ u8 ] ,
365+ buffer : & mut [ u8 ] ,
366+ ) -> Result < ( ) , Error > {
367+ let addr = addr. into ( ) ;
368+ self . prepare_write ( addr, bytes. len ( ) ) ?;
369+ self . write_bytes ( bytes. iter ( ) . cloned ( ) ) ?;
320370
321371 // Wait until data was sent
322372 while {
@@ -326,24 +376,122 @@ impl<I2C: Instance> I2c<I2C> {
326376 isr. tc ( ) . bit_is_clear ( )
327377 } { }
328378
329- // Set up current address for reading
330- self . i2c . cr2 ( ) . modify ( |_, w| {
331- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
332- w. nbytes ( ) . set ( buffer. len ( ) as u8 ) ;
333- w. rd_wrn ( ) . set_bit ( )
334- } ) ;
379+ self . read ( addr, buffer)
380+ }
335381
336- // Send another START condition
337- self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
382+ pub fn transaction < ' a > (
383+ & mut self ,
384+ addr : impl Into < Address > ,
385+ mut ops : impl Iterator < Item = Hal1Operation < ' a > > ,
386+ ) -> Result < ( ) , Error > {
387+ let addr = addr. into ( ) ;
388+ if let Some ( mut prev_op) = ops. next ( ) {
389+ // 1. Generate Start for operation
390+ match & prev_op {
391+ Hal1Operation :: Read ( buf) => self . prepare_read ( addr, buf. len ( ) , true ) ?,
392+ Hal1Operation :: Write ( data) => self . prepare_write ( addr, data. len ( ) ) ?,
393+ } ;
394+
395+ for op in ops {
396+ // 2. Execute previous operations.
397+ match & mut prev_op {
398+ Hal1Operation :: Read ( rb) => self . read_bytes ( rb) ?,
399+ Hal1Operation :: Write ( wb) => self . write_bytes ( wb. iter ( ) . cloned ( ) ) ?,
400+ } ;
401+ // 3. If operation changes type we must generate new start
402+ match ( & prev_op, & op) {
403+ ( Hal1Operation :: Read ( _) , Hal1Operation :: Write ( data) ) => {
404+ self . prepare_write ( addr, data. len ( ) ) ?
405+ }
406+ ( Hal1Operation :: Write ( _) , Hal1Operation :: Read ( buf) ) => {
407+ self . prepare_read ( addr, buf. len ( ) , false ) ?
408+ }
409+ _ => { } // No changes if operation have not changed
410+ }
411+
412+ prev_op = op;
413+ }
338414
339- // Send the autoend after setting the start to get a restart
340- self . i2c . cr2 ( ) . modify ( |_, w| w. autoend ( ) . set_bit ( ) ) ;
415+ // 4. Now, prev_op is last command use methods variations that will generate stop
416+ match prev_op {
417+ Hal1Operation :: Read ( rb) => self . read_bytes ( rb) ?,
418+ Hal1Operation :: Write ( wb) => self . write_bytes ( wb. iter ( ) . cloned ( ) ) ?,
419+ } ;
341420
342- // Now read in all bytes
343- for c in buffer. iter_mut ( ) {
344- * c = self . recv_byte ( ) ?;
421+ self . end_transaction ( ) ?;
345422 }
346423
347- self . end_transaction ( )
424+ // Fallthrough is success
425+ Ok ( ( ) )
426+ }
427+
428+ pub fn transaction_slice (
429+ & mut self ,
430+ addr : impl Into < Address > ,
431+ ops_slice : & mut [ Hal1Operation < ' _ > ] ,
432+ ) -> Result < ( ) , Error > {
433+ let addr = addr. into ( ) ;
434+ transaction_impl ! ( self , addr, ops_slice, Hal1Operation ) ;
435+ // Fallthrough is success
436+ Ok ( ( ) )
437+ }
438+
439+ fn transaction_slice_hal_02 (
440+ & mut self ,
441+ addr : impl Into < Address > ,
442+ ops_slice : & mut [ Hal02Operation < ' _ > ] ,
443+ ) -> Result < ( ) , Error > {
444+ let addr = addr. into ( ) ;
445+ transaction_impl ! ( self , addr, ops_slice, Hal02Operation ) ;
446+ // Fallthrough is success
447+ Ok ( ( ) )
348448 }
349449}
450+
451+ macro_rules! transaction_impl {
452+ ( $self: ident, $addr: ident, $ops_slice: ident, $Operation: ident) => {
453+ let i2c = $self;
454+ let addr = $addr;
455+ let mut ops = $ops_slice. iter_mut( ) ;
456+
457+ if let Some ( mut prev_op) = ops. next( ) {
458+ // 1. Generate Start for operation
459+ match & prev_op {
460+ $Operation:: Read ( buf) => i2c. prepare_read( addr, buf. len( ) , true ) ?,
461+ $Operation:: Write ( data) => i2c. prepare_write( addr, data. len( ) ) ?,
462+ } ;
463+
464+ for op in ops {
465+ // 2. Execute previous operations.
466+ match & mut prev_op {
467+ $Operation:: Read ( rb) => i2c. read_bytes( rb) ?,
468+ $Operation:: Write ( wb) => i2c. write_bytes( wb. iter( ) . cloned( ) ) ?,
469+ } ;
470+ // 3. If operation changes type we must generate new start
471+ match ( & prev_op, & op) {
472+ ( $Operation:: Read ( _) , $Operation:: Write ( data) ) => {
473+ i2c. prepare_write( addr, data. len( ) ) ?
474+ }
475+ ( $Operation:: Write ( _) , $Operation:: Read ( buf) ) => {
476+ i2c. prepare_read( addr, buf. len( ) , false ) ?
477+ }
478+ _ => { } // No changes if operation have not changed
479+ }
480+
481+ prev_op = op;
482+ }
483+
484+ // 4. Now, prev_op is last command use methods variations that will generate stop
485+ match prev_op {
486+ $Operation:: Read ( rb) => i2c. read_bytes( rb) ?,
487+ $Operation:: Write ( wb) => i2c. write_bytes( wb. iter( ) . cloned( ) ) ?,
488+ } ;
489+
490+ i2c. end_transaction( ) ?;
491+ }
492+ } ;
493+ }
494+ use transaction_impl;
495+
496+ // Note: implementation is from f0xx-hal
497+ // TODO: check error handling. See https://github.com/stm32-rs/stm32f0xx-hal/pull/95/files
0 commit comments