|
26 | 26 | #include <stdbool.h> |
27 | 27 | #include <stddef.h> |
28 | 28 |
|
| 29 | +#include <libopencm3/lpc43xx/m4/nvic.h> |
| 30 | +#include <libopencm3/cm3/nvic.h> |
| 31 | + |
29 | 32 | #include <fixed_point.h> |
| 33 | +#include <gpdma.h> |
30 | 34 | #include <hackrf_core.h> |
31 | 35 | #include <hackrf_ui.h> |
32 | 36 | #include <m0_state.h> |
@@ -75,6 +79,8 @@ typedef struct { |
75 | 79 |
|
76 | 80 | set_sample_r_params_t set_sample_r_params; |
77 | 81 |
|
| 82 | +void transceiver_dma_setup(void); |
| 83 | + |
78 | 84 | usb_request_status_t usb_vendor_request_set_baseband_filter_bandwidth( |
79 | 85 | usb_endpoint_t* const endpoint, |
80 | 86 | const usb_transfer_stage_t stage) |
@@ -347,6 +353,8 @@ void transceiver_startup(const transceiver_mode_t mode) |
347 | 353 | usb_started = 0; |
348 | 354 | usb_completed = 0; |
349 | 355 |
|
| 356 | + transceiver_dma_setup(); |
| 357 | + |
350 | 358 | radio_switch_opmode(&radio, mode); |
351 | 359 |
|
352 | 360 | hackrf_ui()->set_transceiver_mode(mode); |
@@ -460,15 +468,63 @@ usb_request_status_t usb_vendor_request_get_buffer_size( |
460 | 468 | return USB_REQUEST_STATUS_OK; |
461 | 469 | } |
462 | 470 |
|
| 471 | +/* clang-format off */ |
| 472 | + |
| 473 | +// Which GPDMA channel to use. |
| 474 | +const uint32_t DMA_CHANNEL = 1; |
| 475 | + |
| 476 | +// GPDMA CCONFIG register setting. |
| 477 | +const uint32_t DMA_CONFIG = |
| 478 | + GPDMA_CCONFIG_FLOWCNTRL(0) // memory-to-memory |
| 479 | + | GPDMA_CCONFIG_IE(0) // no error interrupt |
| 480 | + | GPDMA_CCONFIG_ITC(1) // terminal count interrupt |
| 481 | + | GPDMA_CCONFIG_L(0) // do not lock |
| 482 | + | GPDMA_CCONFIG_H(0); // do not halt |
| 483 | + |
| 484 | +// GPDMA CCONTROL register setting (excluding TRANSFERSIZE field). |
| 485 | +const uint32_t DMA_CONTROL = |
| 486 | + GPDMA_CCONTROL_SBSIZE(7) // 256-transfer src bursts |
| 487 | + | GPDMA_CCONTROL_DBSIZE(7) // 256-transfer dst bursts |
| 488 | + | GPDMA_CCONTROL_SWIDTH(2) // 32-bit src transfers |
| 489 | + | GPDMA_CCONTROL_DWIDTH(2) // 32-bit dst transfers |
| 490 | + | GPDMA_CCONTROL_S(0) // AHB Master 0 |
| 491 | + | GPDMA_CCONTROL_D(1) // AHB Master 1 |
| 492 | + | GPDMA_CCONTROL_SI(1) // increment source |
| 493 | + | GPDMA_CCONTROL_DI(1) // increment destination |
| 494 | + | GPDMA_CCONTROL_PROT1(0) // user mode |
| 495 | + | GPDMA_CCONTROL_PROT2(0) // not bufferable |
| 496 | + | GPDMA_CCONTROL_PROT3(0) // not cacheable |
| 497 | + | GPDMA_CCONTROL_I(1); // interrupt enabled |
| 498 | + |
| 499 | +/* clang-format on */ |
| 500 | + |
| 501 | +// Called before any sequence of DMA transfers. |
| 502 | +void transceiver_dma_setup(void) |
| 503 | +{ |
| 504 | + gpdma_controller_enable(); |
| 505 | + GPDMA_CCONFIG(DMA_CHANNEL) = DMA_CONFIG; |
| 506 | + GPDMA_CCONTROL(DMA_CHANNEL) = DMA_CONTROL; |
| 507 | + GPDMA_CLLI(DMA_CHANNEL) = 0; |
| 508 | + GPDMA_INTTCCLEAR = (1 << DMA_CHANNEL); |
| 509 | + nvic_enable_irq(NVIC_DMA_IRQ); |
| 510 | +} |
| 511 | + |
| 512 | +// Called to start each DMA transfer. |
463 | 513 | void transceiver_start_dma(void* src, void* dest, size_t size) |
464 | 514 | { |
| 515 | + uint32_t num_transfers = size >> 2; |
| 516 | + GPDMA_CCONTROL(DMA_CHANNEL) = DMA_CONTROL | num_transfers; |
| 517 | + GPDMA_CSRCADDR(DMA_CHANNEL) = (uint32_t) src; |
| 518 | + GPDMA_CDESTADDR(DMA_CHANNEL) = (uint32_t) dest; |
465 | 519 | dma_pending = size; |
466 | | - memcpy(dest, src, size); |
467 | | - dma_isr(); |
| 520 | + gpdma_channel_enable(DMA_CHANNEL); |
468 | 521 | } |
469 | 522 |
|
| 523 | +// Called when a DMA transfer completes. |
470 | 524 | void dma_isr(void) |
471 | 525 | { |
| 526 | + gpdma_channel_disable(DMA_CHANNEL); |
| 527 | + GPDMA_INTTCCLEAR = (1 << DMA_CHANNEL); |
472 | 528 | m0_state.m4_count += dma_pending; |
473 | 529 | dma_pending = 0; |
474 | 530 | } |
|
0 commit comments