@@ -8,9 +8,13 @@ use crate::gpio;
8
8
use crate :: rcc:: Clocks ;
9
9
use fugit:: { HertzU32 as Hertz , RateExtU32 } ;
10
10
11
+ mod common;
11
12
mod hal_02;
12
13
mod hal_1;
13
14
15
+ pub use common:: { Address , Error , NoAcknowledgeSource } ;
16
+ use common:: { Hal02Operation , Hal1Operation } ;
17
+
14
18
pub mod dma;
15
19
16
20
#[ derive( Debug , Eq , PartialEq ) ]
@@ -70,39 +74,6 @@ pub struct I2c<I2C: Instance> {
70
74
pins : ( I2C :: Scl , I2C :: Sda ) ,
71
75
}
72
76
73
- pub use embedded_hal:: i2c:: NoAcknowledgeSource ;
74
-
75
- #[ derive( Debug , Eq , PartialEq , Copy , Clone ) ]
76
- #[ non_exhaustive]
77
- pub enum Error {
78
- Overrun ,
79
- NoAcknowledge ( NoAcknowledgeSource ) ,
80
- Timeout ,
81
- // Note: The Bus error type is not currently returned, but is maintained for compatibility.
82
- Bus ,
83
- Crc ,
84
- ArbitrationLoss ,
85
- }
86
-
87
- impl Error {
88
- pub ( crate ) fn nack_addr ( self ) -> Self {
89
- match self {
90
- Error :: NoAcknowledge ( NoAcknowledgeSource :: Unknown ) => {
91
- Error :: NoAcknowledge ( NoAcknowledgeSource :: Address )
92
- }
93
- e => e,
94
- }
95
- }
96
- pub ( crate ) fn nack_data ( self ) -> Self {
97
- match self {
98
- Error :: NoAcknowledge ( NoAcknowledgeSource :: Unknown ) => {
99
- Error :: NoAcknowledge ( NoAcknowledgeSource :: Data )
100
- }
101
- e => e,
102
- }
103
- }
104
- }
105
-
106
77
pub trait Instance :
107
78
crate :: Sealed
108
79
+ crate :: Ptr < RB = i2c1:: RegisterBlock >
@@ -155,10 +126,7 @@ impl<I2C: Instance> I2cExt for I2C {
155
126
}
156
127
}
157
128
158
- impl < I2C > I2c < I2C >
159
- where
160
- I2C : Instance ,
161
- {
129
+ impl < I2C : Instance > I2c < I2C > {
162
130
pub fn new (
163
131
i2c : I2C ,
164
132
pins : ( impl Into < I2C :: Scl > , impl Into < I2C :: Sda > ) ,
@@ -287,7 +255,7 @@ impl<I2C: Instance> I2c<I2C> {
287
255
288
256
/// Sends START and Address for writing
289
257
#[ inline( always) ]
290
- fn prepare_write ( & self , addr : u8 ) -> Result < ( ) , Error > {
258
+ fn prepare_write ( & self , addr : Address ) -> Result < ( ) , Error > {
291
259
// Wait until a previous STOP condition finishes. When the previous
292
260
// STOP was generated inside an ISR (e.g. DMA interrupt handler),
293
261
// the ISR returns without waiting for the STOP condition to finish.
@@ -313,9 +281,20 @@ impl<I2C: Instance> I2c<I2C> {
313
281
}
314
282
315
283
// Set up current address, we're trying to talk to
316
- self . i2c
317
- . dr ( )
318
- . write ( |w| unsafe { w. bits ( u32:: from ( addr) << 1 ) } ) ;
284
+ match addr {
285
+ Address :: Seven ( addr) => {
286
+ self . i2c
287
+ . dr ( )
288
+ . write ( |w| unsafe { w. bits ( u32:: from ( addr) << 1 ) } ) ;
289
+ }
290
+ Address :: Ten ( addr) => {
291
+ let [ msbs, lsbs] = addr. to_be_bytes ( ) ;
292
+ let msbs = ( ( msbs & 0b11 ) << 1 ) & 0b11110000 ;
293
+ let dr = self . i2c . dr ( ) ;
294
+ dr. write ( |w| unsafe { w. bits ( u32:: from ( msbs) ) } ) ;
295
+ dr. write ( |w| unsafe { w. bits ( u32:: from ( lsbs) ) } ) ;
296
+ }
297
+ }
319
298
320
299
// Wait until address was sent
321
300
loop {
@@ -337,7 +316,7 @@ impl<I2C: Instance> I2c<I2C> {
337
316
}
338
317
339
318
/// Sends START and Address for reading
340
- fn prepare_read ( & self , addr : u8 ) -> Result < ( ) , Error > {
319
+ fn prepare_read ( & self , addr : Address , first_transaction : bool ) -> Result < ( ) , Error > {
341
320
// Wait until a previous STOP condition finishes. When the previous
342
321
// STOP was generated inside an ISR (e.g. DMA interrupt handler),
343
322
// the ISR returns without waiting for the STOP condition to finish.
@@ -361,9 +340,26 @@ impl<I2C: Instance> I2c<I2C> {
361
340
} { }
362
341
363
342
// Set up current address, we're trying to talk to
364
- self . i2c
365
- . dr ( )
366
- . write ( |w| unsafe { w. bits ( ( u32:: from ( addr) << 1 ) + 1 ) } ) ;
343
+ match addr {
344
+ Address :: Seven ( addr) => {
345
+ self . i2c
346
+ . dr ( )
347
+ . write ( |w| unsafe { w. bits ( ( u32:: from ( addr) << 1 ) & 1 ) } ) ;
348
+ }
349
+ Address :: Ten ( addr) => {
350
+ let [ msbs, lsbs] = addr. to_be_bytes ( ) ;
351
+ let msbs = ( ( msbs & 0b11 ) << 1 ) & 0b11110000 ;
352
+ let dr = self . i2c . dr ( ) ;
353
+ if first_transaction {
354
+ dr. write ( |w| unsafe { w. bits ( u32:: from ( msbs) ) } ) ;
355
+ dr. write ( |w| unsafe { w. bits ( u32:: from ( lsbs) ) } ) ;
356
+ }
357
+ self . i2c . cr1 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
358
+ // Wait until START condition was generated
359
+ while self . i2c . sr1 ( ) . read ( ) . sb ( ) . bit_is_clear ( ) { }
360
+ dr. write ( |w| unsafe { w. bits ( u32:: from ( msbs & 1 ) ) } ) ;
361
+ }
362
+ }
367
363
368
364
// Wait until address was sent
369
365
loop {
@@ -439,12 +435,22 @@ impl<I2C: Instance> I2c<I2C> {
439
435
Ok ( ( ) )
440
436
}
441
437
442
- pub fn read ( & mut self , addr : u8 , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
438
+ pub fn read ( & mut self , addr : impl Into < Address > , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
439
+ self . read_inner ( addr. into ( ) , buffer, true )
440
+ }
441
+
442
+ #[ inline( always) ]
443
+ fn read_inner (
444
+ & mut self ,
445
+ addr : Address ,
446
+ buffer : & mut [ u8 ] ,
447
+ first_transaction : bool ,
448
+ ) -> Result < ( ) , Error > {
443
449
if buffer. is_empty ( ) {
444
450
return Err ( Error :: Overrun ) ;
445
451
}
446
452
447
- self . prepare_read ( addr) ?;
453
+ self . prepare_read ( addr. into ( ) , first_transaction ) ?;
448
454
self . read_wo_prepare ( buffer)
449
455
}
450
456
@@ -476,8 +482,8 @@ impl<I2C: Instance> I2c<I2C> {
476
482
}
477
483
}
478
484
479
- pub fn write ( & mut self , addr : u8 , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
480
- self . prepare_write ( addr) ?;
485
+ pub fn write ( & mut self , addr : impl Into < Address > , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
486
+ self . prepare_write ( addr. into ( ) ) ?;
481
487
self . write_wo_prepare ( bytes)
482
488
}
483
489
@@ -499,11 +505,11 @@ impl<I2C: Instance> I2c<I2C> {
499
505
Ok ( ( ) )
500
506
}
501
507
502
- pub fn write_iter < B > ( & mut self , addr : u8 , bytes : B ) -> Result < ( ) , Error >
508
+ pub fn write_iter < B > ( & mut self , addr : impl Into < Address > , bytes : B ) -> Result < ( ) , Error >
503
509
where
504
510
B : IntoIterator < Item = u8 > ,
505
511
{
506
- self . prepare_write ( addr) ?;
512
+ self . prepare_write ( addr. into ( ) ) ?;
507
513
self . write_bytes ( bytes. into_iter ( ) ) ?;
508
514
509
515
// Send a STOP condition
@@ -520,30 +526,43 @@ impl<I2C: Instance> I2c<I2C> {
520
526
Ok ( ( ) )
521
527
}
522
528
523
- pub fn write_read ( & mut self , addr : u8 , bytes : & [ u8 ] , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
529
+ pub fn write_read (
530
+ & mut self ,
531
+ addr : impl Into < Address > ,
532
+ bytes : & [ u8 ] ,
533
+ buffer : & mut [ u8 ] ,
534
+ ) -> Result < ( ) , Error > {
535
+ let addr = addr. into ( ) ;
524
536
self . prepare_write ( addr) ?;
525
537
self . write_bytes ( bytes. iter ( ) . cloned ( ) ) ?;
526
- self . read ( addr, buffer)
538
+ self . read_inner ( addr, buffer, false )
527
539
}
528
540
529
- pub fn write_iter_read < B > ( & mut self , addr : u8 , bytes : B , buffer : & mut [ u8 ] ) -> Result < ( ) , Error >
541
+ pub fn write_iter_read < B > (
542
+ & mut self ,
543
+ addr : impl Into < Address > ,
544
+ bytes : B ,
545
+ buffer : & mut [ u8 ] ,
546
+ ) -> Result < ( ) , Error >
530
547
where
531
548
B : IntoIterator < Item = u8 > ,
532
549
{
550
+ let addr = addr. into ( ) ;
533
551
self . prepare_write ( addr) ?;
534
552
self . write_bytes ( bytes. into_iter ( ) ) ?;
535
- self . read ( addr, buffer)
553
+ self . read_inner ( addr, buffer, false )
536
554
}
537
555
538
556
pub fn transaction < ' a > (
539
557
& mut self ,
540
- addr : u8 ,
558
+ addr : impl Into < Address > ,
541
559
mut ops : impl Iterator < Item = Hal1Operation < ' a > > ,
542
560
) -> Result < ( ) , Error > {
561
+ let addr = addr. into ( ) ;
543
562
if let Some ( mut prev_op) = ops. next ( ) {
544
563
// 1. Generate Start for operation
545
564
match & prev_op {
546
- Hal1Operation :: Read ( _) => self . prepare_read ( addr) ?,
565
+ Hal1Operation :: Read ( _) => self . prepare_read ( addr, true ) ?,
547
566
Hal1Operation :: Write ( _) => self . prepare_write ( addr) ?,
548
567
} ;
549
568
@@ -558,7 +577,9 @@ impl<I2C: Instance> I2c<I2C> {
558
577
( Hal1Operation :: Read ( _) , Hal1Operation :: Write ( _) ) => {
559
578
self . prepare_write ( addr) ?
560
579
}
561
- ( Hal1Operation :: Write ( _) , Hal1Operation :: Read ( _) ) => self . prepare_read ( addr) ?,
580
+ ( Hal1Operation :: Write ( _) , Hal1Operation :: Read ( _) ) => {
581
+ self . prepare_read ( addr, false ) ?
582
+ }
562
583
_ => { } // No changes if operation have not changed
563
584
}
564
585
@@ -578,19 +599,21 @@ impl<I2C: Instance> I2c<I2C> {
578
599
579
600
pub fn transaction_slice (
580
601
& mut self ,
581
- addr : u8 ,
602
+ addr : impl Into < Address > ,
582
603
ops_slice : & mut [ Hal1Operation < ' _ > ] ,
583
604
) -> Result < ( ) , Error > {
605
+ let addr = addr. into ( ) ;
584
606
transaction_impl ! ( self , addr, ops_slice, Hal1Operation ) ;
585
607
// Fallthrough is success
586
608
Ok ( ( ) )
587
609
}
588
610
589
611
fn transaction_slice_hal_02 (
590
612
& mut self ,
591
- addr : u8 ,
613
+ addr : impl Into < Address > ,
592
614
ops_slice : & mut [ Hal02Operation < ' _ > ] ,
593
615
) -> Result < ( ) , Error > {
616
+ let addr = addr. into ( ) ;
594
617
transaction_impl ! ( self , addr, ops_slice, Hal02Operation ) ;
595
618
// Fallthrough is success
596
619
Ok ( ( ) )
@@ -606,7 +629,7 @@ macro_rules! transaction_impl {
606
629
if let Some ( mut prev_op) = ops. next( ) {
607
630
// 1. Generate Start for operation
608
631
match & prev_op {
609
- $Operation:: Read ( _) => i2c. prepare_read( addr) ?,
632
+ $Operation:: Read ( _) => i2c. prepare_read( addr, true ) ?,
610
633
$Operation:: Write ( _) => i2c. prepare_write( addr) ?,
611
634
} ;
612
635
@@ -619,7 +642,7 @@ macro_rules! transaction_impl {
619
642
// 3. If operation changes type we must generate new start
620
643
match ( & prev_op, & op) {
621
644
( $Operation:: Read ( _) , $Operation:: Write ( _) ) => i2c. prepare_write( addr) ?,
622
- ( $Operation:: Write ( _) , $Operation:: Read ( _) ) => i2c. prepare_read( addr) ?,
645
+ ( $Operation:: Write ( _) , $Operation:: Read ( _) ) => i2c. prepare_read( addr, false ) ?,
623
646
_ => { } // No changes if operation have not changed
624
647
}
625
648
@@ -635,6 +658,3 @@ macro_rules! transaction_impl {
635
658
} ;
636
659
}
637
660
use transaction_impl;
638
-
639
- type Hal1Operation < ' a > = embedded_hal:: i2c:: Operation < ' a > ;
640
- type Hal02Operation < ' a > = embedded_hal_02:: blocking:: i2c:: Operation < ' a > ;
0 commit comments