@@ -5,8 +5,8 @@ use core::{
55 task:: { Context , Poll } ,
66} ;
77
8+ use embedded_dma:: { ReadBuffer , WriteBuffer } ;
89use embedded_hal:: spi:: ErrorType ;
9- use embedded_hal_async:: spi:: SpiBus ;
1010use futures_util:: join;
1111use futures_util:: task:: AtomicWaker ;
1212
@@ -228,18 +228,22 @@ where
228228 W : Word + DmaWord ,
229229 MODE : Rx < W > ,
230230{
231- pub fn start_dma_read < ' a > (
231+ pub fn start_dma_read < ' a , D > (
232232 & ' a mut self ,
233- words : & ' a mut [ W ] ,
234- ) -> Result < DmaTransfer < ' a , <MODE as Rx < W > >:: CH > , Error > {
233+ mut destination : D ,
234+ ) -> Result < DmaTransfer < ' a , <MODE as Rx < W > >:: CH > , Error >
235+ where
236+ D : WriteBuffer < Word = W > ,
237+ {
235238 let config = DmaConfig :: new ( ) . with_request ( SPI :: rx_dma_request ( ) ) ;
239+ let ( _, len) = unsafe { destination. write_buffer ( ) } ;
236240
237- self . spi . inner . set_transfer_word_count ( words . len ( ) as u16 ) ;
241+ self . spi . inner . set_transfer_word_count ( len as u16 ) ;
238242 // Make sure to handle any errors before initializing a transfer
239243 self . setup_read_mode ( ) ?;
240244
241245 let spi = & mut self . spi ;
242- let transfer = self . mode . init_rx_transfer ( config, words ) ;
246+ let transfer = self . mode . init_rx_transfer ( config, destination ) ;
243247
244248 spi. inner . enable_rx_dma ( ) ;
245249
@@ -250,8 +254,11 @@ where
250254 Ok ( transfer)
251255 }
252256
253- async fn read_dma ( & mut self , words : & mut [ W ] ) -> Result < ( ) , Error > {
254- let result = self . start_dma_read ( words) ?. await ;
257+ pub async fn read_dma < D > ( & mut self , destination : D ) -> Result < ( ) , Error >
258+ where
259+ D : WriteBuffer < Word = W > ,
260+ {
261+ let result = self . start_dma_read ( destination) ?. await ;
255262 self . finish_transfer_async ( result) . await
256263 }
257264}
@@ -263,19 +270,24 @@ where
263270 W : Word + DmaWord ,
264271 MODE : Tx < W > ,
265272{
266- pub fn start_dma_write < ' a > (
273+ pub fn start_dma_write < ' a , S > (
267274 & ' a mut self ,
268- words : & ' a [ W ] ,
269- ) -> Result < DmaTransfer < ' a , <MODE as Tx < W > >:: CH > , Error > {
275+ source : S ,
276+ ) -> Result < DmaTransfer < ' a , <MODE as Tx < W > >:: CH > , Error >
277+ where
278+ S : ReadBuffer < Word = W > ,
279+ {
270280 let config = DmaConfig :: new ( ) . with_request ( SPI :: tx_dma_request ( ) ) ;
271281
272- self . inner . set_transfer_word_count ( words. len ( ) as u16 ) ;
282+ let ( _, len) = unsafe { source. read_buffer ( ) } ;
283+
284+ self . inner . set_transfer_word_count ( len as u16 ) ;
273285
274286 // Make sure to handle any errors before initializing a transfer
275287 self . setup_write_mode ( ) ?;
276288
277289 let spi = & mut self . spi ;
278- let transfer = self . mode . init_tx_transfer ( config, words ) ;
290+ let transfer = self . mode . init_tx_transfer ( config, source ) ;
279291
280292 transfer. start_nonblocking ( ) ;
281293 spi. inner . enable_tx_dma ( ) ;
@@ -284,8 +296,11 @@ where
284296 Ok ( transfer)
285297 }
286298
287- async fn write_dma ( & mut self , words : & [ W ] ) -> Result < ( ) , Error > {
288- let result = self . start_dma_write ( words) ?. await ;
299+ pub async fn write_dma < S > ( & mut self , source : S ) -> Result < ( ) , Error >
300+ where
301+ S : ReadBuffer < Word = W > ,
302+ {
303+ let result = self . start_dma_write ( source) ?. await ;
289304 self . finish_transfer_async ( result) . await
290305 }
291306}
@@ -298,27 +313,33 @@ where
298313 TX : DmaChannel ,
299314 RX : DmaChannel ,
300315{
301- pub fn start_dma_duplex_transfer < ' a > (
316+ pub fn start_dma_duplex_transfer < ' a , S , D > (
302317 & ' a mut self ,
303- read : & ' a mut [ W ] ,
304- write : & ' a [ W ] ,
305- ) -> Result < ( DmaTransfer < ' a , TX > , DmaTransfer < ' a , RX > ) , Error > {
318+ source : S ,
319+ mut destination : D ,
320+ ) -> Result < ( DmaTransfer < ' a , TX > , DmaTransfer < ' a , RX > ) , Error >
321+ where
322+ S : ReadBuffer < Word = W > ,
323+ D : WriteBuffer < Word = W > ,
324+ {
325+ let ( _, read_len) = unsafe { source. read_buffer ( ) } ;
326+ let ( _, write_len) = unsafe { destination. write_buffer ( ) } ;
327+
306328 assert_eq ! (
307- read. len( ) ,
308- write. len( ) ,
329+ read_len, write_len,
309330 "Read and write buffers must have the same length"
310331 ) ;
311332
312333 let tx_config = DmaConfig :: new ( ) . with_request ( SPI :: tx_dma_request ( ) ) ;
313334 let rx_config = DmaConfig :: new ( ) . with_request ( SPI :: rx_dma_request ( ) ) ;
314335
315- self . inner . set_transfer_word_count ( read . len ( ) as u16 ) ;
336+ self . inner . set_transfer_word_count ( read_len as u16 ) ;
316337
317338 self . check_transfer_mode ( ) ?;
318339
319340 let spi = & mut self . spi ;
320- let tx_transfer = self . mode . init_tx_transfer ( tx_config, write ) ;
321- let rx_transfer = self . mode . init_rx_transfer ( rx_config, read ) ;
341+ let tx_transfer = self . mode . init_tx_transfer ( tx_config, source ) ;
342+ let rx_transfer = self . mode . init_rx_transfer ( rx_config, destination ) ;
322343
323344 spi. inner . enable_rx_dma ( ) ;
324345 rx_transfer. start_nonblocking ( ) ;
@@ -329,27 +350,38 @@ where
329350 Ok ( ( tx_transfer, rx_transfer) )
330351 }
331352
332- async fn transfer_dma (
353+ pub async fn transfer_dma < S , D > (
333354 & mut self ,
334- read : & mut [ W ] ,
335- write : & [ W ] ,
336- ) -> Result < ( ) , Error > {
337- let ( tx, rx) = self . start_dma_duplex_transfer ( read, write) ?;
355+ source : S ,
356+ destination : D ,
357+ ) -> Result < ( ) , Error >
358+ where
359+ S : ReadBuffer < Word = W > ,
360+ D : WriteBuffer < Word = W > ,
361+ {
362+ let ( tx, rx) = self . start_dma_duplex_transfer ( source, destination) ?;
338363 let ( tx, rx) = ( tx. into_future ( ) , rx. into_future ( ) ) ;
339364 let results = join ! ( tx, rx) ;
340365 let result = results. 0 . and ( results. 1 ) ;
341366
342367 self . finish_transfer_async ( result) . await
343368 }
344369
345- async fn transfer_inplace_dma (
370+ pub async fn transfer_inplace_dma < B > (
346371 & mut self ,
347- words : & mut [ W ] ,
348- ) -> Result < ( ) , Error > {
372+ mut buffer : B ,
373+ ) -> Result < ( ) , Error >
374+ where
375+ B : WriteBuffer < Word = W > ,
376+ {
377+ let ( ptr, len) = unsafe { buffer. write_buffer ( ) } ;
378+
349379 // Note (unsafe): Data will be read from the start of the buffer before data is written
350- // to those locations just like for blocking non-DMA in-place transfers
351- let write: & [ W ] = unsafe { * ( words. as_ptr ( ) as * const & [ W ] ) } ;
352- self . transfer_dma ( words, write) . await
380+ // to those locations just like for blocking non-DMA in-place transfers, and the location
381+ // is already guaranteed to be 'static
382+ let source = unsafe { core:: slice:: from_raw_parts ( ptr, len) } ;
383+
384+ self . transfer_dma ( source, buffer) . await
353385 }
354386}
355387
@@ -361,112 +393,6 @@ where
361393 type Error = Error ;
362394}
363395
364- impl < SPI , CH , W > SpiBus < W > for SpiDma < SPI , DmaTx < SPI , W , CH > , W >
365- where
366- SPI : Instance + Waker ,
367- W : Word + DmaWord ,
368- CH : DmaChannel ,
369- {
370- async fn read ( & mut self , _words : & mut [ W ] ) -> Result < ( ) , Self :: Error > {
371- unimplemented ! ( "Not supported for simplex transmitter" )
372- }
373-
374- async fn write ( & mut self , words : & [ W ] ) -> Result < ( ) , Self :: Error > {
375- self . write_dma ( words) . await
376- }
377-
378- async fn transfer (
379- & mut self ,
380- _read : & mut [ W ] ,
381- _write : & [ W ] ,
382- ) -> Result < ( ) , Self :: Error > {
383- unimplemented ! ( "Not supported for simplex transmitter" )
384- }
385-
386- async fn transfer_in_place (
387- & mut self ,
388- _words : & mut [ W ] ,
389- ) -> Result < ( ) , Self :: Error > {
390- unimplemented ! ( "Not supported for simplex transmitter" )
391- }
392-
393- async fn flush ( & mut self ) -> Result < ( ) , Self :: Error > {
394- // This is handled within each of the above functions
395- Ok ( ( ) )
396- }
397- }
398-
399- impl < SPI , CH , W > SpiBus < W > for SpiDma < SPI , DmaRx < SPI , W , CH > , W >
400- where
401- SPI : Instance + Waker ,
402- W : Word + DmaWord ,
403- CH : DmaChannel ,
404- {
405- async fn read ( & mut self , words : & mut [ W ] ) -> Result < ( ) , Self :: Error > {
406- self . read_dma ( words) . await
407- }
408-
409- async fn write ( & mut self , _words : & [ W ] ) -> Result < ( ) , Self :: Error > {
410- unimplemented ! ( "Not supported for simplex receiver" )
411- }
412-
413- async fn transfer (
414- & mut self ,
415- _read : & mut [ W ] ,
416- _write : & [ W ] ,
417- ) -> Result < ( ) , Self :: Error > {
418- unimplemented ! ( "Not supported for simplex receiver" )
419- }
420-
421- async fn transfer_in_place (
422- & mut self ,
423- _words : & mut [ W ] ,
424- ) -> Result < ( ) , Self :: Error > {
425- unimplemented ! ( "Not supported for simplex receiver" )
426- }
427-
428- async fn flush ( & mut self ) -> Result < ( ) , Self :: Error > {
429- // This is handled within each of the above functions
430- Ok ( ( ) )
431- }
432- }
433-
434- impl < SPI , TX , RX , W > SpiBus < W > for SpiDma < SPI , DmaDuplex < SPI , W , TX , RX > , W >
435- where
436- SPI : Instance + Waker ,
437- W : Word + DmaWord ,
438- TX : DmaChannel ,
439- RX : DmaChannel ,
440- {
441- async fn read ( & mut self , words : & mut [ W ] ) -> Result < ( ) , Self :: Error > {
442- self . read_dma ( words) . await
443- }
444-
445- async fn write ( & mut self , words : & [ W ] ) -> Result < ( ) , Self :: Error > {
446- self . write_dma ( words) . await
447- }
448-
449- async fn transfer (
450- & mut self ,
451- read : & mut [ W ] ,
452- write : & [ W ] ,
453- ) -> Result < ( ) , Self :: Error > {
454- self . transfer_dma ( read, write) . await
455- }
456-
457- async fn transfer_in_place (
458- & mut self ,
459- words : & mut [ W ] ,
460- ) -> Result < ( ) , Self :: Error > {
461- self . transfer_inplace_dma ( words) . await
462- }
463-
464- async fn flush ( & mut self ) -> Result < ( ) , Self :: Error > {
465- // This is handled within each of the above functions
466- Ok ( ( ) )
467- }
468- }
469-
470396struct SpiDmaFuture < ' a , SPI : Instance , MODE , W : Word > {
471397 spi : & ' a mut SpiDma < SPI , MODE , W > ,
472398}
0 commit comments