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