Skip to content

Commit 10a9836

Browse files
committed
Flush both buffers before leaving TX mode.
1 parent 94a7c35 commit 10a9836

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

firmware/common/usb.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
#include "usb_type.h"
3131

32+
usb_queue_head_t* usb_queue_head(const uint_fast8_t endpoint_address);
33+
3234
void usb_peripheral_reset(void);
3335
void usb_phy_enable(void);
3436

firmware/hackrf_usb/usb_api_transceiver.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)