4
4
5
5
use core:: future:: { poll_fn, Future } ;
6
6
use core:: marker:: PhantomData ;
7
- use core:: mem:: MaybeUninit ;
8
7
use core:: sync:: atomic:: compiler_fence;
9
8
use core:: sync:: atomic:: Ordering :: SeqCst ;
10
9
use core:: task:: Poll ;
@@ -17,7 +16,7 @@ use embassy_time::{Duration, Instant};
17
16
use embedded_hal_1:: i2c:: Operation ;
18
17
pub use pac:: twim:: vals:: Frequency ;
19
18
20
- use crate :: chip:: { EASY_DMA_SIZE , FORCE_COPY_BUFFER_SIZE } ;
19
+ use crate :: chip:: EASY_DMA_SIZE ;
21
20
use crate :: gpio:: Pin as GpioPin ;
22
21
use crate :: interrupt:: typelevel:: Interrupt ;
23
22
use crate :: pac:: gpio:: vals as gpiovals;
@@ -75,8 +74,8 @@ pub enum Error {
75
74
Transmit ,
76
75
/// Data reception failed.
77
76
Receive ,
78
- /// The buffer is not in data RAM. It's most likely in flash, and nRF's DMA cannot access flash.
79
- BufferNotInRAM ,
77
+ /// The buffer is not in data RAM and is larger than the RAM buffer . It's most likely in flash, and nRF's DMA cannot access flash.
78
+ RAMBufferTooSmall ,
80
79
/// Didn't receive an ACK bit after the address byte. Address might be wrong, or the i2c device chip might not be connected properly.
81
80
AddressNack ,
82
81
/// Didn't receive an ACK bit after a data byte.
@@ -115,16 +114,24 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
115
114
/// TWI driver.
116
115
pub struct Twim < ' d , T : Instance > {
117
116
_p : Peri < ' d , T > ,
117
+ tx_ram_buffer : & ' d mut [ u8 ] ,
118
118
}
119
119
120
120
impl < ' d , T : Instance > Twim < ' d , T > {
121
121
/// Create a new TWI driver.
122
+ ///
123
+ /// `tx_ram_buffer` is required if any write operations will be performed with data that is not in RAM.
124
+ /// Usually this is static data that the compiler locates in flash instead of RAM. The `tx_ram_buffer`
125
+ /// needs to be at least as large as the largest write operation that will be executed with a buffer
126
+ /// that is not in RAM. If all write operations will be performed from RAM, an empty buffer (`&[]`) may
127
+ /// be used.
122
128
pub fn new (
123
129
twim : Peri < ' d , T > ,
124
130
_irq : impl interrupt:: typelevel:: Binding < T :: Interrupt , InterruptHandler < T > > + ' d ,
125
131
sda : Peri < ' d , impl GpioPin > ,
126
132
scl : Peri < ' d , impl GpioPin > ,
127
133
config : Config ,
134
+ tx_ram_buffer : & ' d mut [ u8 ] ,
128
135
) -> Self {
129
136
let r = T :: regs ( ) ;
130
137
@@ -159,7 +166,10 @@ impl<'d, T: Instance> Twim<'d, T> {
159
166
// Enable TWIM instance.
160
167
r. enable ( ) . write ( |w| w. set_enable ( vals:: Enable :: ENABLED ) ) ;
161
168
162
- let mut twim = Self { _p : twim } ;
169
+ let mut twim = Self {
170
+ _p : twim,
171
+ tx_ram_buffer,
172
+ } ;
163
173
164
174
// Apply runtime peripheral configuration
165
175
Self :: set_config ( & mut twim, & config) . unwrap ( ) ;
@@ -174,21 +184,17 @@ impl<'d, T: Instance> Twim<'d, T> {
174
184
}
175
185
176
186
/// Set TX buffer, checking that it is in RAM and has suitable length.
177
- unsafe fn set_tx_buffer (
178
- & mut self ,
179
- buffer : & [ u8 ] ,
180
- ram_buffer : Option < & mut [ MaybeUninit < u8 > ; FORCE_COPY_BUFFER_SIZE ] > ,
181
- ) -> Result < ( ) , Error > {
187
+ unsafe fn set_tx_buffer ( & mut self , buffer : & [ u8 ] ) -> Result < ( ) , Error > {
182
188
let buffer = if slice_in_ram ( buffer) {
183
189
buffer
184
190
} else {
185
- let ram_buffer = ram_buffer. ok_or ( Error :: BufferNotInRAM ) ?;
191
+ if buffer. len ( ) > self . tx_ram_buffer . len ( ) {
192
+ return Err ( Error :: RAMBufferTooSmall ) ;
193
+ }
186
194
trace ! ( "Copying TWIM tx buffer into RAM for DMA" ) ;
187
- let ram_buffer = & mut ram_buffer[ ..buffer. len ( ) ] ;
188
- // Inline implementation of the nightly API MaybeUninit::copy_from_slice(ram_buffer, buffer)
189
- let uninit_src: & [ MaybeUninit < u8 > ] = unsafe { core:: mem:: transmute ( buffer) } ;
190
- ram_buffer. copy_from_slice ( uninit_src) ;
191
- unsafe { & * ( ram_buffer as * const [ MaybeUninit < u8 > ] as * const [ u8 ] ) }
195
+ let ram_buffer = & mut self . tx_ram_buffer [ ..buffer. len ( ) ] ;
196
+ ram_buffer. copy_from_slice ( buffer) ;
197
+ & * ram_buffer
192
198
} ;
193
199
194
200
if buffer. len ( ) > EASY_DMA_SIZE {
@@ -358,7 +364,6 @@ impl<'d, T: Instance> Twim<'d, T> {
358
364
& mut self ,
359
365
address : u8 ,
360
366
operations : & mut [ Operation < ' _ > ] ,
361
- tx_ram_buffer : Option < & mut [ MaybeUninit < u8 > ; FORCE_COPY_BUFFER_SIZE ] > ,
362
367
last_op : Option < & Operation < ' _ > > ,
363
368
inten : bool ,
364
369
) -> Result < usize , Error > {
@@ -397,7 +402,7 @@ impl<'d, T: Instance> Twim<'d, T> {
397
402
398
403
// Set up DMA buffers.
399
404
unsafe {
400
- self . set_tx_buffer ( wr_buffer, tx_ram_buffer ) ?;
405
+ self . set_tx_buffer ( wr_buffer) ?;
401
406
self . set_rx_buffer ( rd_buffer) ?;
402
407
}
403
408
@@ -450,7 +455,7 @@ impl<'d, T: Instance> Twim<'d, T> {
450
455
{
451
456
// Set up DMA buffers.
452
457
unsafe {
453
- self . set_tx_buffer ( wr_buffer, tx_ram_buffer ) ?;
458
+ self . set_tx_buffer ( wr_buffer) ?;
454
459
self . set_rx_buffer ( rd_buffer) ?;
455
460
}
456
461
@@ -472,7 +477,7 @@ impl<'d, T: Instance> Twim<'d, T> {
472
477
473
478
// Set up DMA buffers.
474
479
unsafe {
475
- self . set_tx_buffer ( buffer, tx_ram_buffer ) ?;
480
+ self . set_tx_buffer ( buffer) ?;
476
481
}
477
482
478
483
// Start write operation.
@@ -539,28 +544,9 @@ impl<'d, T: Instance> Twim<'d, T> {
539
544
/// An `Operation::Write` following an `Operation::Read` must have a
540
545
/// non-empty buffer.
541
546
pub fn blocking_transaction ( & mut self , address : u8 , mut operations : & mut [ Operation < ' _ > ] ) -> Result < ( ) , Error > {
542
- let mut tx_ram_buffer = [ MaybeUninit :: uninit ( ) ; FORCE_COPY_BUFFER_SIZE ] ;
543
547
let mut last_op = None ;
544
548
while !operations. is_empty ( ) {
545
- let ops = self . setup_operations ( address, operations, Some ( & mut tx_ram_buffer) , last_op, false ) ?;
546
- let ( in_progress, rest) = operations. split_at_mut ( ops) ;
547
- self . blocking_wait ( ) ;
548
- self . check_operations ( in_progress) ?;
549
- last_op = in_progress. last ( ) ;
550
- operations = rest;
551
- }
552
- Ok ( ( ) )
553
- }
554
-
555
- /// Same as [`blocking_transaction`](Twim::blocking_transaction) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
556
- pub fn blocking_transaction_from_ram (
557
- & mut self ,
558
- address : u8 ,
559
- mut operations : & mut [ Operation < ' _ > ] ,
560
- ) -> Result < ( ) , Error > {
561
- let mut last_op = None ;
562
- while !operations. is_empty ( ) {
563
- let ops = self . setup_operations ( address, operations, None , last_op, false ) ?;
549
+ let ops = self . setup_operations ( address, operations, last_op, false ) ?;
564
550
let ( in_progress, rest) = operations. split_at_mut ( ops) ;
565
551
self . blocking_wait ( ) ;
566
552
self . check_operations ( in_progress) ?;
@@ -579,31 +565,10 @@ impl<'d, T: Instance> Twim<'d, T> {
579
565
address : u8 ,
580
566
mut operations : & mut [ Operation < ' _ > ] ,
581
567
timeout : Duration ,
582
- ) -> Result < ( ) , Error > {
583
- let mut tx_ram_buffer = [ MaybeUninit :: uninit ( ) ; FORCE_COPY_BUFFER_SIZE ] ;
584
- let mut last_op = None ;
585
- while !operations. is_empty ( ) {
586
- let ops = self . setup_operations ( address, operations, Some ( & mut tx_ram_buffer) , last_op, false ) ?;
587
- let ( in_progress, rest) = operations. split_at_mut ( ops) ;
588
- self . blocking_wait_timeout ( timeout) ?;
589
- self . check_operations ( in_progress) ?;
590
- last_op = in_progress. last ( ) ;
591
- operations = rest;
592
- }
593
- Ok ( ( ) )
594
- }
595
-
596
- /// Same as [`blocking_transaction_timeout`](Twim::blocking_transaction_timeout) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
597
- #[ cfg( feature = "time" ) ]
598
- pub fn blocking_transaction_from_ram_timeout (
599
- & mut self ,
600
- address : u8 ,
601
- mut operations : & mut [ Operation < ' _ > ] ,
602
- timeout : Duration ,
603
568
) -> Result < ( ) , Error > {
604
569
let mut last_op = None ;
605
570
while !operations. is_empty ( ) {
606
- let ops = self . setup_operations ( address, operations, None , last_op, false ) ?;
571
+ let ops = self . setup_operations ( address, operations, last_op, false ) ?;
607
572
let ( in_progress, rest) = operations. split_at_mut ( ops) ;
608
573
self . blocking_wait_timeout ( timeout) ?;
609
574
self . check_operations ( in_progress) ?;
@@ -624,28 +589,9 @@ impl<'d, T: Instance> Twim<'d, T> {
624
589
/// An `Operation::Write` following an `Operation::Read` must have a
625
590
/// non-empty buffer.
626
591
pub async fn transaction ( & mut self , address : u8 , mut operations : & mut [ Operation < ' _ > ] ) -> Result < ( ) , Error > {
627
- let mut tx_ram_buffer = [ MaybeUninit :: uninit ( ) ; FORCE_COPY_BUFFER_SIZE ] ;
628
- let mut last_op = None ;
629
- while !operations. is_empty ( ) {
630
- let ops = self . setup_operations ( address, operations, Some ( & mut tx_ram_buffer) , last_op, true ) ?;
631
- let ( in_progress, rest) = operations. split_at_mut ( ops) ;
632
- self . async_wait ( ) . await ?;
633
- self . check_operations ( in_progress) ?;
634
- last_op = in_progress. last ( ) ;
635
- operations = rest;
636
- }
637
- Ok ( ( ) )
638
- }
639
-
640
- /// Same as [`transaction`](Twim::transaction) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
641
- pub async fn transaction_from_ram (
642
- & mut self ,
643
- address : u8 ,
644
- mut operations : & mut [ Operation < ' _ > ] ,
645
- ) -> Result < ( ) , Error > {
646
592
let mut last_op = None ;
647
593
while !operations. is_empty ( ) {
648
- let ops = self . setup_operations ( address, operations, None , last_op, true ) ?;
594
+ let ops = self . setup_operations ( address, operations, last_op, true ) ?;
649
595
let ( in_progress, rest) = operations. split_at_mut ( ops) ;
650
596
self . async_wait ( ) . await ?;
651
597
self . check_operations ( in_progress) ?;
@@ -665,11 +611,6 @@ impl<'d, T: Instance> Twim<'d, T> {
665
611
self . blocking_transaction ( address, & mut [ Operation :: Write ( buffer) ] )
666
612
}
667
613
668
- /// Same as [`blocking_write`](Twim::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
669
- pub fn blocking_write_from_ram ( & mut self , address : u8 , buffer : & [ u8 ] ) -> Result < ( ) , Error > {
670
- self . blocking_transaction_from_ram ( address, & mut [ Operation :: Write ( buffer) ] )
671
- }
672
-
673
614
/// Read from an I2C slave.
674
615
///
675
616
/// The buffer must have a length of at most 255 bytes on the nRF52832
@@ -687,16 +628,6 @@ impl<'d, T: Instance> Twim<'d, T> {
687
628
self . blocking_transaction ( address, & mut [ Operation :: Write ( wr_buffer) , Operation :: Read ( rd_buffer) ] )
688
629
}
689
630
690
- /// Same as [`blocking_write_read`](Twim::blocking_write_read) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
691
- pub fn blocking_write_read_from_ram (
692
- & mut self ,
693
- address : u8 ,
694
- wr_buffer : & [ u8 ] ,
695
- rd_buffer : & mut [ u8 ] ,
696
- ) -> Result < ( ) , Error > {
697
- self . blocking_transaction_from_ram ( address, & mut [ Operation :: Write ( wr_buffer) , Operation :: Read ( rd_buffer) ] )
698
- }
699
-
700
631
// ===========================================
701
632
702
633
/// Write to an I2C slave with timeout.
@@ -707,17 +638,6 @@ impl<'d, T: Instance> Twim<'d, T> {
707
638
self . blocking_transaction_timeout ( address, & mut [ Operation :: Write ( buffer) ] , timeout)
708
639
}
709
640
710
- /// Same as [`blocking_write`](Twim::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
711
- #[ cfg( feature = "time" ) ]
712
- pub fn blocking_write_from_ram_timeout (
713
- & mut self ,
714
- address : u8 ,
715
- buffer : & [ u8 ] ,
716
- timeout : Duration ,
717
- ) -> Result < ( ) , Error > {
718
- self . blocking_transaction_from_ram_timeout ( address, & mut [ Operation :: Write ( buffer) ] , timeout)
719
- }
720
-
721
641
/// Read from an I2C slave.
722
642
///
723
643
/// The buffer must have a length of at most 255 bytes on the nRF52832
@@ -747,22 +667,6 @@ impl<'d, T: Instance> Twim<'d, T> {
747
667
)
748
668
}
749
669
750
- /// Same as [`blocking_write_read`](Twim::blocking_write_read) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
751
- #[ cfg( feature = "time" ) ]
752
- pub fn blocking_write_read_from_ram_timeout (
753
- & mut self ,
754
- address : u8 ,
755
- wr_buffer : & [ u8 ] ,
756
- rd_buffer : & mut [ u8 ] ,
757
- timeout : Duration ,
758
- ) -> Result < ( ) , Error > {
759
- self . blocking_transaction_from_ram_timeout (
760
- address,
761
- & mut [ Operation :: Write ( wr_buffer) , Operation :: Read ( rd_buffer) ] ,
762
- timeout,
763
- )
764
- }
765
-
766
670
// ===========================================
767
671
768
672
/// Read from an I2C slave.
@@ -781,12 +685,6 @@ impl<'d, T: Instance> Twim<'d, T> {
781
685
self . transaction ( address, & mut [ Operation :: Write ( buffer) ] ) . await
782
686
}
783
687
784
- /// Same as [`write`](Twim::write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
785
- pub async fn write_from_ram ( & mut self , address : u8 , buffer : & [ u8 ] ) -> Result < ( ) , Error > {
786
- self . transaction_from_ram ( address, & mut [ Operation :: Write ( buffer) ] )
787
- . await
788
- }
789
-
790
688
/// Write data to an I2C slave, then read data from the slave without
791
689
/// triggering a stop condition between the two.
792
690
///
@@ -796,17 +694,6 @@ impl<'d, T: Instance> Twim<'d, T> {
796
694
self . transaction ( address, & mut [ Operation :: Write ( wr_buffer) , Operation :: Read ( rd_buffer) ] )
797
695
. await
798
696
}
799
-
800
- /// Same as [`write_read`](Twim::write_read) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
801
- pub async fn write_read_from_ram (
802
- & mut self ,
803
- address : u8 ,
804
- wr_buffer : & [ u8 ] ,
805
- rd_buffer : & mut [ u8 ] ,
806
- ) -> Result < ( ) , Error > {
807
- self . transaction_from_ram ( address, & mut [ Operation :: Write ( wr_buffer) , Operation :: Read ( rd_buffer) ] )
808
- . await
809
- }
810
697
}
811
698
812
699
impl < ' a , T : Instance > Drop for Twim < ' a , T > {
@@ -904,7 +791,7 @@ impl embedded_hal_1::i2c::Error for Error {
904
791
Self :: RxBufferTooLong => embedded_hal_1:: i2c:: ErrorKind :: Other ,
905
792
Self :: Transmit => embedded_hal_1:: i2c:: ErrorKind :: Other ,
906
793
Self :: Receive => embedded_hal_1:: i2c:: ErrorKind :: Other ,
907
- Self :: BufferNotInRAM => embedded_hal_1:: i2c:: ErrorKind :: Other ,
794
+ Self :: RAMBufferTooSmall => embedded_hal_1:: i2c:: ErrorKind :: Other ,
908
795
Self :: AddressNack => {
909
796
embedded_hal_1:: i2c:: ErrorKind :: NoAcknowledge ( embedded_hal_1:: i2c:: NoAcknowledgeSource :: Address )
910
797
}
0 commit comments