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 :
@@ -213,6 +220,83 @@ impl<I2C: Instance> I2c<I2C> {
213220 Ok ( ( ) )
214221 }
215222
223+ /// Sends START and Address for writing
224+ #[ inline( always) ]
225+ fn prepare_write ( & self , addr : Address , datalen : usize ) -> Result < ( ) , Error > {
226+ // Set up current slave address for writing and disable autoending
227+ self . i2c . cr2 ( ) . modify ( |_, w| {
228+ match addr {
229+ Address :: Seven ( addr) => {
230+ w. add10 ( ) . clear_bit ( ) ;
231+ w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
232+ }
233+ Address :: Ten ( addr) => {
234+ w. add10 ( ) . set_bit ( ) ;
235+ w. sadd ( ) . set ( addr) ;
236+ }
237+ }
238+ w. nbytes ( ) . set ( datalen as u8 ) ;
239+ w. rd_wrn ( ) . clear_bit ( ) ;
240+ w. autoend ( ) . clear_bit ( )
241+ } ) ;
242+
243+ // Send a START condition
244+ self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
245+
246+ // Wait until address was sent
247+ while {
248+ let isr = self . i2c . isr ( ) . read ( ) ;
249+ self . check_and_clear_error_flags ( & isr)
250+ . map_err ( Error :: nack_addr) ?;
251+ isr. txis ( ) . bit_is_clear ( ) && isr. tc ( ) . bit_is_clear ( )
252+ } { }
253+
254+ Ok ( ( ) )
255+ }
256+
257+ /// Sends START and Address for reading
258+ fn prepare_read (
259+ & self ,
260+ addr : Address ,
261+ buflen : usize ,
262+ first_transaction : bool ,
263+ ) -> Result < ( ) , Error > {
264+ // Set up current address for reading
265+ self . i2c . cr2 ( ) . modify ( |_, w| {
266+ match addr {
267+ Address :: Seven ( addr) => {
268+ w. add10 ( ) . clear_bit ( ) ;
269+ w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
270+ }
271+ Address :: Ten ( addr) => {
272+ w. add10 ( ) . set_bit ( ) ;
273+ w. head10r ( ) . bit ( !first_transaction) ;
274+ w. sadd ( ) . set ( addr) ;
275+ }
276+ }
277+ w. nbytes ( ) . set ( buflen as u8 ) ;
278+ w. rd_wrn ( ) . set_bit ( )
279+ } ) ;
280+
281+ // Send a START condition
282+ self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
283+
284+ // Send the autoend after setting the start to get a restart
285+ self . i2c . cr2 ( ) . modify ( |_, w| w. autoend ( ) . set_bit ( ) ) ;
286+
287+ Ok ( ( ) )
288+ }
289+
290+ fn write_bytes ( & mut self , bytes : impl Iterator < Item = u8 > ) -> Result < ( ) , Error > {
291+ // Send bytes
292+ for c in bytes {
293+ self . send_byte ( c) ?;
294+ }
295+
296+ // Fallthrough is success
297+ Ok ( ( ) )
298+ }
299+
216300 fn send_byte ( & self , byte : u8 ) -> Result < ( ) , Error > {
217301 // Wait until we're ready for sending
218302 while {
@@ -242,72 +326,38 @@ impl<I2C: Instance> I2c<I2C> {
242326 Ok ( value)
243327 }
244328
245- pub fn read ( & mut self , addr : u8 , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
246- // Set up current address for reading
247- self . i2c . cr2 ( ) . modify ( |_, w| {
248- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
249- w. nbytes ( ) . set ( buffer. len ( ) as u8 ) ;
250- w. rd_wrn ( ) . set_bit ( )
251- } ) ;
252-
253- // Send a START condition
254- self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
255-
256- // Send the autoend after setting the start to get a restart
257- self . i2c . cr2 ( ) . modify ( |_, w| w. autoend ( ) . set_bit ( ) ) ;
258-
259- // Now read in all bytes
260- for c in buffer. iter_mut ( ) {
329+ fn read_bytes ( & mut self , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
330+ // Receive bytes into buffer
331+ for c in buffer {
261332 * c = self . recv_byte ( ) ?;
262333 }
263334
264- self . end_transaction ( )
335+ Ok ( ( ) )
265336 }
266337
267- pub fn write ( & mut self , addr : u8 , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
268- // Set up current slave address for writing and enable autoending
269- self . i2c . cr2 ( ) . modify ( |_, w| {
270- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
271- w. nbytes ( ) . set ( bytes. len ( ) as u8 ) ;
272- w. rd_wrn ( ) . clear_bit ( ) ;
273- w. autoend ( ) . set_bit ( )
274- } ) ;
275-
276- // Send a START condition
277- self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
278-
279- // Send out all individual bytes
280- for c in bytes {
281- self . send_byte ( * c) ?;
282- }
338+ pub fn read ( & mut self , addr : impl Into < Address > , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
339+ self . prepare_read ( addr. into ( ) , buffer. len ( ) , true ) ?;
340+ self . read_bytes ( buffer) ?;
283341
284342 self . end_transaction ( )
285343 }
286344
287- pub fn write_read ( & mut self , addr : u8 , bytes : & [ u8 ] , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
288- // Set up current slave address for writing and disable autoending
289- self . i2c . cr2 ( ) . modify ( |_, w| {
290- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
291- w. nbytes ( ) . set ( bytes. len ( ) as u8 ) ;
292- w. rd_wrn ( ) . clear_bit ( ) ;
293- w. autoend ( ) . clear_bit ( )
294- } ) ;
345+ pub fn write ( & mut self , addr : impl Into < Address > , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
346+ self . prepare_write ( addr. into ( ) , bytes. len ( ) ) ?;
347+ self . write_bytes ( bytes. iter ( ) . cloned ( ) ) ?;
295348
296- // Send a START condition
297- self . i2c . cr2 ( ) . modify ( |_ , w| w . start ( ) . set_bit ( ) ) ;
349+ self . end_transaction ( )
350+ }
298351
299- // Wait until the transmit buffer is empty and there hasn't been any error condition
300- while {
301- let isr = self . i2c . isr ( ) . read ( ) ;
302- self . check_and_clear_error_flags ( & isr)
303- . map_err ( Error :: nack_addr) ?;
304- isr. txis ( ) . bit_is_clear ( ) && isr. tc ( ) . bit_is_clear ( )
305- } { }
306-
307- // Send out all individual bytes
308- for c in bytes {
309- self . send_byte ( * c) ?;
310- }
352+ pub fn write_read (
353+ & mut self ,
354+ addr : impl Into < Address > ,
355+ bytes : & [ u8 ] ,
356+ buffer : & mut [ u8 ] ,
357+ ) -> Result < ( ) , Error > {
358+ let addr = addr. into ( ) ;
359+ self . prepare_write ( addr, bytes. len ( ) ) ?;
360+ self . write_bytes ( bytes. iter ( ) . cloned ( ) ) ?;
311361
312362 // Wait until data was sent
313363 while {
@@ -317,24 +367,122 @@ impl<I2C: Instance> I2c<I2C> {
317367 isr. tc ( ) . bit_is_clear ( )
318368 } { }
319369
320- // Set up current address for reading
321- self . i2c . cr2 ( ) . modify ( |_, w| {
322- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
323- w. nbytes ( ) . set ( buffer. len ( ) as u8 ) ;
324- w. rd_wrn ( ) . set_bit ( )
325- } ) ;
370+ self . read ( addr, buffer)
371+ }
326372
327- // Send another START condition
328- self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
373+ pub fn transaction < ' a > (
374+ & mut self ,
375+ addr : impl Into < Address > ,
376+ mut ops : impl Iterator < Item = Hal1Operation < ' a > > ,
377+ ) -> Result < ( ) , Error > {
378+ let addr = addr. into ( ) ;
379+ if let Some ( mut prev_op) = ops. next ( ) {
380+ // 1. Generate Start for operation
381+ match & prev_op {
382+ Hal1Operation :: Read ( buf) => self . prepare_read ( addr, buf. len ( ) , true ) ?,
383+ Hal1Operation :: Write ( data) => self . prepare_write ( addr, data. len ( ) ) ?,
384+ } ;
385+
386+ for op in ops {
387+ // 2. Execute previous operations.
388+ match & mut prev_op {
389+ Hal1Operation :: Read ( rb) => self . read_bytes ( rb) ?,
390+ Hal1Operation :: Write ( wb) => self . write_bytes ( wb. iter ( ) . cloned ( ) ) ?,
391+ } ;
392+ // 3. If operation changes type we must generate new start
393+ match ( & prev_op, & op) {
394+ ( Hal1Operation :: Read ( _) , Hal1Operation :: Write ( data) ) => {
395+ self . prepare_write ( addr, data. len ( ) ) ?
396+ }
397+ ( Hal1Operation :: Write ( _) , Hal1Operation :: Read ( buf) ) => {
398+ self . prepare_read ( addr, buf. len ( ) , false ) ?
399+ }
400+ _ => { } // No changes if operation have not changed
401+ }
402+
403+ prev_op = op;
404+ }
329405
330- // Send the autoend after setting the start to get a restart
331- self . i2c . cr2 ( ) . modify ( |_, w| w. autoend ( ) . set_bit ( ) ) ;
406+ // 4. Now, prev_op is last command use methods variations that will generate stop
407+ match prev_op {
408+ Hal1Operation :: Read ( rb) => self . read_bytes ( rb) ?,
409+ Hal1Operation :: Write ( wb) => self . write_bytes ( wb. iter ( ) . cloned ( ) ) ?,
410+ } ;
332411
333- // Now read in all bytes
334- for c in buffer. iter_mut ( ) {
335- * c = self . recv_byte ( ) ?;
412+ self . end_transaction ( ) ?;
336413 }
337414
338- self . end_transaction ( )
415+ // Fallthrough is success
416+ Ok ( ( ) )
417+ }
418+
419+ pub fn transaction_slice (
420+ & mut self ,
421+ addr : impl Into < Address > ,
422+ ops_slice : & mut [ Hal1Operation < ' _ > ] ,
423+ ) -> Result < ( ) , Error > {
424+ let addr = addr. into ( ) ;
425+ transaction_impl ! ( self , addr, ops_slice, Hal1Operation ) ;
426+ // Fallthrough is success
427+ Ok ( ( ) )
428+ }
429+
430+ fn transaction_slice_hal_02 (
431+ & mut self ,
432+ addr : impl Into < Address > ,
433+ ops_slice : & mut [ Hal02Operation < ' _ > ] ,
434+ ) -> Result < ( ) , Error > {
435+ let addr = addr. into ( ) ;
436+ transaction_impl ! ( self , addr, ops_slice, Hal02Operation ) ;
437+ // Fallthrough is success
438+ Ok ( ( ) )
339439 }
340440}
441+
442+ macro_rules! transaction_impl {
443+ ( $self: ident, $addr: ident, $ops_slice: ident, $Operation: ident) => {
444+ let i2c = $self;
445+ let addr = $addr;
446+ let mut ops = $ops_slice. iter_mut( ) ;
447+
448+ if let Some ( mut prev_op) = ops. next( ) {
449+ // 1. Generate Start for operation
450+ match & prev_op {
451+ $Operation:: Read ( buf) => i2c. prepare_read( addr, buf. len( ) , true ) ?,
452+ $Operation:: Write ( data) => i2c. prepare_write( addr, data. len( ) ) ?,
453+ } ;
454+
455+ for op in ops {
456+ // 2. Execute previous operations.
457+ match & mut prev_op {
458+ $Operation:: Read ( rb) => i2c. read_bytes( rb) ?,
459+ $Operation:: Write ( wb) => i2c. write_bytes( wb. iter( ) . cloned( ) ) ?,
460+ } ;
461+ // 3. If operation changes type we must generate new start
462+ match ( & prev_op, & op) {
463+ ( $Operation:: Read ( _) , $Operation:: Write ( data) ) => {
464+ i2c. prepare_write( addr, data. len( ) ) ?
465+ }
466+ ( $Operation:: Write ( _) , $Operation:: Read ( buf) ) => {
467+ i2c. prepare_read( addr, buf. len( ) , false ) ?
468+ }
469+ _ => { } // No changes if operation have not changed
470+ }
471+
472+ prev_op = op;
473+ }
474+
475+ // 4. Now, prev_op is last command use methods variations that will generate stop
476+ match prev_op {
477+ $Operation:: Read ( rb) => i2c. read_bytes( rb) ?,
478+ $Operation:: Write ( wb) => i2c. write_bytes( wb. iter( ) . cloned( ) ) ?,
479+ } ;
480+
481+ i2c. end_transaction( ) ?;
482+ }
483+ } ;
484+ }
485+ use transaction_impl;
486+
487+ // Note: implementation is from f0xx-hal
488+ // TODO: check error handling. See https://github.com/stm32-rs/stm32f0xx-hal/pull/95/files
0 commit comments