1
1
use core:: ops:: Deref ;
2
2
3
3
use crate :: gpio;
4
- use crate :: i2c :: { Error , NoAcknowledgeSource } ;
4
+
5
5
use crate :: pac:: fmpi2c1 as i2c1;
6
6
use crate :: pac:: { self , rcc, RCC } ;
7
7
use crate :: rcc:: { BusClock , Clocks , Enable , Reset } ;
8
8
use fugit:: { HertzU32 as Hertz , RateExtU32 } ;
9
9
use micromath:: F32Ext ;
10
10
11
+ #[ path = "i2c/common.rs" ]
12
+ mod common;
13
+ pub use common:: { Address , Error , NoAcknowledgeSource } ;
14
+ use common:: { Hal02Operation , Hal1Operation } ;
15
+
11
16
// Old names
12
17
pub use I2c as FmpI2c ;
13
18
pub use Mode as FmpMode ;
14
19
20
+ #[ path = "i2c/hal_02.rs" ]
15
21
mod hal_02;
22
+ #[ path = "i2c/hal_1.rs" ]
16
23
mod hal_1;
17
24
18
25
type I2cSel = rcc:: dckcfgr2:: FMPI2C1SEL ;
@@ -403,6 +410,83 @@ impl<I2C: Instance> I2c<I2C> {
403
410
Ok ( ( ) )
404
411
}
405
412
413
+ /// Sends START and Address for writing
414
+ #[ inline( always) ]
415
+ fn prepare_write ( & self , addr : Address , datalen : usize ) -> Result < ( ) , Error > {
416
+ // Set up current slave address for writing and disable autoending
417
+ self . i2c . cr2 ( ) . modify ( |_, w| {
418
+ match addr {
419
+ Address :: Seven ( addr) => {
420
+ w. add10 ( ) . clear_bit ( ) ;
421
+ w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
422
+ }
423
+ Address :: Ten ( addr) => {
424
+ w. add10 ( ) . set_bit ( ) ;
425
+ w. sadd ( ) . set ( addr) ;
426
+ }
427
+ }
428
+ w. nbytes ( ) . set ( datalen as u8 ) ;
429
+ w. rd_wrn ( ) . clear_bit ( ) ;
430
+ w. autoend ( ) . clear_bit ( )
431
+ } ) ;
432
+
433
+ // Send a START condition
434
+ self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
435
+
436
+ // Wait until address was sent
437
+ while {
438
+ let isr = self . i2c . isr ( ) . read ( ) ;
439
+ self . check_and_clear_error_flags ( & isr)
440
+ . map_err ( Error :: nack_addr) ?;
441
+ isr. txis ( ) . bit_is_clear ( ) && isr. tc ( ) . bit_is_clear ( )
442
+ } { }
443
+
444
+ Ok ( ( ) )
445
+ }
446
+
447
+ /// Sends START and Address for reading
448
+ fn prepare_read (
449
+ & self ,
450
+ addr : Address ,
451
+ buflen : usize ,
452
+ first_transaction : bool ,
453
+ ) -> Result < ( ) , Error > {
454
+ // Set up current address for reading
455
+ self . i2c . cr2 ( ) . modify ( |_, w| {
456
+ match addr {
457
+ Address :: Seven ( addr) => {
458
+ w. add10 ( ) . clear_bit ( ) ;
459
+ w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
460
+ }
461
+ Address :: Ten ( addr) => {
462
+ w. add10 ( ) . set_bit ( ) ;
463
+ w. head10r ( ) . bit ( !first_transaction) ;
464
+ w. sadd ( ) . set ( addr) ;
465
+ }
466
+ }
467
+ w. nbytes ( ) . set ( buflen as u8 ) ;
468
+ w. rd_wrn ( ) . set_bit ( )
469
+ } ) ;
470
+
471
+ // Send a START condition
472
+ self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
473
+
474
+ // Send the autoend after setting the start to get a restart
475
+ self . i2c . cr2 ( ) . modify ( |_, w| w. autoend ( ) . set_bit ( ) ) ;
476
+
477
+ Ok ( ( ) )
478
+ }
479
+
480
+ fn write_bytes ( & mut self , bytes : impl Iterator < Item = u8 > ) -> Result < ( ) , Error > {
481
+ // Send bytes
482
+ for c in bytes {
483
+ self . send_byte ( c) ?;
484
+ }
485
+
486
+ // Fallthrough is success
487
+ Ok ( ( ) )
488
+ }
489
+
406
490
fn send_byte ( & self , byte : u8 ) -> Result < ( ) , Error > {
407
491
// Wait until we're ready for sending
408
492
while {
@@ -432,72 +516,38 @@ impl<I2C: Instance> I2c<I2C> {
432
516
Ok ( value)
433
517
}
434
518
435
- pub fn read ( & mut self , addr : u8 , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
436
- // Set up current address for reading
437
- self . i2c . cr2 ( ) . modify ( |_, w| {
438
- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
439
- w. nbytes ( ) . set ( buffer. len ( ) as u8 ) ;
440
- w. rd_wrn ( ) . set_bit ( )
441
- } ) ;
442
-
443
- // Send a START condition
444
- self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
445
-
446
- // Send the autoend after setting the start to get a restart
447
- self . i2c . cr2 ( ) . modify ( |_, w| w. autoend ( ) . set_bit ( ) ) ;
448
-
449
- // Now read in all bytes
450
- for c in buffer. iter_mut ( ) {
519
+ fn read_bytes ( & mut self , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
520
+ // Receive bytes into buffer
521
+ for c in buffer {
451
522
* c = self . recv_byte ( ) ?;
452
523
}
453
524
454
- self . end_transaction ( )
525
+ Ok ( ( ) )
455
526
}
456
527
457
- pub fn write ( & mut self , addr : u8 , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
458
- // Set up current slave address for writing and enable autoending
459
- self . i2c . cr2 ( ) . modify ( |_, w| {
460
- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
461
- w. nbytes ( ) . set ( bytes. len ( ) as u8 ) ;
462
- w. rd_wrn ( ) . clear_bit ( ) ;
463
- w. autoend ( ) . set_bit ( )
464
- } ) ;
465
-
466
- // Send a START condition
467
- self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
468
-
469
- // Send out all individual bytes
470
- for c in bytes {
471
- self . send_byte ( * c) ?;
472
- }
528
+ pub fn read ( & mut self , addr : impl Into < Address > , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
529
+ self . prepare_read ( addr. into ( ) , buffer. len ( ) , true ) ?;
530
+ self . read_bytes ( buffer) ?;
473
531
474
532
self . end_transaction ( )
475
533
}
476
534
477
- pub fn write_read ( & mut self , addr : u8 , bytes : & [ u8 ] , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
478
- // Set up current slave address for writing and disable autoending
479
- self . i2c . cr2 ( ) . modify ( |_, w| {
480
- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
481
- w. nbytes ( ) . set ( bytes. len ( ) as u8 ) ;
482
- w. rd_wrn ( ) . clear_bit ( ) ;
483
- w. autoend ( ) . clear_bit ( )
484
- } ) ;
535
+ pub fn write ( & mut self , addr : impl Into < Address > , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
536
+ self . prepare_write ( addr. into ( ) , bytes. len ( ) ) ?;
537
+ self . write_bytes ( bytes. iter ( ) . cloned ( ) ) ?;
485
538
486
- // Send a START condition
487
- self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
488
-
489
- // Wait until the transmit buffer is empty and there hasn't been any error condition
490
- while {
491
- let isr = self . i2c . isr ( ) . read ( ) ;
492
- self . check_and_clear_error_flags ( & isr)
493
- . map_err ( Error :: nack_addr) ?;
494
- isr. txis ( ) . bit_is_clear ( ) && isr. tc ( ) . bit_is_clear ( )
495
- } { }
539
+ self . end_transaction ( )
540
+ }
496
541
497
- // Send out all individual bytes
498
- for c in bytes {
499
- self . send_byte ( * c) ?;
500
- }
542
+ pub fn write_read (
543
+ & mut self ,
544
+ addr : impl Into < Address > ,
545
+ bytes : & [ u8 ] ,
546
+ buffer : & mut [ u8 ] ,
547
+ ) -> Result < ( ) , Error > {
548
+ let addr = addr. into ( ) ;
549
+ self . prepare_write ( addr, bytes. len ( ) ) ?;
550
+ self . write_bytes ( bytes. iter ( ) . cloned ( ) ) ?;
501
551
502
552
// Wait until data was sent
503
553
while {
@@ -507,24 +557,122 @@ impl<I2C: Instance> I2c<I2C> {
507
557
isr. tc ( ) . bit_is_clear ( )
508
558
} { }
509
559
510
- // Set up current address for reading
511
- self . i2c . cr2 ( ) . modify ( |_, w| {
512
- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
513
- w. nbytes ( ) . set ( buffer. len ( ) as u8 ) ;
514
- w. rd_wrn ( ) . set_bit ( )
515
- } ) ;
560
+ self . read ( addr, buffer)
561
+ }
516
562
517
- // Send another START condition
518
- self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
563
+ pub fn transaction < ' a > (
564
+ & mut self ,
565
+ addr : impl Into < Address > ,
566
+ mut ops : impl Iterator < Item = Hal1Operation < ' a > > ,
567
+ ) -> Result < ( ) , Error > {
568
+ let addr = addr. into ( ) ;
569
+ if let Some ( mut prev_op) = ops. next ( ) {
570
+ // 1. Generate Start for operation
571
+ match & prev_op {
572
+ Hal1Operation :: Read ( buf) => self . prepare_read ( addr, buf. len ( ) , true ) ?,
573
+ Hal1Operation :: Write ( data) => self . prepare_write ( addr, data. len ( ) ) ?,
574
+ } ;
575
+
576
+ for op in ops {
577
+ // 2. Execute previous operations.
578
+ match & mut prev_op {
579
+ Hal1Operation :: Read ( rb) => self . read_bytes ( rb) ?,
580
+ Hal1Operation :: Write ( wb) => self . write_bytes ( wb. iter ( ) . cloned ( ) ) ?,
581
+ } ;
582
+ // 3. If operation changes type we must generate new start
583
+ match ( & prev_op, & op) {
584
+ ( Hal1Operation :: Read ( _) , Hal1Operation :: Write ( data) ) => {
585
+ self . prepare_write ( addr, data. len ( ) ) ?
586
+ }
587
+ ( Hal1Operation :: Write ( _) , Hal1Operation :: Read ( buf) ) => {
588
+ self . prepare_read ( addr, buf. len ( ) , false ) ?
589
+ }
590
+ _ => { } // No changes if operation have not changed
591
+ }
519
592
520
- // Send the autoend after setting the start to get a restart
521
- self . i2c . cr2 ( ) . modify ( |_ , w| w . autoend ( ) . set_bit ( ) ) ;
593
+ prev_op = op ;
594
+ }
522
595
523
- // Now read in all bytes
524
- for c in buffer. iter_mut ( ) {
525
- * c = self . recv_byte ( ) ?;
596
+ // 4. Now, prev_op is last command use methods variations that will generate stop
597
+ match prev_op {
598
+ Hal1Operation :: Read ( rb) => self . read_bytes ( rb) ?,
599
+ Hal1Operation :: Write ( wb) => self . write_bytes ( wb. iter ( ) . cloned ( ) ) ?,
600
+ } ;
601
+
602
+ self . end_transaction ( ) ?;
526
603
}
527
604
528
- self . end_transaction ( )
605
+ // Fallthrough is success
606
+ Ok ( ( ) )
607
+ }
608
+
609
+ pub fn transaction_slice (
610
+ & mut self ,
611
+ addr : impl Into < Address > ,
612
+ ops_slice : & mut [ Hal1Operation < ' _ > ] ,
613
+ ) -> Result < ( ) , Error > {
614
+ let addr = addr. into ( ) ;
615
+ transaction_impl ! ( self , addr, ops_slice, Hal1Operation ) ;
616
+ // Fallthrough is success
617
+ Ok ( ( ) )
618
+ }
619
+
620
+ fn transaction_slice_hal_02 (
621
+ & mut self ,
622
+ addr : impl Into < Address > ,
623
+ ops_slice : & mut [ Hal02Operation < ' _ > ] ,
624
+ ) -> Result < ( ) , Error > {
625
+ let addr = addr. into ( ) ;
626
+ transaction_impl ! ( self , addr, ops_slice, Hal02Operation ) ;
627
+ // Fallthrough is success
628
+ Ok ( ( ) )
529
629
}
530
630
}
631
+
632
+ macro_rules! transaction_impl {
633
+ ( $self: ident, $addr: ident, $ops_slice: ident, $Operation: ident) => {
634
+ let i2c = $self;
635
+ let addr = $addr;
636
+ let mut ops = $ops_slice. iter_mut( ) ;
637
+
638
+ if let Some ( mut prev_op) = ops. next( ) {
639
+ // 1. Generate Start for operation
640
+ match & prev_op {
641
+ $Operation:: Read ( buf) => i2c. prepare_read( addr, buf. len( ) , true ) ?,
642
+ $Operation:: Write ( data) => i2c. prepare_write( addr, data. len( ) ) ?,
643
+ } ;
644
+
645
+ for op in ops {
646
+ // 2. Execute previous operations.
647
+ match & mut prev_op {
648
+ $Operation:: Read ( rb) => i2c. read_bytes( rb) ?,
649
+ $Operation:: Write ( wb) => i2c. write_bytes( wb. iter( ) . cloned( ) ) ?,
650
+ } ;
651
+ // 3. If operation changes type we must generate new start
652
+ match ( & prev_op, & op) {
653
+ ( $Operation:: Read ( _) , $Operation:: Write ( data) ) => {
654
+ i2c. prepare_write( addr, data. len( ) ) ?
655
+ }
656
+ ( $Operation:: Write ( _) , $Operation:: Read ( buf) ) => {
657
+ i2c. prepare_read( addr, buf. len( ) , false ) ?
658
+ }
659
+ _ => { } // No changes if operation have not changed
660
+ }
661
+
662
+ prev_op = op;
663
+ }
664
+
665
+ // 4. Now, prev_op is last command use methods variations that will generate stop
666
+ match prev_op {
667
+ $Operation:: Read ( rb) => i2c. read_bytes( rb) ?,
668
+ $Operation:: Write ( wb) => i2c. write_bytes( wb. iter( ) . cloned( ) ) ?,
669
+ } ;
670
+
671
+ i2c. end_transaction( ) ?;
672
+ }
673
+ } ;
674
+ }
675
+ use transaction_impl;
676
+
677
+ // Note: implementation is from f0xx-hal
678
+ // TODO: check error handling. See https://github.com/stm32-rs/stm32f0xx-hal/pull/95/files
0 commit comments