2
2
//! [stm32h7xx-hal](https://github.com/stm32-rs/stm32h7xx-hal) implementation,
3
3
//! as of 2021-02-25.
4
4
5
- use crate :: gpio:: { Alternate , OpenDrain , Output , AF4 } ;
6
5
use crate :: hal:: blocking:: i2c:: { Read , Write , WriteRead } ;
7
- use crate :: pac:: { i2c1, I2C1 , I2C2 } ;
6
+ #[ cfg( any( feature = "stm32l4x1" , feature = "stm32l4x2" , feature = "stm32l4x6" ) ) ]
7
+ use crate :: pac:: I2C4 ;
8
+ use crate :: pac:: { i2c1, I2C1 , I2C2 , I2C3 } ;
9
+
8
10
use crate :: rcc:: { Clocks , APB1R1 } ;
9
- #[ cfg( any( feature = "stm32l4x5" , feature = "stm32l4x6" ) ) ]
10
- use crate :: stm32:: I2C3 ;
11
11
use crate :: time:: Hertz ;
12
12
use cast:: { u16, u8} ;
13
13
use core:: ops:: Deref ;
@@ -31,7 +31,7 @@ pub enum Error {
31
31
}
32
32
33
33
#[ doc( hidden) ]
34
- mod private {
34
+ pub ( self ) mod private {
35
35
pub trait Sealed { }
36
36
}
37
37
@@ -44,12 +44,12 @@ pub trait SdaPin<I2C>: private::Sealed {}
44
44
macro_rules! pins {
45
45
( $spi: ident, $af: ident, SCL : [ $( $scl: ident) ,* ] , SDA : [ $( $sda: ident) ,* ] ) => {
46
46
$(
47
- impl private:: Sealed for $scl<Alternate <$af, Output <OpenDrain >>> { }
48
- impl SclPin <$spi> for $scl<Alternate <$af, Output <OpenDrain >>> { }
47
+ impl super :: private:: Sealed for $scl<Alternate <$af, Output <OpenDrain >>> { }
48
+ impl super :: SclPin <$spi> for $scl<Alternate <$af, Output <OpenDrain >>> { }
49
49
) *
50
50
$(
51
- impl private:: Sealed for $sda<Alternate <$af, Output <OpenDrain >>> { }
52
- impl SdaPin <$spi> for $sda<Alternate <$af, Output <OpenDrain >>> { }
51
+ impl super :: private:: Sealed for $sda<Alternate <$af, Output <OpenDrain >>> { }
52
+ impl super :: SdaPin <$spi> for $sda<Alternate <$af, Output <OpenDrain >>> { }
53
53
) *
54
54
}
55
55
}
@@ -60,6 +60,8 @@ pub struct I2c<I2C, PINS> {
60
60
pins : PINS ,
61
61
}
62
62
63
+ // TODO review why StartCondition and State structs exists. Last
64
+ // update to them was november 2020
63
65
/// Start conditions that govern repeated sequential transfer
64
66
#[ derive( Debug , Clone ) ]
65
67
enum StartCondition {
@@ -119,48 +121,40 @@ impl State {
119
121
}
120
122
}
121
123
122
- impl < SCL , SDA > I2c < I2C1 , ( SCL , SDA ) > {
123
- pub fn i2c1 < F > ( i2c : I2C1 , pins : ( SCL , SDA ) , freq : F , clocks : Clocks , apb1 : & mut APB1R1 ) -> Self
124
- where
125
- F : Into < Hertz > ,
126
- SCL : SclPin < I2C1 > ,
127
- SDA : SdaPin < I2C1 > ,
128
- {
129
- apb1. enr ( ) . modify ( |_, w| w. i2c1en ( ) . set_bit ( ) ) ;
130
- apb1. rstr ( ) . modify ( |_, w| w. i2c1rst ( ) . set_bit ( ) ) ;
131
- apb1. rstr ( ) . modify ( |_, w| w. i2c1rst ( ) . clear_bit ( ) ) ;
132
- Self :: new ( i2c, pins, freq, clocks)
133
- }
124
+ macro_rules! hal {
125
+ ( $i2c_type: ident, $enr: ident, $rstr: ident, $i2cX: ident, $i2cXen: ident, $i2cXrst: ident) => {
126
+ impl <SCL , SDA > I2c <$i2c_type, ( SCL , SDA ) > {
127
+ pub fn $i2cX<F >(
128
+ i2c: $i2c_type,
129
+ pins: ( SCL , SDA ) ,
130
+ freq: F ,
131
+ clocks: Clocks ,
132
+ apb1: & mut APB1R1 ,
133
+ ) -> Self
134
+ where
135
+ F : Into <Hertz >,
136
+ SCL : SclPin <$i2c_type>,
137
+ SDA : SdaPin <$i2c_type>,
138
+ {
139
+ apb1. $enr( ) . modify( |_, w| w. $i2cXen( ) . set_bit( ) ) ;
140
+ apb1. $rstr( ) . modify( |_, w| w. $i2cXrst( ) . set_bit( ) ) ;
141
+ apb1. $rstr( ) . modify( |_, w| w. $i2cXrst( ) . clear_bit( ) ) ;
142
+ Self :: new( i2c, pins, freq, clocks)
143
+ }
144
+ }
145
+ } ;
134
146
}
135
147
136
- impl < SCL , SDA > I2c < I2C2 , ( SCL , SDA ) > {
137
- pub fn i2c2 < F > ( i2c : I2C2 , pins : ( SCL , SDA ) , freq : F , clocks : Clocks , apb1 : & mut APB1R1 ) -> Self
138
- where
139
- F : Into < Hertz > ,
140
- SCL : SclPin < I2C2 > ,
141
- SDA : SdaPin < I2C2 > ,
142
- {
143
- apb1. enr ( ) . modify ( |_, w| w. i2c2en ( ) . set_bit ( ) ) ;
144
- apb1. rstr ( ) . modify ( |_, w| w. i2c2rst ( ) . set_bit ( ) ) ;
145
- apb1. rstr ( ) . modify ( |_, w| w. i2c2rst ( ) . clear_bit ( ) ) ;
146
- Self :: new ( i2c, pins, freq, clocks)
147
- }
148
- }
148
+ hal ! ( I2C1 , enr, rstr, i2c1, i2c1en, i2c1rst) ;
149
+ hal ! ( I2C2 , enr, rstr, i2c2, i2c2en, i2c2rst) ;
150
+ hal ! ( I2C3 , enr, rstr, i2c3, i2c3en, i2c3rst) ;
149
151
150
- #[ cfg( any( feature = "stm32l4x5" , feature = "stm32l4x6" ) ) ]
151
- impl < SCL , SDA > I2c < I2C3 , ( SCL , SDA ) > {
152
- pub fn i2c3 < F > ( i2c : I2C3 , pins : ( SCL , SDA ) , freq : F , clocks : Clocks , apb1 : & mut APB1R1 ) -> Self
153
- where
154
- F : Into < Hertz > ,
155
- SCL : SclPin < I2C3 > ,
156
- SDA : SdaPin < I2C3 > ,
157
- {
158
- apb1. enr ( ) . modify ( |_, w| w. i2c3en ( ) . set_bit ( ) ) ;
159
- apb1. rstr ( ) . modify ( |_, w| w. i2c3rst ( ) . set_bit ( ) ) ;
160
- apb1. rstr ( ) . modify ( |_, w| w. i2c3rst ( ) . clear_bit ( ) ) ;
161
- Self :: new ( i2c, pins, freq, clocks)
162
- }
163
- }
152
+ // This peripheral is not present on
153
+ // STM32L471XX and STM32L431XX
154
+ // STM32L432XX and STM32l442XX
155
+ // STM32L486XX and STM32L476XX
156
+ #[ cfg( any( feature = "stm32l4x1" , feature = "stm32l4x2" , feature = "stm32l4x6" ) ) ]
157
+ hal ! ( I2C4 , enr2, rstr2, i2c4, i2c4en, i2c4rst) ;
164
158
165
159
impl < SCL , SDA , I2C > I2c < I2C , ( SCL , SDA ) >
166
160
where
@@ -225,14 +219,26 @@ where
225
219
( presc, scll, sclh, sdadel, scldel)
226
220
} ;
227
221
228
- let presc = u8 ( presc) . unwrap ( ) ;
222
+ macro_rules! u8_or_panic {
223
+ ( $value: expr, $message: literal) => {
224
+ match u8 ( $value) {
225
+ Ok ( value) => value,
226
+ Err ( _) => panic!( $message) ,
227
+ }
228
+ } ;
229
+ }
230
+
231
+ let presc = u8_or_panic ! ( presc, "I2C pres" ) ;
229
232
assert ! ( presc < 16 ) ;
230
- let scldel = u8 ( scldel) . unwrap ( ) ;
233
+
234
+ let scldel = u8_or_panic ! ( scldel, "I2C scldel" ) ;
231
235
assert ! ( scldel < 16 ) ;
232
- let sdadel = u8 ( sdadel) . unwrap ( ) ;
236
+
237
+ let sdadel = u8_or_panic ! ( sdadel, "I2C sdadel" ) ;
233
238
assert ! ( sdadel < 16 ) ;
234
- let sclh = u8 ( sclh) . unwrap ( ) ;
235
- let scll = u8 ( scll) . unwrap ( ) ;
239
+
240
+ let sclh = u8_or_panic ! ( sclh, "I2C sclh" ) ;
241
+ let scll = u8_or_panic ! ( scll, "I2C scll" ) ;
236
242
237
243
// Configure for "fast mode" (400 KHz)
238
244
i2c. timingr . write ( |w| {
@@ -472,35 +478,110 @@ where
472
478
}
473
479
}
474
480
475
- use crate :: gpio:: gpioa:: { PA10 , PA9 } ;
476
- use crate :: gpio:: gpiob:: { PB10 , PB11 , PB6 , PB7 } ;
481
+ #[ cfg( feature = "stm32l4x1" ) ]
482
+ mod stm32l4x1_pins {
483
+ use super :: { I2C1 , I2C2 , I2C3 , I2C4 } ;
484
+ use crate :: gpio:: * ;
485
+ use gpioa:: { PA10 , PA7 , PA9 } ;
486
+ use gpiob:: { PB10 , PB11 , PB13 , PB14 , PB4 , PB6 , PB7 , PB8 , PB9 } ;
487
+ use gpioc:: { PC0 , PC1 } ;
477
488
478
- #[ cfg( any( feature = "stm32l4x3" , feature = "stm32l4x5" , feature = "stm32l4x6" ) ) ]
479
- use crate :: gpio:: gpioc:: { PC0 , PC1 } ;
489
+ pins ! ( I2C1 , AF4 , SCL : [ PB6 , PB8 ] , SDA : [ PB7 , PB9 ] ) ;
480
490
481
- # [ cfg ( any ( feature = "stm32l4x1" , feature = "stm32l4x3" , feature = "stm32l4x6" ) ) ]
482
- use crate :: gpio :: gpiob :: PB8 ;
491
+ // Not on STM32L471XX
492
+ pins ! ( I2C1 , AF4 , SCL : [ PA9 ] , SDA : [ PA10 ] ) ;
483
493
484
- #[ cfg( any( feature = "stm32l4x1" , feature = "stm32l4x6" ) ) ]
485
- use crate :: gpio:: gpiob:: { PB13 , PB14 , PB9 } ;
494
+ pins ! ( I2C2 , AF4 , SCL : [ PB10 , PB13 ] , SDA : [ PB11 , PB14 ] ) ;
486
495
487
- pins ! ( I2C1 , AF4 ,
488
- SCL : [ PA9 , PB6 ] ,
489
- SDA : [ PA10 , PB7 ] ) ;
496
+ pins ! ( I2C3 , AF4 , SCL : [ PC0 ] , SDA : [ PC1 ] ) ;
490
497
491
- pins ! ( I2C2 , AF4 , SCL : [ PB10 ] , SDA : [ PB11 ] ) ;
498
+ // Not on STM32L471XX
499
+ pins ! ( I2C3 , AF4 , SCL : [ PA7 ] , SDA : [ PB4 ] ) ;
492
500
493
- #[ cfg( any( feature = "stm32l4x1" , feature = "stm32l4x6" ) ) ]
494
- pins ! ( I2C1 , AF4 , SCL : [ PB8 ] , SDA : [ PB9 ] ) ;
501
+ // Not on STM32L471XX and STM32L431XX
502
+ pins ! ( I2C4 , AF4 , SCL : [ PD12 ] , SDA : [ PD13 ] ) ;
503
+ pins ! ( I2C4 , AF3 , SCL : [ PB10 ] , SDA : [ PB11 ] ) ;
504
+ }
495
505
496
- #[ cfg( any( feature = "stm32l4x1" , feature = "stm32l4x6" ) ) ]
497
- pins ! ( I2C2 , AF4 , SCL : [ PB13 ] , SDA : [ PB14 ] ) ;
506
+ #[ cfg( feature = "stm32l4x2" ) ]
507
+ mod stm32l4x2_pins {
508
+ use super :: { I2C1 , I2C2 , I2C3 , I2C4 } ;
509
+ use crate :: gpio:: * ;
510
+ use gpioa:: { PA10 , PA7 , PA9 } ;
511
+ use gpiob:: { PB10 , PB11 , PB13 , PB14 , PB4 , PB6 , PB7 , PB8 , PB9 } ;
512
+ use gpioc:: { PC0 , PC1 } ;
498
513
499
- #[ cfg( any( feature = "stm32l4x5" , feature = "stm32l4x6" ) ) ]
500
- pins ! ( I2C3 , AF4 , SCL : [ PC0 ] , SDA : [ PC1 ] ) ;
514
+ pins ! ( I2C1 , AF4 , SCL : [ PA9 , PB6 ] , SDA : [ PA10 , PB7 ] ) ;
501
515
502
- #[ cfg( feature = "stm32l4x3" ) ]
503
- pins ! ( I2C1 , AF4 , SCL : [ PB8 ] , SDA : [ ] ) ;
516
+ // Technically not present on STM32L432XX and STM32l442XX (pins missing from ref. manual)
517
+ pins ! ( I2C2 , AF4 , SCL : [ PB8 , PB10 , PB13 ] , SDA : [ PB9 , PB11 , PB14 ] ) ;
518
+
519
+ pins ! ( I2C3 , AF4 , SCL : [ PA7 ] , SDA : [ PB4 ] ) ;
520
+
521
+ // Technically not present on STM32L432XX and STM32l442XX (pins missing from ref. manual)
522
+ pins ! ( I2C3 , AF4 , SCL : [ PC0 ] , SDA : [ PC1 ] ) ;
523
+
524
+ // Technically not present on STM32L432XX and STM32l442XX (pins missing from ref. manual)
525
+ // Not present on STM32L412XX and STM32L422XX
526
+ pins ! ( I2C4 , AF2 , SCL : [ PC0 ] , SDA : [ PC1 ] ) ;
527
+ pins ! ( I2C4 , AF3 , SCL : [ PB10 ] , SDA : [ PB11 ] ) ;
528
+ pins ! ( I2C4 , AF4 , SCL : [ PD12 ] , SDA : [ PD13 ] ) ;
529
+ }
504
530
505
531
#[ cfg( feature = "stm32l4x3" ) ]
506
- pins ! ( I2C2 , AF4 , SCL : [ PC0 ] , SDA : [ PC1 ] ) ;
532
+ mod stm32l4x3_pins {
533
+ use super :: { I2C1 , I2C2 , I2C3 } ;
534
+ use crate :: gpio:: * ;
535
+ use gpioa:: { PA10 , PA7 , PA9 } ;
536
+ use gpiob:: { PB10 , PB11 , PB13 , PB14 , PB4 , PB6 , PB7 , PB8 , PB9 } ;
537
+ use gpioc:: { PC0 , PC1 } ;
538
+
539
+ pins ! ( I2C1 , AF4 , SCL : [ PA9 , PB6 , PB8 ] , SDA : [ PA10 , PB7 , PB9 ] ) ;
540
+
541
+ pins ! ( I2C2 , AF4 , SCL : [ PB10 , PB13 ] , SDA : [ PB11 , PB14 ] ) ;
542
+
543
+ pins ! ( I2C3 , AF4 , SCL : [ PA7 , PC0 ] , SDA : [ PB4 , PC1 ] ) ;
544
+ }
545
+
546
+ #[ cfg( feature = "stm32l4x5" ) ]
547
+ mod stm32l4x5_pins {
548
+ use super :: { I2C1 , I2C2 , I2C3 } ;
549
+ use crate :: gpio:: * ;
550
+ use gpiob:: { PB10 , PB11 , PB13 , PB14 , PB6 , PB7 , PB8 , PB9 } ;
551
+ use gpioc:: { PC0 , PC1 } ;
552
+
553
+ pins ! ( I2C1 , AF4 , SCL : [ PB6 , PB8 ] , SDA : [ PB7 , PB9 ] ) ;
554
+
555
+ pins ! ( I2C2 , AF4 , SCL : [ PB10 , PB13 ] , SDA : [ PB11 , PB14 ] ) ;
556
+
557
+ pins ! ( I2C3 , AF4 , SCL : [ PC0 ] , SDA : [ PC1 ] ) ;
558
+ }
559
+
560
+ #[ cfg( feature = "stm32l4x6" ) ]
561
+ mod stm32l4x6_pins {
562
+ use super :: { I2C1 , I2C2 , I2C3 , I2C4 } ;
563
+ use crate :: gpio:: * ;
564
+ use gpioa:: PA7 ;
565
+ use gpiob:: { PB10 , PB11 , PB13 , PB14 , PB4 , PB6 , PB7 , PB8 , PB9 } ;
566
+ use gpioc:: { PC0 , PC1 } ;
567
+ use gpiod:: { PD12 , PD13 } ;
568
+ use gpiof:: { PF0 , PF1 , PF14 , PF15 } ;
569
+ use gpiog:: { PG13 , PG14 , PG7 , PG8 } ;
570
+
571
+ pins ! ( I2C1 , AF4 , SCL : [ PB6 , PB8 ] , SDA : [ PB7 , PB9 ] ) ;
572
+
573
+ pins ! ( I2C2 , AF4 , SCL : [ PB10 , PB13 , PF1 ] , SDA : [ PB11 , PB14 , PF0 ] ) ;
574
+
575
+ pins ! ( I2C3 , AF4 , SCL : [ PC0 , PG7 , PG14 ] , SDA : [ PC1 , PG8 , PG13 ] ) ;
576
+
577
+ // Both not on STM32L486XX and STM32L476XX
578
+ pins ! ( I2C3 , AF4 , SCL : [ PA7 ] , SDA : [ PB4 ] ) ;
579
+ pins ! ( I2C4 , AF4 , SCL : [ PD12 , PF14 ] , SDA : [ PD13 , PF15 ] ) ;
580
+
581
+ // These are present on STM32L496XX and STM32L4A6xG, but the
582
+ // PAC does not have gpioh, so we can't actually these pins
583
+ // Both not on STM32L486XX and STM32L476XX
584
+ // use gpioh::{PH4, PH5, PH7, PH8};
585
+ // pins!(I2C2, AF4, SCL: [PH4], SDA: [PH5]);
586
+ // pins!(I2C3, AF4, SCL: [PH7], SDA: [PH8]);
587
+ }
0 commit comments