1
- use core:: ops:: { Deref , DerefMut } ;
1
+ use core:: {
2
+ future:: Future ,
3
+ ops:: { Deref , DerefMut } ,
4
+ pin:: Pin ,
5
+ task:: { Context , Poll } ,
6
+ } ;
2
7
8
+ use atomic_waker:: AtomicWaker ;
3
9
use embedded_hal:: spi:: ErrorType ;
4
10
use embedded_hal_async:: spi:: SpiBus ;
5
11
6
12
use crate :: gpdma:: {
7
- config:: DmaConfig , periph:: { DmaDuplex , DmaRx , DmaTx , Rx , RxAddr , Tx , TxAddr } , ChannelRegs , DmaChannel , DmaTransfer , Error as DmaError , Word as DmaWord
13
+ config:: DmaConfig ,
14
+ periph:: { DmaDuplex , DmaRx , DmaTx , Rx , RxAddr , Tx , TxAddr } ,
15
+ ChannelRegs , DmaChannel , DmaTransfer , Error as DmaError , Word as DmaWord ,
8
16
} ;
9
17
10
18
use super :: { Error , Instance , Spi , Word } ;
59
67
}
60
68
}
61
69
62
-
63
70
pub struct SpiDma < SPI , W : Word , MODE > {
64
71
spi : Spi < SPI , W > ,
65
72
mode : MODE ,
91
98
self . inner . disable_dma ( ) ;
92
99
result
93
100
}
101
+
102
+ async fn finish_transfer_async (
103
+ & mut self ,
104
+ result : Result < ( ) , DmaError > ,
105
+ ) -> Result < ( ) , Error > {
106
+ let result = match result {
107
+ Ok ( _) => {
108
+ SpiDmaFuture :: new ( self ) . await
109
+ }
110
+ Err ( error) => {
111
+ self . abort_transaction ( ) ;
112
+ Err ( Error :: DmaError ( error) )
113
+ }
114
+ } ;
115
+ result
116
+ }
94
117
}
95
118
96
119
impl < SPI , W , CH > SpiDma < SPI , W , DmaTx < SPI , W , CH > >
@@ -110,7 +133,9 @@ where
110
133
}
111
134
112
135
pub fn free ( self ) -> ( Spi < SPI , W > , DmaChannel < CH > ) {
113
- ( self . spi , self . mode . into ( ) )
136
+ let spi = self . spi ;
137
+ let channel = self . mode . into ( ) ;
138
+ ( spi, channel)
114
139
}
115
140
}
116
141
@@ -212,7 +237,7 @@ where
212
237
213
238
async fn read_dma ( & mut self , words : & mut [ W ] ) -> Result < ( ) , Error > {
214
239
let result = self . start_dma_read ( words) ?. to_async ( ) . await ;
215
- self . finish_transfer ( result)
240
+ self . finish_transfer_async ( result) . await
216
241
}
217
242
}
218
243
@@ -246,7 +271,7 @@ where
246
271
247
272
async fn write_dma ( & mut self , words : & [ W ] ) -> Result < ( ) , Error > {
248
273
let result = self . start_dma_write ( words) ?. to_async ( ) . await ;
249
- self . finish_transfer ( result)
274
+ self . finish_transfer_async ( result) . await
250
275
}
251
276
}
252
277
@@ -296,7 +321,7 @@ where
296
321
let ( tx, rx) = ( tx. to_async ( ) , rx. to_async ( ) ) ;
297
322
let result = tx. await . and ( rx. await ) ;
298
323
299
- self . finish_transfer ( result)
324
+ self . finish_transfer_async ( result) . await
300
325
}
301
326
302
327
async fn transfer_inplace_dma (
@@ -423,3 +448,49 @@ where
423
448
Ok ( ( ) )
424
449
}
425
450
}
451
+
452
+ struct SpiDmaFuture < ' a , SPI : Instance , W : Word , MODE > {
453
+ spi : & ' a mut SpiDma < SPI , W , MODE > ,
454
+ waker : AtomicWaker ,
455
+ }
456
+
457
+ impl < ' a , SPI : Instance , W : Word , MODE > SpiDmaFuture < ' a , SPI , W , MODE > {
458
+ fn new ( spi : & ' a mut SpiDma < SPI , W , MODE > ) -> Self {
459
+ Self {
460
+ spi,
461
+ waker : AtomicWaker :: new ( ) ,
462
+ }
463
+ }
464
+ }
465
+
466
+ impl < SPI : Instance , W : Word , MODE > Unpin for SpiDmaFuture < ' _ , SPI , W , MODE > { }
467
+
468
+ impl < SPI : Instance , W : Word , MODE > Drop for SpiDmaFuture < ' _ , SPI , W , MODE > {
469
+ fn drop ( & mut self ) {
470
+ if !self . spi . is_transaction_complete ( ) {
471
+ self . spi . abort_transaction ( ) ;
472
+ } else if self . spi . inner . is_enabled ( ) {
473
+ self . spi . disable ( ) ;
474
+ } else {
475
+ // do nothing if the transaction is already complete
476
+ }
477
+ }
478
+ }
479
+
480
+ impl < SPI : Instance , W : Word , MODE > Future for SpiDmaFuture < ' _ , SPI , W , MODE > {
481
+ type Output = Result < ( ) , Error > ;
482
+
483
+ fn poll (
484
+ mut self : Pin < & mut Self > ,
485
+ cx : & mut Context < ' _ > ,
486
+ ) -> Poll < Self :: Output > {
487
+ self . waker . register ( cx. waker ( ) ) ;
488
+
489
+ if self . spi . is_transaction_complete ( ) {
490
+ self . spi . disable ( ) ;
491
+ Poll :: Ready ( Ok ( ( ) ) )
492
+ } else {
493
+ Poll :: Pending
494
+ }
495
+ }
496
+ }
0 commit comments