@@ -561,6 +561,71 @@ void tx_mode(uint32_t seq)
561561 }
562562 }
563563
564+ // Host has now requested to stop TX. We won't initiate any further USB
565+ // transfers into the bulk buffer. However, we should make sure all
566+ // data currently in the USB bulk buffer reaches the sample buffer.
567+
568+ if ((usb_started - usb_completed ) > 0 ) {
569+ // We were part way through a 16KB firmware-side transfer when
570+ // the transceiver mode change request to stop TX was received.
571+ //
572+ // We want to include the contents of that partial transfer in
573+ // the data we move to the sample buffer.
574+ //
575+ // The transfer was already stopped by usb_endpoint_flush(),
576+ // which was called from request_transceiver_mode().
577+ //
578+ // We will not have had a callback, and the transfer descriptor
579+ // (dTD) will not have been updated, since the transfer did not
580+ // complete.
581+ //
582+ // However, as long as we haven't started a new transfer, we
583+ // can retrieve the partial byte count from the transfer
584+ // overlay in the endpoint queue head (dQH) (UM10503 25.9.1).
585+
586+ usb_queue_head_t * const qh =
587+ usb_queue_head (usb_endpoint_bulk_out .address );
588+ unsigned int bytes_remaining =
589+ (qh -> total_bytes & USB_TD_DTD_TOKEN_TOTAL_BYTES_MASK ) >>
590+ USB_TD_DTD_TOKEN_TOTAL_BYTES_SHIFT ;
591+ unsigned int bytes_transferred = USB_TRANSFER_SIZE - bytes_remaining ;
592+ usb_completed += bytes_transferred ;
593+ }
594+
595+ // Feed the remaining data from the bulk buffer to the sample buffer.
596+ // At this point, we also need to handle the case where there is less data
597+ // to be transferred to the sample buffer than a full-sized DMA transfer.
598+
599+ // Any remainder of less than 4 bytes will be ignored; this is the chunk
600+ // size of our DMA transfers.
601+ while ((usb_completed - m0_state .m4_count ) >= 4 ) {
602+ uint32_t data_used = m0_state .m0_count ;
603+ uint32_t data_available = usb_completed - dma_started ;
604+ uint32_t space_in_use = dma_started - data_used ;
605+ uint32_t space_available = USB_SAMP_BUFFER_SIZE - space_in_use ;
606+ uint32_t samp_offset = dma_started & USB_SAMP_BUFFER_MASK ;
607+ uint32_t bulk_offset = dma_started & USB_BULK_BUFFER_MASK ;
608+ bool ahb_busy = !((data_used ^ dma_started ) & BUF_HALF_MASK );
609+ size_t size = data_available >= DMA_TRANSFER_SIZE ? DMA_TRANSFER_SIZE :
610+ data_available ;
611+ if (dma_pending || ahb_busy || size > space_available ) {
612+ continue ;
613+ }
614+ transceiver_start_dma (
615+ & usb_bulk_buffer [bulk_offset ],
616+ & usb_samp_buffer [samp_offset ],
617+ size );
618+ dma_started += size ;
619+ }
620+
621+ // Wait for the data in the sample buffer to be transmitted.
622+
623+ // Any remainder of less than 32 bytes will be ignored; this is
624+ // the chunk size used by the M0 core to transfer samples to SGPIO.
625+ while ((m0_state .m4_count - m0_state .m0_count ) >= 32 )
626+ ;
627+
628+ // All data received from the host has now been transmitted.
564629 transceiver_shutdown ();
565630}
566631
0 commit comments