22
33use core:: convert:: From ;
44use core:: result:: Result :: { Err , Ok } ;
5+ use embassy_futures:: { block_on, join:: join} ;
6+ use embassy_sync:: blocking_mutex:: raw:: NoopRawMutex ;
7+ use embassy_sync:: zerocopy_channel:: { Channel , Receiver , Sender } ;
58use embedded_hal:: digital:: OutputPin ;
69use embedded_hal_async:: spi:: SpiBus ;
710use num_enum:: { IntoPrimitive , TryFromPrimitive } ;
@@ -34,7 +37,7 @@ fn le_u24_to_u32(bytes: &[u8]) -> u32 {
3437
3538const S_ACK : u8 = 0x06 ;
3639const S_NAK : u8 = 0x15 ;
37- const MAX_BUFFER_SIZE : usize = 2048 ;
40+ const MAX_BUFFER_SIZE : usize = 16 << 20 ;
3841
3942#[ derive( FromBytes , IntoBytes , Unaligned , Immutable ) ]
4043#[ repr( C , packed) ]
@@ -338,7 +341,7 @@ where
338341 }
339342 SerprogCommand :: OSpiOp => {
340343 debug ! ( "Received OSpiOp CMD" ) ;
341- let mut sdata = [ 0_u8 ; MAX_BUFFER_SIZE + 6 ] ;
344+ let mut sdata = [ 0_u8 ; 64 ] ;
342345 self . transport
343346 . read ( sdata. as_mut_slice ( ) )
344347 . await
@@ -347,75 +350,120 @@ where
347350 let op_slen = le_u24_to_u32 ( & sdata[ 0 ..3 ] ) as usize ;
348351 let op_rlen = le_u24_to_u32 ( & sdata[ 3 ..6 ] ) as usize ;
349352
350- let mut rdata = [ 0_u8 ; MAX_BUFFER_SIZE ] ;
353+ let mut usb_rx_spi_tx_buf = [ ( [ 0u8 ; 64 ] , 0 ) ; 4 ] ;
354+ let mut usb_rx_spi_tx_channel: Channel < ' _ , NoopRawMutex , ( [ u8 ; 64 ] , usize ) > =
355+ Channel :: new ( & mut usb_rx_spi_tx_buf) ;
356+ let ( usb_rx, spi_tx) = usb_rx_spi_tx_channel. split ( ) ;
357+
358+ let mut usb_tx_spi_rx_buf = [ ( [ 0u8 ; 64 ] , 0 ) ; 8 ] ;
359+ let mut usb_tx_spi_rx_channel: Channel < ' _ , NoopRawMutex , ( [ u8 ; 64 ] , usize ) > =
360+ Channel :: new ( & mut usb_tx_spi_rx_buf) ;
361+ let ( spi_rx, usb_tx) = usb_tx_spi_rx_channel. split ( ) ;
362+
363+ let usb_task = async |transport : & mut T ,
364+ mut sender : Sender < NoopRawMutex , ( [ u8 ; 64 ] , usize ) > ,
365+ sdata_size : usize ,
366+ sdata_0 : [ u8 ; 64 ] ,
367+ mut receiver : Receiver < NoopRawMutex , ( [ u8 ; 64 ] , usize ) > ,
368+ rdata_size : usize |
369+ -> Result < ( ) , SerprogError > {
370+ // First block
371+ let mut data_to_read = sdata_size;
372+ {
373+ let ( buf, size) = sender. send ( ) . await ;
374+ let block_size = data_to_read. min ( 64 - 6 ) ;
375+ buf[ ..block_size] . copy_from_slice ( & sdata_0[ 6 ..6 + block_size] ) ;
376+ * size = block_size;
377+ sender. send_done ( ) ;
378+ data_to_read -= block_size;
379+ }
380+
381+ while data_to_read > 0 {
382+ let read_size = data_to_read. min ( 64 ) ;
383+ let ( buf, size) = sender. send ( ) . await ;
384+ * size = read_size;
385+ transport. read ( & mut buf[ ..read_size] ) . await . map_err ( |_| {
386+ SerprogError :: TransportRead ( "Error reading OSpiOp data" )
387+ } ) ?;
388+ sender. send_done ( ) ;
389+ data_to_read -= read_size;
390+ }
391+ transport
392+ . write ( & [ S_ACK ] )
393+ . await
394+ . map_err ( |_| SerprogError :: TransportWrite ( "Error writing SBustype ACK" ) ) ?;
351395
352- let sdata = & sdata. as_slice ( ) [ 6 ..6 + op_slen] ;
396+ let mut data_to_send = rdata_size;
397+ while data_to_send > 0 {
398+ let ( buf, size) = receiver. receive ( ) . await ;
399+ let size = * size;
400+ transport. write ( & buf[ ..size] ) . await . map_err ( |_| {
401+ SerprogError :: TransportWrite ( "Error writing SPI read data" )
402+ } ) ?;
403+ receiver. receive_done ( ) ;
404+ data_to_send -= size;
405+ }
406+ Ok ( ( ) )
407+ } ;
353408
354- debug ! (
355- "Starting SPI transfer, sdata: {:?}, rdata: {:?}" ,
356- & sdata[ ..op_slen as usize ] ,
357- & rdata[ ..op_rlen as usize ]
358- ) ;
409+ let spi_task = async |spi : & mut SPI ,
410+ mut receiver : Receiver < NoopRawMutex , ( [ u8 ; 64 ] , usize ) > ,
411+ sdata_size : usize ,
412+ mut sender : Sender < NoopRawMutex , ( [ u8 ; 64 ] , usize ) > ,
413+ rdata_size : usize ,
414+ cs : & mut CS |
415+ -> Result < ( ) , SerprogError > {
416+ spi. flush ( ) . await . map_err ( |_| {
417+ SerprogError :: SpiFlush ( "Error flushing SPI before transfer" )
418+ } ) ?;
419+
420+ cs. set_low ( )
421+ . map_err ( |_| SerprogError :: CsSetLow ( "Error setting CS low" ) ) ?;
422+ let mut data_to_write = sdata_size;
423+ while data_to_write > 0 {
424+ let ( buf, size) = receiver. receive ( ) . await ;
425+ data_to_write -= * size;
426+ spi. write ( & buf[ ..* size] )
427+ . await
428+ . map_err ( |_| SerprogError :: SpiTransfer ( "Error writing OSpiOp data" ) ) ?;
429+ receiver. receive_done ( ) ;
430+ }
431+ let mut data_to_read = rdata_size;
432+ while data_to_read > 0 {
433+ let ( buf, size) = sender. send ( ) . await ;
434+ let read_size = data_to_read. min ( buf. len ( ) ) ;
435+ spi. read ( & mut buf[ ..read_size] )
436+ . await
437+ . map_err ( |_| SerprogError :: SpiTransfer ( "Error reading OSpiOp data" ) ) ?;
438+ * size = read_size;
439+ sender. send_done ( ) ;
440+ data_to_read -= read_size;
441+ }
442+ cs. set_high ( )
443+ . map_err ( |_| SerprogError :: CsSetHigh ( "Error setting CS high" ) ) ?;
444+ debug ! ( "OSpiOp CMD done" ) ;
445+ Ok ( ( ) )
446+ } ;
359447
360- // This call is blocking according to the SPI HAL
361- self . spi
362- . flush ( )
363- . await
364- . map_err ( |_| SerprogError :: SpiFlush ( "Error flushing SPI before transfer" ) ) ?;
365-
366- self . cs
367- . set_low ( )
368- . map_err ( |_| SerprogError :: CsSetLow ( "Error setting CS low" ) ) ?;
369-
370- let mut spi_op =
371- async |spi : & mut SPI , transport : & mut T | -> Result < ( ) , SerprogError > {
372- match spi. write ( & sdata[ ..op_slen as usize ] ) . await {
373- Ok ( _) => {
374- debug ! ( "SPI transfer successful" ) ;
375- debug ! ( "Received data (rdata): {:?}" , & rdata[ ..op_rlen as usize ] ) ;
376- match spi. read ( & mut rdata[ ..op_rlen as usize ] ) . await {
377- Ok ( _) => {
378- debug ! ( "SPI read successful" ) ;
379- debug ! (
380- "Received data (rdata): {:?}" ,
381- & rdata[ ..op_rlen as usize ]
382- ) ;
383- transport. write ( & [ S_ACK ] ) . await . map_err ( |_| {
384- SerprogError :: TransportWrite ( "Error writing OSpiOp ACK" )
385- } ) ?;
386-
387- // Send the full rdata in chunks
388- transport. write ( & rdata[ ..op_rlen as usize ] ) . await . map_err (
389- |_| {
390- SerprogError :: TransportWrite (
391- "Error writing SPI read data" ,
392- )
393- } ,
394- ) ?;
395- }
396- Err ( _) => {
397- error ! ( "SPI read error" ) ;
398- if let Err ( e) = transport. write ( & [ S_NAK ] ) . await {
399- error ! ( "Error writing NAK: {:?}" , e) ;
400- }
401- }
402- }
403- }
404- Err ( _) => {
405- error ! ( "SPI transfer error" ) ;
406- transport. write ( & [ S_NAK ] ) . await . map_err ( |_| {
407- SerprogError :: TransportWrite ( "Error writing OSpiOp NAK" )
408- } ) ?;
409- Err ( SerprogError :: SpiTransfer ( "SPI transfer failed" ) ) ?;
410- }
411- }
412- Ok ( ( ) )
413- } ;
414- embassy_futures:: block_on ( spi_op ( & mut self . spi , & mut self . transport ) ) ?;
415-
416- self . cs
417- . set_high ( )
418- . map_err ( |_| SerprogError :: CsSetHigh ( "Error setting CS high" ) ) ?;
448+ let ( spi_res, usb_res) = block_on ( join (
449+ spi_task (
450+ & mut self . spi ,
451+ spi_tx,
452+ op_slen,
453+ spi_rx,
454+ op_rlen,
455+ & mut self . cs ,
456+ ) ,
457+ usb_task ( & mut self . transport , usb_rx, op_slen, sdata, usb_tx, op_rlen) ,
458+ ) ) ;
459+ if let Err ( spi_err) = spi_res {
460+ self . transport
461+ . write ( & [ S_NAK ] )
462+ . await
463+ . map_err ( |_| SerprogError :: TransportWrite ( "Failed to report SPI failed" ) ) ?;
464+ return Err ( spi_err) ;
465+ }
466+ usb_res?;
419467
420468 Ok ( ( ) )
421469 }
0 commit comments