Skip to content

Commit d863307

Browse files
committed
Use DMA for transfers.
1 parent 3e248c4 commit d863307

File tree

1 file changed

+43
-11
lines changed

1 file changed

+43
-11
lines changed

firmware/hackrf_usb/usb_api_transceiver.c

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "operacake_sctimer.h"
2828

2929
#include <libopencm3/cm3/vector.h>
30+
#include <libopencm3/lpc43xx/gpdma.h>
3031
#include "usb_buffer.h"
3132
#include "usb_api_m0_state.h"
3233

@@ -40,6 +41,7 @@
4041
#include "usb.h"
4142
#include "usb_queue.h"
4243
#include "platform_detect.h"
44+
#include "gpdma.h"
4345

4446
#include <stddef.h>
4547
#include <string.h>
@@ -50,7 +52,10 @@
5052
#define USB_TRANSFER_SIZE 0x4000
5153
#define DMA_TRANSFER_SIZE 0x2000
5254

55+
#define DMA_CHANNEL 1
56+
5357
uint32_t dma_started, usb_started, usb_completed;
58+
volatile bool dma_busy;
5459

5560
typedef struct {
5661
uint32_t freq_mhz;
@@ -320,6 +325,7 @@ void transceiver_shutdown(void)
320325

321326
void transceiver_startup(const transceiver_mode_t mode)
322327
{
328+
dma_busy = false;
323329
dma_started = 0;
324330
usb_started = 0;
325331
usb_completed = 0;
@@ -409,15 +415,43 @@ usb_request_status_t usb_vendor_request_set_rx_overrun_limit(
409415
return USB_REQUEST_STATUS_OK;
410416
}
411417

412-
void transceiver_start_dma(void* src, void* dest, size_t size, void (*callback)(size_t))
418+
void transceiver_start_dma(void* src, void* dest, size_t size)
413419
{
414-
memcpy(dest, src, size);
415-
callback(size);
420+
uint32_t num_transfers = size >> 2;
421+
gpdma_controller_enable();
422+
GPDMA_CSRCADDR(DMA_CHANNEL) = (uint32_t) src;
423+
GPDMA_CDESTADDR(DMA_CHANNEL) = (uint32_t) dest;
424+
GPDMA_CLLI(DMA_CHANNEL) = 0;
425+
GPDMA_CCONTROL(DMA_CHANNEL) = GPDMA_CCONTROL_TRANSFERSIZE(num_transfers) |
426+
GPDMA_CCONTROL_SBSIZE(7) // 256-transfer src bursts
427+
| GPDMA_CCONTROL_DBSIZE(7) // 256-transfer dst bursts
428+
| GPDMA_CCONTROL_SWIDTH(2) // 32-bit src transfers
429+
| GPDMA_CCONTROL_DWIDTH(2) // 32-bit dst transfers
430+
| GPDMA_CCONTROL_S(0) // AHB Master 0
431+
| GPDMA_CCONTROL_D(1) // AHB Master 1
432+
| GPDMA_CCONTROL_SI(1) // increment source
433+
| GPDMA_CCONTROL_DI(1) // increment destination
434+
| GPDMA_CCONTROL_PROT1(0) // user mode
435+
| GPDMA_CCONTROL_PROT2(0) // not bufferable
436+
| GPDMA_CCONTROL_PROT3(0) // not cacheable
437+
| GPDMA_CCONTROL_I(1); // interrupt enabled
438+
GPDMA_CCONFIG(DMA_CHANNEL) = GPDMA_CCONFIG_FLOWCNTRL(0) // memory-to-memory
439+
| GPDMA_CCONFIG_IE(0) // no error interrupt
440+
| GPDMA_CCONFIG_ITC(1) // terminal count interrupt
441+
| GPDMA_CCONFIG_L(0) // do not lock
442+
| GPDMA_CCONFIG_H(0); // do not halt
443+
GPDMA_INTTCCLEAR = (1 << DMA_CHANNEL);
444+
nvic_enable_irq(NVIC_DMA_IRQ);
445+
gpdma_channel_enable(DMA_CHANNEL);
446+
dma_busy = true;
416447
}
417448

418-
void transceiver_dma_transfer_complete(size_t bytes_transferred)
449+
void dma_isr()
419450
{
420-
m0_state.m4_count += bytes_transferred;
451+
gpdma_channel_disable(DMA_CHANNEL);
452+
GPDMA_INTTCCLEAR = (1 << DMA_CHANNEL);
453+
m0_state.m4_count += DMA_TRANSFER_SIZE;
454+
dma_busy = false;
421455
}
422456

423457
void transceiver_bulk_transfer_complete(void* user_data, unsigned int bytes_transferred)
@@ -438,15 +472,14 @@ void rx_mode(uint32_t seq)
438472
uint32_t data_available = data_gathered - dma_started;
439473
uint32_t space_in_use = usb_completed - dma_completed;
440474
uint32_t space_available = USB_BULK_BUFFER_SIZE - space_in_use;
441-
if ((data_available >= DMA_TRANSFER_SIZE) &&
475+
if (!dma_busy && (data_available >= DMA_TRANSFER_SIZE) &&
442476
(space_available >= DMA_TRANSFER_SIZE)) {
443477
uint32_t samp_offset = dma_started & USB_SAMP_BUFFER_MASK;
444478
uint32_t bulk_offset = dma_started & USB_BULK_BUFFER_MASK;
445479
transceiver_start_dma(
446480
&usb_samp_buffer[samp_offset],
447481
&usb_bulk_buffer[bulk_offset],
448-
DMA_TRANSFER_SIZE,
449-
transceiver_dma_transfer_complete);
482+
DMA_TRANSFER_SIZE);
450483
dma_started += DMA_TRANSFER_SIZE;
451484
}
452485
if ((m0_state.m4_count - usb_started) >= USB_TRANSFER_SIZE) {
@@ -490,15 +523,14 @@ void tx_mode(uint32_t seq)
490523
uint32_t data_available = usb_completed - dma_started;
491524
uint32_t space_in_use = dma_completed - data_used;
492525
uint32_t space_available = USB_SAMP_BUFFER_SIZE - space_in_use;
493-
if ((data_available >= DMA_TRANSFER_SIZE) &&
526+
if (!dma_busy && (data_available >= DMA_TRANSFER_SIZE) &&
494527
(space_available >= DMA_TRANSFER_SIZE)) {
495528
uint32_t samp_offset = dma_started & USB_SAMP_BUFFER_MASK;
496529
uint32_t bulk_offset = dma_started & USB_BULK_BUFFER_MASK;
497530
transceiver_start_dma(
498531
&usb_bulk_buffer[bulk_offset],
499532
&usb_samp_buffer[samp_offset],
500-
DMA_TRANSFER_SIZE,
501-
transceiver_dma_transfer_complete);
533+
DMA_TRANSFER_SIZE);
502534
dma_started += DMA_TRANSFER_SIZE;
503535
}
504536
if ((usb_started - m0_state.m4_count) <= USB_TRANSFER_SIZE) {

0 commit comments

Comments
 (0)