I'd like to add the configuration of linflexd1 as UART and DMA setup. Maybe this helps, analysing my problem.
Partially this is code from the MQX UART driver, which I extended for testing purposes, partially it is taken from sample code and/or own libraries.
The DMA transfer is working, but I get additional bytes (sometimes) with the value zero in the destination buffer.
Any help is appreciated.
Thanks in advance.
Setup of UART DMA on Channel 4
#define BT_DMA_CHANNEL 4
EDMA.CR.B.ERCA = 1; // Round Robin Channel Arbitration is enabled
uint8_t channel = BT_DMA_CHANNEL; // use DMA channel 4 for UART RX
uint8_t source = 33; // DMA MUX Source Number, See MPC5645S Reference Manual, page 645
/* Configure DMA Channel Mux
*/
DMAMUX.CHCONFIG[channel].R = 0; /* Disable and clear mux channel */
DMAMUX.CHCONFIG[channel].B.SOURCE = source; /* Assign source with channel */
/* Disable and clear EDMA for desired channel
*/
EDMA.CERQ.B.CERQ = BT_DMA_CHANNEL; // Clear enable DMA request
EDMA.CEEI.B.CEEI = BT_DMA_CHANNEL; // Clear enable error interrupt
EDMA.CERR.B.CER = BT_DMA_CHANNEL; // Clear DMA error
EDMA.CDNE.B.CDNE = BT_DMA_CHANNEL; // Clear Done Status bit
EDMA.CPR[channel].R = 0; // Channel priority
struct EDMA_TCD_STD_tag tcd_uart;
memset((void*)&tcd_uart, 0, sizeof(tcd_uart)); // Clear structure
// tcd configuration as described in MPC5645S Reference Manual, page 1032
tcd_uart.SOFF = 0; // no source increment
tcd_uart.SSIZE = 0; // size = 1byte
tcd_uart.DOFF = 1; // byte-wise increment
tcd_uart.DSIZE = 0; // byte-wise transfer
tcd_uart.NBYTESu.B.NBYTES = 1; // minor loop transfer: 1 byte
tcd_uart.D_REQ = 1; // Disable DMA after major iteration finished
tcd_uart.INT_MAJ = 1; // Interrupt after major iteration count finished
tcd_uart.START = 0; // Do not start manually
// Write TCD for channel 4
memcpy((void*)&EDMA.TCD[BT_DMA_CHANNEL], tcd, sizeof(struct EDMA_TCD_STD_tag));
// Enable DMA RX interrupt for DMA channel 4
_int_install_isr(MPXD20_INTC_EDMA_CHANNEL_0_VECTOR + BT_DMA_CHANNEL, bt_dma_rx_interrupt_handler, 0);
_bsp_int_init(MPXD20_INTC_EDMA_CHANNEL_0_VECTOR + BT_DMA_CHANNEL, 4, 0, TRUE);
// calculate source and destination addresses
uint32_t src_addr = (uint32_t) ((char*) &linflexd_ptr->BDRM[3]);
uint32_t dest_addr = (uint32_t)&s_bt_dma_buffer;
uint16_t count = 4; // Major iteration counter: 4.
// Set Source and Destination addresses, major iteration counter (count) and enable channel
EDMA.CDNE.B.CDNE = channel; // Clear DONE status
EDMA.TCD[channel].SADDR = s_address;
EDMA.TCD[channel].DADDR = d_address;
EDMA.TCD[channel].BITER = count;
EDMA.TCD[channel].CITER = count;
EDMA.SERQ.B.SERQ = channel; // Set enable DMA request
DMAMUX.CHCONFIG[channel].B.ENBL = 1; // Enable mux channel
Initialisation of UART1
uartcr = LINFLEXD_UARTCR_UART; // Enable UART Mode
uartcr |= LINFLEXD_UARTCR_RFBM; // Enable FIFO mode for RX buffer (mandatory for DMA)
uartcr |= LINFLEXD_UARTCR_WL0; // UART word length: 8bit
linflexd_ptr = (VLINFLEXD_1_2_3_REG_STRUCT_PTR) io_info_ptr->LINFLEXD_PTR; // Cast linflexd ptr, as linflex 1,2 and 3 structure differs from linflex0
// Save interrupt enable state - reconfigure may be done from polled or interrupt mode driver
linier = linflexd_ptr->LINIER;
/* Go into init mode */
linflexd_ptr->LINCR1 = LINFLEXD_LINCR1_INIT;
linflexd_ptr->LINCR1 = LINFLEXD_LINCR1_INIT;
/* Select UART mode and set parameters */
linflexd_ptr->UARTCR = LINFLEXD_UARTCR_UART;
linflexd_ptr->UARTCR = uartcr;
/* Calculate baud rate */
lfdiv = (io_info_ptr->INIT.CLOCK_SPEED*2/io_info_ptr->INIT.BAUD_RATE + 1)/2;
linflexd_ptr->LINFBRR = lfdiv & 0xf;
linflexd_ptr->LINIBRR = lfdiv>>4;
/* Disable interrupts */
linflexd_ptr->LINIER = 0;
/* Enable Tx and Rx */
uartcr |= LINFLEXD_UARTCR_RXEN | LINFLEXD_UARTCR_TXEN;
linflexd_ptr->UARTCR = uartcr;
// Enable DMA RX Interrupt
linflexd_ptr->DMARXE = 0x0000ffff; // taken from sample code. Channels can't be enabled individually.
/* Leave init mode */
linflexd_ptr->LINCR1 &= ~LINFLEXD_LINCR1_INIT;
/* Restore interrupt enable state */
linflexd_ptr->LINIER = linier;