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