@@ -8,42 +8,100 @@ use embassy_hal_internal::{into_ref, Peripheral};
8
8
9
9
use super :: {
10
10
Async , Blocking , Info , Instance , InterruptHandler , Mode , Result , SclPin , SdaPin , SlaveDma , TransferError ,
11
- I2C_WAKERS ,
11
+ I2C_WAKERS , TEN_BIT_PREFIX ,
12
12
} ;
13
13
use crate :: interrupt:: typelevel:: Interrupt ;
14
14
use crate :: pac:: i2c0:: stat:: Slvstate ;
15
15
use crate :: { dma, interrupt} ;
16
16
17
+ /// Address errors
18
+ #[ derive( Copy , Clone , Debug ) ]
19
+ pub enum AddressError {
20
+ /// Invalid address conversion
21
+ InvalidConversion ,
22
+ }
23
+
17
24
/// I2C address type
18
25
#[ derive( Copy , Clone , Debug ) ]
19
- pub struct Address ( u8 ) ;
26
+ pub enum Address {
27
+ /// 7-bit address
28
+ SevenBit ( u8 ) ,
29
+ /// 10-bit address
30
+ TenBit ( u16 ) ,
31
+ }
20
32
21
33
impl Address {
22
- /// Construct an address type
34
+ /// Construct a 7-bit address type
23
35
#[ must_use]
24
36
pub const fn new ( addr : u8 ) -> Option < Self > {
25
37
match addr {
26
- 0x08 ..=0x77 => Some ( Self ( addr) ) ,
38
+ 0x08 ..=0x77 => Some ( Self :: SevenBit ( addr) ) ,
39
+ _ => None ,
40
+ }
41
+ }
42
+
43
+ /// Construct a 10-bit address type
44
+ #[ must_use]
45
+ pub const fn new_10bit ( addr : u16 ) -> Option < Self > {
46
+ match addr {
47
+ 0x080 ..=0x3FF => Some ( Self :: TenBit ( addr) ) ,
27
48
_ => None ,
28
49
}
29
50
}
30
51
31
52
/// interpret address as a read command
32
53
#[ must_use]
33
- pub fn read ( & self ) -> u8 {
34
- ( self . 0 << 1 ) | 1
54
+ pub fn read ( & self ) -> [ u8 ; 2 ] {
55
+ match self {
56
+ Self :: SevenBit ( addr) => [ ( addr << 1 ) | 1 , 0 ] ,
57
+ Self :: TenBit ( addr) => [ ( ( ( addr >> 8 ) as u8 ) << 1 ) | TEN_BIT_PREFIX | 1 , ( addr & 0xFF ) as u8 ] ,
58
+ }
35
59
}
36
60
37
61
/// interpret address as a write command
38
62
#[ must_use]
39
- pub fn write ( & self ) -> u8 {
40
- self . 0 << 1
63
+ pub fn write ( & self ) -> [ u8 ; 2 ] {
64
+ match self {
65
+ Self :: SevenBit ( addr) => [ addr << 1 , 0 ] ,
66
+ Self :: TenBit ( addr) => [ ( ( ( addr >> 8 ) as u8 ) << 1 ) | TEN_BIT_PREFIX , ( addr & 0xFF ) as u8 ] ,
67
+ }
68
+ }
69
+ }
70
+
71
+ impl TryFrom < Address > for u8 {
72
+ type Error = AddressError ;
73
+
74
+ fn try_from ( value : Address ) -> core:: result:: Result < Self , Self :: Error > {
75
+ match value {
76
+ Address :: SevenBit ( addr) => Ok ( addr) ,
77
+ Address :: TenBit ( _) => Err ( AddressError :: InvalidConversion ) ,
78
+ }
41
79
}
42
80
}
43
81
44
- impl From < Address > for u8 {
45
- fn from ( value : Address ) -> Self {
46
- value. 0
82
+ impl TryFrom < Address > for u16 {
83
+ type Error = AddressError ;
84
+
85
+ fn try_from ( value : Address ) -> core:: result:: Result < Self , Self :: Error > {
86
+ match value {
87
+ Address :: SevenBit ( addr) => Ok ( addr as u16 ) ,
88
+ Address :: TenBit ( addr) => Ok ( addr) ,
89
+ }
90
+ }
91
+ }
92
+
93
+ #[ derive( Copy , Clone , Debug ) ]
94
+ struct TenBitAddressInfo {
95
+ first_byte : u8 ,
96
+ second_byte : u8 ,
97
+ }
98
+
99
+ impl TenBitAddressInfo {
100
+ fn new ( address : u16 ) -> Self {
101
+ Self {
102
+ first_byte : ( ( ( address >> 8 ) as u8 ) << 1 ) | TEN_BIT_PREFIX ,
103
+ second_byte : ( address & 0xFF ) as u8 ,
104
+ }
47
105
}
48
106
}
49
107
@@ -64,7 +122,7 @@ pub enum Response {
64
122
/// I2C transaction complete with this amount of bytes
65
123
Complete ( usize ) ,
66
124
67
- /// I2C transaction pending wutg this amount of bytes completed so far
125
+ /// I2C transaction pending with this amount of bytes completed so far
68
126
Pending ( usize ) ,
69
127
}
70
128
@@ -73,6 +131,7 @@ pub struct I2cSlave<'a, M: Mode> {
73
131
info : Info ,
74
132
_phantom : PhantomData < M > ,
75
133
dma_ch : Option < dma:: channel:: Channel < ' a > > ,
134
+ ten_bit_info : Option < TenBitAddressInfo > ,
76
135
}
77
136
78
137
impl < ' a , M : Mode > I2cSlave < ' a , M > {
@@ -95,6 +154,7 @@ impl<'a, M: Mode> I2cSlave<'a, M> {
95
154
// this check should be redundant with T::set_mode()? above
96
155
let info = T :: info ( ) ;
97
156
let i2c = info. regs ;
157
+ let mut ten_bit_info = None ;
98
158
99
159
// rates taken assuming SFRO:
100
160
//
@@ -111,11 +171,25 @@ impl<'a, M: Mode> I2cSlave<'a, M> {
111
171
// SAFETY: only unsafe due to .bits usage
112
172
unsafe { w. divval ( ) . bits ( 0 ) } ) ;
113
173
114
- // address 0 match = addr, per UM11147 24.3.2.1
115
- i2c. slvadr ( 0 ) . modify ( |_, w|
116
- // note: shift is omitted as performed via w.slvadr()
117
- // SAFETY: unsafe only required due to use of unnamed "bits" field
118
- unsafe { w. slvadr ( ) . bits ( address. 0 ) } . sadisable ( ) . enabled ( ) ) ;
174
+ match address {
175
+ Address :: SevenBit ( addr) => {
176
+ // address 0 match = addr, per UM11147 24.3.2.1
177
+ i2c. slvadr ( 0 ) . modify ( |_, w|
178
+ // note: shift is omitted as performed via w.slvadr()
179
+ // SAFETY: unsafe only required due to use of unnamed "bits" field
180
+ unsafe { w. slvadr ( ) . bits ( addr) } . sadisable ( ) . enabled ( ) ) ;
181
+ }
182
+ Address :: TenBit ( addr) => {
183
+ // Save the 10 bit address to use later
184
+ ten_bit_info = Some ( TenBitAddressInfo :: new ( addr) ) ;
185
+
186
+ // address 0 match = addr first byte, per UM11147 24.7.4
187
+ i2c. slvadr ( 0 ) . modify ( |_, w|
188
+ // note: byte needs to be adjusted for shift performed via w.slvadr()
189
+ // SAFETY: unsafe only required due to use of unnamed "bits" field
190
+ unsafe { w. slvadr ( ) . bits ( ten_bit_info. unwrap ( ) . first_byte >> 1 ) } . sadisable ( ) . enabled ( ) ) ;
191
+ }
192
+ }
119
193
120
194
// SLVEN = 1, per UM11147 24.3.2.1
121
195
i2c. cfg ( ) . write ( |w| w. slven ( ) . enabled ( ) ) ;
@@ -124,6 +198,7 @@ impl<'a, M: Mode> I2cSlave<'a, M> {
124
198
info,
125
199
_phantom : PhantomData ,
126
200
dma_ch,
201
+ ten_bit_info,
127
202
} )
128
203
}
129
204
}
@@ -336,6 +411,43 @@ impl I2cSlave<'_, Async> {
336
411
// Poll for HW to transitioning from addressed to receive/transmit
337
412
self . poll_sw_action ( ) . await ;
338
413
414
+ if let Some ( ten_bit_address) = self . ten_bit_info {
415
+ // For 10 bit address, the first byte received is the second byte of the address
416
+ if i2c. slvdat ( ) . read ( ) . data ( ) . bits ( ) == ten_bit_address. second_byte {
417
+ i2c. slvctl ( ) . write ( |w| w. slvcontinue ( ) . continue_ ( ) ) ;
418
+ self . poll_sw_action ( ) . await ;
419
+ } else {
420
+ // If the second byte of the 10 bit address is not received, then nack the address.
421
+ i2c. slvctl ( ) . write ( |w| w. slvnack ( ) . nack ( ) ) ;
422
+ return Ok ( Command :: Probe ) ;
423
+ }
424
+
425
+ // Check slave is still selected, master has not sent a stop
426
+ if i2c. stat ( ) . read ( ) . slvsel ( ) . is_selected ( ) {
427
+ // Check for a restart
428
+ if i2c. stat ( ) . read ( ) . slvstate ( ) . is_slave_address ( ) {
429
+ // Check if first byte of 10 bit address is received again with read bit set
430
+ if i2c. slvdat ( ) . read ( ) . data ( ) . bits ( ) == ten_bit_address. first_byte | 1 {
431
+ i2c. slvctl ( ) . write ( |w| w. slvcontinue ( ) . continue_ ( ) ) ;
432
+ self . poll_sw_action ( ) . await ;
433
+ } else {
434
+ // If the first byte of the 10 bit address is not received again, then nack the address.
435
+ i2c. slvctl ( ) . write ( |w| w. slvnack ( ) . nack ( ) ) ;
436
+ return Ok ( Command :: Probe ) ;
437
+ }
438
+ // Check slave is ready for transmit
439
+ if !i2c. stat ( ) . read ( ) . slvstate ( ) . is_slave_transmit ( ) {
440
+ return Err ( TransferError :: WriteFail . into ( ) ) ;
441
+ }
442
+ } else {
443
+ // Check slave is ready to receive
444
+ if !i2c. stat ( ) . read ( ) . slvstate ( ) . is_slave_receive ( ) {
445
+ return Err ( TransferError :: ReadFail . into ( ) ) ;
446
+ }
447
+ }
448
+ }
449
+ }
450
+
339
451
// We are deselected, so it must be an 0 byte write transaction
340
452
if i2c. stat ( ) . read ( ) . slvdesel ( ) . is_deselected ( ) {
341
453
// Clear the deselected bit
0 commit comments