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+
11+ #[ path = "i2c/common.rs" ]
12+ mod common;
13+ pub use common:: { Address , Error , NoAcknowledgeSource } ;
14+ use common:: { Hal02Operation , Hal1Operation } ;
15+
1016// Old names
1117pub use I2c as FmpI2c ;
1218pub use Mode as FmpMode ;
1319
20+ #[ path = "i2c/hal_02.rs" ]
1421mod hal_02;
22+ #[ path = "i2c/hal_1.rs" ]
1523mod hal_1;
1624
1725pub trait Instance :
@@ -222,6 +230,83 @@ impl<I2C: Instance> I2c<I2C> {
222230 Ok ( ( ) )
223231 }
224232
233+ /// Sends START and Address for writing
234+ #[ inline( always) ]
235+ fn prepare_write ( & self , addr : Address , datalen : usize ) -> Result < ( ) , Error > {
236+ // Set up current slave address for writing and disable autoending
237+ self . i2c . cr2 ( ) . modify ( |_, w| {
238+ match addr {
239+ Address :: Seven ( addr) => {
240+ w. add10 ( ) . clear_bit ( ) ;
241+ w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
242+ }
243+ Address :: Ten ( addr) => {
244+ w. add10 ( ) . set_bit ( ) ;
245+ w. sadd ( ) . set ( addr) ;
246+ }
247+ }
248+ w. nbytes ( ) . set ( datalen as u8 ) ;
249+ w. rd_wrn ( ) . clear_bit ( ) ;
250+ w. autoend ( ) . clear_bit ( )
251+ } ) ;
252+
253+ // Send a START condition
254+ self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
255+
256+ // Wait until address was sent
257+ while {
258+ let isr = self . i2c . isr ( ) . read ( ) ;
259+ self . check_and_clear_error_flags ( & isr)
260+ . map_err ( Error :: nack_addr) ?;
261+ isr. txis ( ) . bit_is_clear ( ) && isr. tc ( ) . bit_is_clear ( )
262+ } { }
263+
264+ Ok ( ( ) )
265+ }
266+
267+ /// Sends START and Address for reading
268+ fn prepare_read (
269+ & self ,
270+ addr : Address ,
271+ buflen : usize ,
272+ first_transaction : bool ,
273+ ) -> Result < ( ) , Error > {
274+ // Set up current address for reading
275+ self . i2c . cr2 ( ) . modify ( |_, w| {
276+ match addr {
277+ Address :: Seven ( addr) => {
278+ w. add10 ( ) . clear_bit ( ) ;
279+ w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
280+ }
281+ Address :: Ten ( addr) => {
282+ w. add10 ( ) . set_bit ( ) ;
283+ w. head10r ( ) . bit ( !first_transaction) ;
284+ w. sadd ( ) . set ( addr) ;
285+ }
286+ }
287+ w. nbytes ( ) . set ( buflen as u8 ) ;
288+ w. rd_wrn ( ) . set_bit ( )
289+ } ) ;
290+
291+ // Send a START condition
292+ self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
293+
294+ // Send the autoend after setting the start to get a restart
295+ self . i2c . cr2 ( ) . modify ( |_, w| w. autoend ( ) . set_bit ( ) ) ;
296+
297+ Ok ( ( ) )
298+ }
299+
300+ fn write_bytes ( & mut self , bytes : impl Iterator < Item = u8 > ) -> Result < ( ) , Error > {
301+ // Send bytes
302+ for c in bytes {
303+ self . send_byte ( c) ?;
304+ }
305+
306+ // Fallthrough is success
307+ Ok ( ( ) )
308+ }
309+
225310 fn send_byte ( & self , byte : u8 ) -> Result < ( ) , Error > {
226311 // Wait until we're ready for sending
227312 while {
@@ -251,72 +336,38 @@ impl<I2C: Instance> I2c<I2C> {
251336 Ok ( value)
252337 }
253338
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 ( ) {
339+ fn read_bytes ( & mut self , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
340+ // Receive bytes into buffer
341+ for c in buffer {
270342 * c = self . recv_byte ( ) ?;
271343 }
272344
273- self . end_transaction ( )
345+ Ok ( ( ) )
274346 }
275347
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- }
348+ pub fn read ( & mut self , addr : impl Into < Address > , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
349+ self . prepare_read ( addr. into ( ) , buffer. len ( ) , true ) ?;
350+ self . read_bytes ( buffer) ?;
292351
293352 self . end_transaction ( )
294353 }
295354
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- } ) ;
355+ pub fn write ( & mut self , addr : impl Into < Address > , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
356+ self . prepare_write ( addr. into ( ) , bytes. len ( ) ) ?;
357+ self . write_bytes ( bytes. iter ( ) . cloned ( ) ) ?;
304358
305- // Send a START condition
306- self . i2c . cr2 ( ) . modify ( |_ , w| w . start ( ) . set_bit ( ) ) ;
359+ self . end_transaction ( )
360+ }
307361
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- }
362+ pub fn write_read (
363+ & mut self ,
364+ addr : impl Into < Address > ,
365+ bytes : & [ u8 ] ,
366+ buffer : & mut [ u8 ] ,
367+ ) -> Result < ( ) , Error > {
368+ let addr = addr. into ( ) ;
369+ self . prepare_write ( addr, bytes. len ( ) ) ?;
370+ self . write_bytes ( bytes. iter ( ) . cloned ( ) ) ?;
320371
321372 // Wait until data was sent
322373 while {
@@ -326,24 +377,122 @@ impl<I2C: Instance> I2c<I2C> {
326377 isr. tc ( ) . bit_is_clear ( )
327378 } { }
328379
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- } ) ;
380+ self . read ( addr, buffer)
381+ }
335382
336- // Send another START condition
337- self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
383+ pub fn transaction < ' a > (
384+ & mut self ,
385+ addr : impl Into < Address > ,
386+ mut ops : impl Iterator < Item = Hal1Operation < ' a > > ,
387+ ) -> Result < ( ) , Error > {
388+ let addr = addr. into ( ) ;
389+ if let Some ( mut prev_op) = ops. next ( ) {
390+ // 1. Generate Start for operation
391+ match & prev_op {
392+ Hal1Operation :: Read ( buf) => self . prepare_read ( addr, buf. len ( ) , true ) ?,
393+ Hal1Operation :: Write ( data) => self . prepare_write ( addr, data. len ( ) ) ?,
394+ } ;
395+
396+ for op in ops {
397+ // 2. Execute previous operations.
398+ match & mut prev_op {
399+ Hal1Operation :: Read ( rb) => self . read_bytes ( rb) ?,
400+ Hal1Operation :: Write ( wb) => self . write_bytes ( wb. iter ( ) . cloned ( ) ) ?,
401+ } ;
402+ // 3. If operation changes type we must generate new start
403+ match ( & prev_op, & op) {
404+ ( Hal1Operation :: Read ( _) , Hal1Operation :: Write ( data) ) => {
405+ self . prepare_write ( addr, data. len ( ) ) ?
406+ }
407+ ( Hal1Operation :: Write ( _) , Hal1Operation :: Read ( buf) ) => {
408+ self . prepare_read ( addr, buf. len ( ) , false ) ?
409+ }
410+ _ => { } // No changes if operation have not changed
411+ }
412+
413+ prev_op = op;
414+ }
338415
339- // Send the autoend after setting the start to get a restart
340- self . i2c . cr2 ( ) . modify ( |_, w| w. autoend ( ) . set_bit ( ) ) ;
416+ // 4. Now, prev_op is last command use methods variations that will generate stop
417+ match prev_op {
418+ Hal1Operation :: Read ( rb) => self . read_bytes ( rb) ?,
419+ Hal1Operation :: Write ( wb) => self . write_bytes ( wb. iter ( ) . cloned ( ) ) ?,
420+ } ;
341421
342- // Now read in all bytes
343- for c in buffer. iter_mut ( ) {
344- * c = self . recv_byte ( ) ?;
422+ self . end_transaction ( ) ?;
345423 }
346424
347- self . end_transaction ( )
425+ // Fallthrough is success
426+ Ok ( ( ) )
427+ }
428+
429+ pub fn transaction_slice (
430+ & mut self ,
431+ addr : impl Into < Address > ,
432+ ops_slice : & mut [ Hal1Operation < ' _ > ] ,
433+ ) -> Result < ( ) , Error > {
434+ let addr = addr. into ( ) ;
435+ transaction_impl ! ( self , addr, ops_slice, Hal1Operation ) ;
436+ // Fallthrough is success
437+ Ok ( ( ) )
438+ }
439+
440+ fn transaction_slice_hal_02 (
441+ & mut self ,
442+ addr : impl Into < Address > ,
443+ ops_slice : & mut [ Hal02Operation < ' _ > ] ,
444+ ) -> Result < ( ) , Error > {
445+ let addr = addr. into ( ) ;
446+ transaction_impl ! ( self , addr, ops_slice, Hal02Operation ) ;
447+ // Fallthrough is success
448+ Ok ( ( ) )
348449 }
349450}
451+
452+ macro_rules! transaction_impl {
453+ ( $self: ident, $addr: ident, $ops_slice: ident, $Operation: ident) => {
454+ let i2c = $self;
455+ let addr = $addr;
456+ let mut ops = $ops_slice. iter_mut( ) ;
457+
458+ if let Some ( mut prev_op) = ops. next( ) {
459+ // 1. Generate Start for operation
460+ match & prev_op {
461+ $Operation:: Read ( buf) => i2c. prepare_read( addr, buf. len( ) , true ) ?,
462+ $Operation:: Write ( data) => i2c. prepare_write( addr, data. len( ) ) ?,
463+ } ;
464+
465+ for op in ops {
466+ // 2. Execute previous operations.
467+ match & mut prev_op {
468+ $Operation:: Read ( rb) => i2c. read_bytes( rb) ?,
469+ $Operation:: Write ( wb) => i2c. write_bytes( wb. iter( ) . cloned( ) ) ?,
470+ } ;
471+ // 3. If operation changes type we must generate new start
472+ match ( & prev_op, & op) {
473+ ( $Operation:: Read ( _) , $Operation:: Write ( data) ) => {
474+ i2c. prepare_write( addr, data. len( ) ) ?
475+ }
476+ ( $Operation:: Write ( _) , $Operation:: Read ( buf) ) => {
477+ i2c. prepare_read( addr, buf. len( ) , false ) ?
478+ }
479+ _ => { } // No changes if operation have not changed
480+ }
481+
482+ prev_op = op;
483+ }
484+
485+ // 4. Now, prev_op is last command use methods variations that will generate stop
486+ match prev_op {
487+ $Operation:: Read ( rb) => i2c. read_bytes( rb) ?,
488+ $Operation:: Write ( wb) => i2c. write_bytes( wb. iter( ) . cloned( ) ) ?,
489+ } ;
490+
491+ i2c. end_transaction( ) ?;
492+ }
493+ } ;
494+ }
495+ use transaction_impl;
496+
497+ // Note: implementation is from f0xx-hal
498+ // TODO: check error handling. See https://github.com/stm32-rs/stm32f0xx-hal/pull/95/files
0 commit comments