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 } ;
7
7
use crate :: rcc:: { BusClock , Enable , Reset } ;
8
8
use fugit:: { HertzU32 as Hertz , RateExtU32 } ;
9
9
10
+ #[ path = "i2c/common.rs" ]
11
+ mod common;
12
+ pub use common:: { Address , Error , NoAcknowledgeSource } ;
13
+ use common:: { Hal02Operation , Hal1Operation } ;
14
+
10
15
// Old names
11
16
pub use I2c as FmpI2c ;
12
17
pub use Mode as FmpMode ;
13
18
19
+ #[ path = "i2c/hal_02.rs" ]
14
20
mod hal_02;
21
+ #[ path = "i2c/hal_1.rs" ]
15
22
mod hal_1;
16
23
17
24
pub trait Instance :
@@ -213,6 +220,83 @@ impl<I2C: Instance> I2c<I2C> {
213
220
Ok ( ( ) )
214
221
}
215
222
223
+ /// Sends START and Address for writing
224
+ #[ inline( always) ]
225
+ fn prepare_write ( & self , addr : Address , datalen : usize ) -> Result < ( ) , Error > {
226
+ // Set up current slave address for writing and disable autoending
227
+ self . i2c . cr2 ( ) . modify ( |_, w| {
228
+ match addr {
229
+ Address :: Seven ( addr) => {
230
+ w. add10 ( ) . clear_bit ( ) ;
231
+ w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
232
+ }
233
+ Address :: Ten ( addr) => {
234
+ w. add10 ( ) . set_bit ( ) ;
235
+ w. sadd ( ) . set ( addr) ;
236
+ }
237
+ }
238
+ w. nbytes ( ) . set ( datalen as u8 ) ;
239
+ w. rd_wrn ( ) . clear_bit ( ) ;
240
+ w. autoend ( ) . clear_bit ( )
241
+ } ) ;
242
+
243
+ // Send a START condition
244
+ self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
245
+
246
+ // Wait until address was sent
247
+ while {
248
+ let isr = self . i2c . isr ( ) . read ( ) ;
249
+ self . check_and_clear_error_flags ( & isr)
250
+ . map_err ( Error :: nack_addr) ?;
251
+ isr. txis ( ) . bit_is_clear ( ) && isr. tc ( ) . bit_is_clear ( )
252
+ } { }
253
+
254
+ Ok ( ( ) )
255
+ }
256
+
257
+ /// Sends START and Address for reading
258
+ fn prepare_read (
259
+ & self ,
260
+ addr : Address ,
261
+ buflen : usize ,
262
+ first_transaction : bool ,
263
+ ) -> Result < ( ) , Error > {
264
+ // Set up current address for reading
265
+ self . i2c . cr2 ( ) . modify ( |_, w| {
266
+ match addr {
267
+ Address :: Seven ( addr) => {
268
+ w. add10 ( ) . clear_bit ( ) ;
269
+ w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
270
+ }
271
+ Address :: Ten ( addr) => {
272
+ w. add10 ( ) . set_bit ( ) ;
273
+ w. head10r ( ) . bit ( !first_transaction) ;
274
+ w. sadd ( ) . set ( addr) ;
275
+ }
276
+ }
277
+ w. nbytes ( ) . set ( buflen as u8 ) ;
278
+ w. rd_wrn ( ) . set_bit ( )
279
+ } ) ;
280
+
281
+ // Send a START condition
282
+ self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
283
+
284
+ // Send the autoend after setting the start to get a restart
285
+ self . i2c . cr2 ( ) . modify ( |_, w| w. autoend ( ) . set_bit ( ) ) ;
286
+
287
+ Ok ( ( ) )
288
+ }
289
+
290
+ fn write_bytes ( & mut self , bytes : impl Iterator < Item = u8 > ) -> Result < ( ) , Error > {
291
+ // Send bytes
292
+ for c in bytes {
293
+ self . send_byte ( c) ?;
294
+ }
295
+
296
+ // Fallthrough is success
297
+ Ok ( ( ) )
298
+ }
299
+
216
300
fn send_byte ( & self , byte : u8 ) -> Result < ( ) , Error > {
217
301
// Wait until we're ready for sending
218
302
while {
@@ -242,72 +326,38 @@ impl<I2C: Instance> I2c<I2C> {
242
326
Ok ( value)
243
327
}
244
328
245
- pub fn read ( & mut self , addr : u8 , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
246
- // Set up current address for reading
247
- self . i2c . cr2 ( ) . modify ( |_, w| {
248
- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
249
- w. nbytes ( ) . set ( buffer. len ( ) as u8 ) ;
250
- w. rd_wrn ( ) . set_bit ( )
251
- } ) ;
252
-
253
- // Send a START condition
254
- self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
255
-
256
- // Send the autoend after setting the start to get a restart
257
- self . i2c . cr2 ( ) . modify ( |_, w| w. autoend ( ) . set_bit ( ) ) ;
258
-
259
- // Now read in all bytes
260
- for c in buffer. iter_mut ( ) {
329
+ fn read_bytes ( & mut self , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
330
+ // Receive bytes into buffer
331
+ for c in buffer {
261
332
* c = self . recv_byte ( ) ?;
262
333
}
263
334
264
- self . end_transaction ( )
335
+ Ok ( ( ) )
265
336
}
266
337
267
- pub fn write ( & mut self , addr : u8 , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
268
- // Set up current slave address for writing and enable autoending
269
- self . i2c . cr2 ( ) . modify ( |_, w| {
270
- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
271
- w. nbytes ( ) . set ( bytes. len ( ) as u8 ) ;
272
- w. rd_wrn ( ) . clear_bit ( ) ;
273
- w. autoend ( ) . set_bit ( )
274
- } ) ;
275
-
276
- // Send a START condition
277
- self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
278
-
279
- // Send out all individual bytes
280
- for c in bytes {
281
- self . send_byte ( * c) ?;
282
- }
338
+ pub fn read ( & mut self , addr : impl Into < Address > , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
339
+ self . prepare_read ( addr. into ( ) , buffer. len ( ) , true ) ?;
340
+ self . read_bytes ( buffer) ?;
283
341
284
342
self . end_transaction ( )
285
343
}
286
344
287
- pub fn write_read ( & mut self , addr : u8 , bytes : & [ u8 ] , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
288
- // Set up current slave address for writing and disable autoending
289
- self . i2c . cr2 ( ) . modify ( |_, w| {
290
- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
291
- w. nbytes ( ) . set ( bytes. len ( ) as u8 ) ;
292
- w. rd_wrn ( ) . clear_bit ( ) ;
293
- w. autoend ( ) . clear_bit ( )
294
- } ) ;
345
+ pub fn write ( & mut self , addr : impl Into < Address > , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
346
+ self . prepare_write ( addr. into ( ) , bytes. len ( ) ) ?;
347
+ self . write_bytes ( bytes. iter ( ) . cloned ( ) ) ?;
295
348
296
- // Send a START condition
297
- self . i2c . cr2 ( ) . modify ( |_ , w| w . start ( ) . set_bit ( ) ) ;
349
+ self . end_transaction ( )
350
+ }
298
351
299
- // Wait until the transmit buffer is empty and there hasn't been any error condition
300
- while {
301
- let isr = self . i2c . isr ( ) . read ( ) ;
302
- self . check_and_clear_error_flags ( & isr)
303
- . map_err ( Error :: nack_addr) ?;
304
- isr. txis ( ) . bit_is_clear ( ) && isr. tc ( ) . bit_is_clear ( )
305
- } { }
306
-
307
- // Send out all individual bytes
308
- for c in bytes {
309
- self . send_byte ( * c) ?;
310
- }
352
+ pub fn write_read (
353
+ & mut self ,
354
+ addr : impl Into < Address > ,
355
+ bytes : & [ u8 ] ,
356
+ buffer : & mut [ u8 ] ,
357
+ ) -> Result < ( ) , Error > {
358
+ let addr = addr. into ( ) ;
359
+ self . prepare_write ( addr, bytes. len ( ) ) ?;
360
+ self . write_bytes ( bytes. iter ( ) . cloned ( ) ) ?;
311
361
312
362
// Wait until data was sent
313
363
while {
@@ -317,24 +367,122 @@ impl<I2C: Instance> I2c<I2C> {
317
367
isr. tc ( ) . bit_is_clear ( )
318
368
} { }
319
369
320
- // Set up current address for reading
321
- self . i2c . cr2 ( ) . modify ( |_, w| {
322
- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
323
- w. nbytes ( ) . set ( buffer. len ( ) as u8 ) ;
324
- w. rd_wrn ( ) . set_bit ( )
325
- } ) ;
370
+ self . read ( addr, buffer)
371
+ }
326
372
327
- // Send another START condition
328
- self . i2c . cr2 ( ) . modify ( |_, w| w. start ( ) . set_bit ( ) ) ;
373
+ pub fn transaction < ' a > (
374
+ & mut self ,
375
+ addr : impl Into < Address > ,
376
+ mut ops : impl Iterator < Item = Hal1Operation < ' a > > ,
377
+ ) -> Result < ( ) , Error > {
378
+ let addr = addr. into ( ) ;
379
+ if let Some ( mut prev_op) = ops. next ( ) {
380
+ // 1. Generate Start for operation
381
+ match & prev_op {
382
+ Hal1Operation :: Read ( buf) => self . prepare_read ( addr, buf. len ( ) , true ) ?,
383
+ Hal1Operation :: Write ( data) => self . prepare_write ( addr, data. len ( ) ) ?,
384
+ } ;
385
+
386
+ for op in ops {
387
+ // 2. Execute previous operations.
388
+ match & mut prev_op {
389
+ Hal1Operation :: Read ( rb) => self . read_bytes ( rb) ?,
390
+ Hal1Operation :: Write ( wb) => self . write_bytes ( wb. iter ( ) . cloned ( ) ) ?,
391
+ } ;
392
+ // 3. If operation changes type we must generate new start
393
+ match ( & prev_op, & op) {
394
+ ( Hal1Operation :: Read ( _) , Hal1Operation :: Write ( data) ) => {
395
+ self . prepare_write ( addr, data. len ( ) ) ?
396
+ }
397
+ ( Hal1Operation :: Write ( _) , Hal1Operation :: Read ( buf) ) => {
398
+ self . prepare_read ( addr, buf. len ( ) , false ) ?
399
+ }
400
+ _ => { } // No changes if operation have not changed
401
+ }
402
+
403
+ prev_op = op;
404
+ }
329
405
330
- // Send the autoend after setting the start to get a restart
331
- self . i2c . cr2 ( ) . modify ( |_, w| w. autoend ( ) . set_bit ( ) ) ;
406
+ // 4. Now, prev_op is last command use methods variations that will generate stop
407
+ match prev_op {
408
+ Hal1Operation :: Read ( rb) => self . read_bytes ( rb) ?,
409
+ Hal1Operation :: Write ( wb) => self . write_bytes ( wb. iter ( ) . cloned ( ) ) ?,
410
+ } ;
332
411
333
- // Now read in all bytes
334
- for c in buffer. iter_mut ( ) {
335
- * c = self . recv_byte ( ) ?;
412
+ self . end_transaction ( ) ?;
336
413
}
337
414
338
- self . end_transaction ( )
415
+ // Fallthrough is success
416
+ Ok ( ( ) )
417
+ }
418
+
419
+ pub fn transaction_slice (
420
+ & mut self ,
421
+ addr : impl Into < Address > ,
422
+ ops_slice : & mut [ Hal1Operation < ' _ > ] ,
423
+ ) -> Result < ( ) , Error > {
424
+ let addr = addr. into ( ) ;
425
+ transaction_impl ! ( self , addr, ops_slice, Hal1Operation ) ;
426
+ // Fallthrough is success
427
+ Ok ( ( ) )
428
+ }
429
+
430
+ fn transaction_slice_hal_02 (
431
+ & mut self ,
432
+ addr : impl Into < Address > ,
433
+ ops_slice : & mut [ Hal02Operation < ' _ > ] ,
434
+ ) -> Result < ( ) , Error > {
435
+ let addr = addr. into ( ) ;
436
+ transaction_impl ! ( self , addr, ops_slice, Hal02Operation ) ;
437
+ // Fallthrough is success
438
+ Ok ( ( ) )
339
439
}
340
440
}
441
+
442
+ macro_rules! transaction_impl {
443
+ ( $self: ident, $addr: ident, $ops_slice: ident, $Operation: ident) => {
444
+ let i2c = $self;
445
+ let addr = $addr;
446
+ let mut ops = $ops_slice. iter_mut( ) ;
447
+
448
+ if let Some ( mut prev_op) = ops. next( ) {
449
+ // 1. Generate Start for operation
450
+ match & prev_op {
451
+ $Operation:: Read ( buf) => i2c. prepare_read( addr, buf. len( ) , true ) ?,
452
+ $Operation:: Write ( data) => i2c. prepare_write( addr, data. len( ) ) ?,
453
+ } ;
454
+
455
+ for op in ops {
456
+ // 2. Execute previous operations.
457
+ match & mut prev_op {
458
+ $Operation:: Read ( rb) => i2c. read_bytes( rb) ?,
459
+ $Operation:: Write ( wb) => i2c. write_bytes( wb. iter( ) . cloned( ) ) ?,
460
+ } ;
461
+ // 3. If operation changes type we must generate new start
462
+ match ( & prev_op, & op) {
463
+ ( $Operation:: Read ( _) , $Operation:: Write ( data) ) => {
464
+ i2c. prepare_write( addr, data. len( ) ) ?
465
+ }
466
+ ( $Operation:: Write ( _) , $Operation:: Read ( buf) ) => {
467
+ i2c. prepare_read( addr, buf. len( ) , false ) ?
468
+ }
469
+ _ => { } // No changes if operation have not changed
470
+ }
471
+
472
+ prev_op = op;
473
+ }
474
+
475
+ // 4. Now, prev_op is last command use methods variations that will generate stop
476
+ match prev_op {
477
+ $Operation:: Read ( rb) => i2c. read_bytes( rb) ?,
478
+ $Operation:: Write ( wb) => i2c. write_bytes( wb. iter( ) . cloned( ) ) ?,
479
+ } ;
480
+
481
+ i2c. end_transaction( ) ?;
482
+ }
483
+ } ;
484
+ }
485
+ use transaction_impl;
486
+
487
+ // Note: implementation is from f0xx-hal
488
+ // TODO: check error handling. See https://github.com/stm32-rs/stm32f0xx-hal/pull/95/files
0 commit comments