I'm trying to use DMA with USART3 to grab some incoming serial data and am having some problems. The interrupt is firing too quickly (chars sent way below TRANSFER_SIZE) and the data isn't written to the right spot (seeing a stack of zeros).
The libmaple example here (https://github.com/leaflabs/libmaple/blob/master/examples/test-usart-dma.cpp) is woefully out of date. Does anyone have a better example?
My (truncated) code (v0.0.12):
#include <dma.h>
#define TRANSFER_SIZE 16
char bytesReceived[TRANSFER_SIZE];
volatile bool dataReady = false;
void DMAEvent(){
dma_irq_cause event = dma_get_irq_cause(DMA1, DMA_CH3);
switch(event) {
case DMA_TRANSFER_COMPLETE:
dma_disable(DMA1, DMA_CH3);
SerialUSB.println("done.");
dataReady = true;
break;
}
}
void setup() {
dataReady = false;
Serial3.begin(9600);
USART3->regs->CR3 = USART_CR3_DMAR; // set DMA request on Rx bit
dma_init(DMA1);
dma_setup_transfer(
DMA1,
DMA_CH3,
&USART3->regs->DR,
DMA_SIZE_8BITS,
bytesReceived,
DMA_SIZE_8BITS,
(DMA_MINC_MODE | DMA_CIRC_MODE | DMA_FROM_MEM | DMA_TRNS_CMPLT));
dma_attach_interrupt(DMA1, DMA_CH3, DMAEvent);
dma_set_priority(DMA1, DMA_CH3, DMA_PRIORITY_VERY_HIGH);
dma_set_num_transfers(DMA1, DMA_CH3, TRANSFER_SIZE);
dma_enable(DMA1, DMA_CH3);
}
void loop() {
if(dataReady)
{
SerialUSB.println("read it back...");
dataReady = false;
for(int i = 0; i < TRANSFER_SIZE; ++i)
{
SerialUSB.print(bytesReceived[i]);
}
}
}
Thanks!
John