1
1
use core:: ops:: Deref ;
2
2
3
3
use crate :: gpio;
4
- use crate :: i2c:: { Error , NoAcknowledgeSource } ;
4
+ use crate :: i2c:: { Address , Error , Hal02Operation , Hal1Operation , NoAcknowledgeSource } ;
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/hal_02.rs" ]
11
12
mod hal_02;
13
+ #[ path = "i2c/hal_1.rs" ]
12
14
mod hal_1;
13
15
14
16
type I2cSel = rcc:: dckcfgr2:: FMPI2C1SEL ;
@@ -364,6 +366,7 @@ impl<I2C: Instance> I2c<I2C> {
364
366
self . i2c . cr1 ( ) . modify ( |_, w| w. pe ( ) . set_bit ( ) ) ;
365
367
}
366
368
369
+ #[ inline( always) ]
367
370
fn check_and_clear_error_flags ( & self , isr : & i2c1:: isr:: R ) -> Result < ( ) , Error > {
368
371
// If we received a NACK, then this is an error
369
372
if isr. nackf ( ) . bit_is_set ( ) {
@@ -376,6 +379,7 @@ impl<I2C: Instance> I2c<I2C> {
376
379
Ok ( ( ) )
377
380
}
378
381
382
+ #[ inline( always) ]
379
383
fn end_transaction ( & self ) -> Result < ( ) , Error > {
380
384
// Check and clear flags if they somehow ended up set
381
385
self . check_and_clear_error_flags ( & self . i2c . isr ( ) . read ( ) )
@@ -385,11 +389,20 @@ impl<I2C: Instance> I2c<I2C> {
385
389
386
390
/// Sends START and Address for writing
387
391
#[ inline( always) ]
388
- fn prepare_write ( & self , addr : u8 , datalen : u8 ) -> Result < ( ) , Error > {
392
+ fn prepare_write ( & self , addr : Address , datalen : usize ) -> Result < ( ) , Error > {
389
393
// Set up current slave address for writing and disable autoending
390
394
self . i2c . cr2 ( ) . modify ( |_, w| {
391
- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
392
- w. nbytes ( ) . set ( datalen) ;
395
+ match addr {
396
+ Address :: Seven ( addr) => {
397
+ w. add10 ( ) . clear_bit ( ) ;
398
+ w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
399
+ }
400
+ Address :: Ten ( addr) => {
401
+ w. add10 ( ) . set_bit ( ) ;
402
+ w. sadd ( ) . set ( addr) ;
403
+ }
404
+ }
405
+ w. nbytes ( ) . set ( datalen as u8 ) ;
393
406
w. rd_wrn ( ) . clear_bit ( ) ;
394
407
w. autoend ( ) . clear_bit ( )
395
408
} ) ;
@@ -409,11 +422,26 @@ impl<I2C: Instance> I2c<I2C> {
409
422
}
410
423
411
424
/// Sends START and Address for reading
412
- fn prepare_read ( & self , addr : u8 , buflen : u8 ) -> Result < ( ) , Error > {
425
+ fn prepare_read (
426
+ & self ,
427
+ addr : Address ,
428
+ buflen : usize ,
429
+ first_transaction : bool ,
430
+ ) -> Result < ( ) , Error > {
413
431
// Set up current address for reading
414
432
self . i2c . cr2 ( ) . modify ( |_, w| {
415
- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
416
- w. nbytes ( ) . set ( buflen) ;
433
+ match addr {
434
+ Address :: Seven ( addr) => {
435
+ w. add10 ( ) . clear_bit ( ) ;
436
+ w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
437
+ }
438
+ Address :: Ten ( addr) => {
439
+ w. add10 ( ) . set_bit ( ) ;
440
+ w. head10r ( ) . bit ( !first_transaction) ;
441
+ w. sadd ( ) . set ( addr) ;
442
+ }
443
+ }
444
+ w. nbytes ( ) . set ( buflen as u8 ) ;
417
445
w. rd_wrn ( ) . set_bit ( )
418
446
} ) ;
419
447
@@ -474,22 +502,28 @@ impl<I2C: Instance> I2c<I2C> {
474
502
Ok ( ( ) )
475
503
}
476
504
477
- pub fn read ( & mut self , addr : u8 , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
478
- self . prepare_read ( addr, buffer. len ( ) as u8 ) ?;
505
+ pub fn read ( & mut self , addr : impl Into < Address > , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
506
+ self . prepare_read ( addr. into ( ) , buffer. len ( ) , true ) ?;
479
507
self . read_bytes ( buffer) ?;
480
508
481
509
self . end_transaction ( )
482
510
}
483
511
484
- pub fn write ( & mut self , addr : u8 , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
485
- self . prepare_write ( addr, bytes. len ( ) as u8 ) ?;
512
+ pub fn write ( & mut self , addr : impl Into < Address > , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
513
+ self . prepare_write ( addr. into ( ) , bytes. len ( ) ) ?;
486
514
self . write_bytes ( bytes. iter ( ) . cloned ( ) ) ?;
487
515
488
516
self . end_transaction ( )
489
517
}
490
518
491
- pub fn write_read ( & mut self , addr : u8 , bytes : & [ u8 ] , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
492
- self . prepare_write ( addr, bytes. len ( ) as u8 ) ?;
519
+ pub fn write_read (
520
+ & mut self ,
521
+ addr : impl Into < Address > ,
522
+ bytes : & [ u8 ] ,
523
+ buffer : & mut [ u8 ] ,
524
+ ) -> Result < ( ) , Error > {
525
+ let addr = addr. into ( ) ;
526
+ self . prepare_write ( addr, bytes. len ( ) ) ?;
493
527
self . write_bytes ( bytes. iter ( ) . cloned ( ) ) ?;
494
528
495
529
// Wait until data was sent
@@ -502,7 +536,120 @@ impl<I2C: Instance> I2c<I2C> {
502
536
503
537
self . read ( addr, buffer)
504
538
}
539
+
540
+ pub fn transaction < ' a > (
541
+ & mut self ,
542
+ addr : impl Into < Address > ,
543
+ mut ops : impl Iterator < Item = Hal1Operation < ' a > > ,
544
+ ) -> Result < ( ) , Error > {
545
+ let addr = addr. into ( ) ;
546
+ if let Some ( mut prev_op) = ops. next ( ) {
547
+ // 1. Generate Start for operation
548
+ match & prev_op {
549
+ Hal1Operation :: Read ( buf) => self . prepare_read ( addr, buf. len ( ) , true ) ?,
550
+ Hal1Operation :: Write ( data) => self . prepare_write ( addr, data. len ( ) ) ?,
551
+ } ;
552
+
553
+ for op in ops {
554
+ // 2. Execute previous operations.
555
+ match & mut prev_op {
556
+ Hal1Operation :: Read ( rb) => self . read_bytes ( rb) ?,
557
+ Hal1Operation :: Write ( wb) => self . write_bytes ( wb. iter ( ) . cloned ( ) ) ?,
558
+ } ;
559
+ // 3. If operation changes type we must generate new start
560
+ match ( & prev_op, & op) {
561
+ ( Hal1Operation :: Read ( _) , Hal1Operation :: Write ( data) ) => {
562
+ self . prepare_write ( addr, data. len ( ) ) ?
563
+ }
564
+ ( Hal1Operation :: Write ( _) , Hal1Operation :: Read ( buf) ) => {
565
+ self . prepare_read ( addr, buf. len ( ) , false ) ?
566
+ }
567
+ _ => { } // No changes if operation have not changed
568
+ }
569
+
570
+ prev_op = op;
571
+ }
572
+
573
+ // 4. Now, prev_op is last command use methods variations that will generate stop
574
+ match prev_op {
575
+ Hal1Operation :: Read ( rb) => self . read_bytes ( rb) ?,
576
+ Hal1Operation :: Write ( wb) => self . write_bytes ( wb. iter ( ) . cloned ( ) ) ?,
577
+ } ;
578
+
579
+ self . end_transaction ( ) ?;
580
+ }
581
+
582
+ // Fallthrough is success
583
+ Ok ( ( ) )
584
+ }
585
+
586
+ pub fn transaction_slice (
587
+ & mut self ,
588
+ addr : impl Into < Address > ,
589
+ ops_slice : & mut [ Hal1Operation < ' _ > ] ,
590
+ ) -> Result < ( ) , Error > {
591
+ let addr = addr. into ( ) ;
592
+ transaction_impl ! ( self , addr, ops_slice, Hal1Operation ) ;
593
+ // Fallthrough is success
594
+ Ok ( ( ) )
595
+ }
596
+
597
+ fn transaction_slice_hal_02 (
598
+ & mut self ,
599
+ addr : impl Into < Address > ,
600
+ ops_slice : & mut [ Hal02Operation < ' _ > ] ,
601
+ ) -> Result < ( ) , Error > {
602
+ let addr = addr. into ( ) ;
603
+ transaction_impl ! ( self , addr, ops_slice, Hal02Operation ) ;
604
+ // Fallthrough is success
605
+ Ok ( ( ) )
606
+ }
607
+ }
608
+
609
+ macro_rules! transaction_impl {
610
+ ( $self: ident, $addr: ident, $ops_slice: ident, $Operation: ident) => {
611
+ let i2c = $self;
612
+ let addr = $addr;
613
+ let mut ops = $ops_slice. iter_mut( ) ;
614
+
615
+ if let Some ( mut prev_op) = ops. next( ) {
616
+ // 1. Generate Start for operation
617
+ match & prev_op {
618
+ $Operation:: Read ( buf) => i2c. prepare_read( addr, buf. len( ) , true ) ?,
619
+ $Operation:: Write ( data) => i2c. prepare_write( addr, data. len( ) ) ?,
620
+ } ;
621
+
622
+ for op in ops {
623
+ // 2. Execute previous operations.
624
+ match & mut prev_op {
625
+ $Operation:: Read ( rb) => i2c. read_bytes( rb) ?,
626
+ $Operation:: Write ( wb) => i2c. write_bytes( wb. iter( ) . cloned( ) ) ?,
627
+ } ;
628
+ // 3. If operation changes type we must generate new start
629
+ match ( & prev_op, & op) {
630
+ ( $Operation:: Read ( _) , $Operation:: Write ( data) ) => {
631
+ i2c. prepare_write( addr, data. len( ) ) ?
632
+ }
633
+ ( $Operation:: Write ( _) , $Operation:: Read ( buf) ) => {
634
+ i2c. prepare_read( addr, buf. len( ) , false ) ?
635
+ }
636
+ _ => { } // No changes if operation have not changed
637
+ }
638
+
639
+ prev_op = op;
640
+ }
641
+
642
+ // 4. Now, prev_op is last command use methods variations that will generate stop
643
+ match prev_op {
644
+ $Operation:: Read ( rb) => i2c. read_bytes( rb) ?,
645
+ $Operation:: Write ( wb) => i2c. write_bytes( wb. iter( ) . cloned( ) ) ?,
646
+ } ;
647
+
648
+ i2c. end_transaction( ) ?;
649
+ }
650
+ } ;
505
651
}
652
+ use transaction_impl;
506
653
507
654
// Note: implementation is from f0xx-hal
508
655
// TODO: check error handling. See https://github.com/stm32-rs/stm32f0xx-hal/pull/95/files
0 commit comments