Here is a KSDK 2.0 based implementation of continuous RX and TX using DMA. It is a mashup of the scatter_gather and lpuart > edma_transfer examples. You can jump into a while(1) in very low power wait mode after calling this function and it will continue running. The RX side writes an 8-element buffer destAddr[] which behaves as a circular buffer. You can get the DMAMGR _* functions from the fsl_dma_manager module in the KSDK.
#define BUFFER_LENGTH 8U
#define HALF_BUFFER_LENGTH (BUFFER_LENGTH / 2U)
#define TCD_QUEUE_SIZE 1U
#define LPUART0SRC_MCGIRCLK 0x3U
#define MID_UART_BAUD 115200
#define TEST_DIR_TX true
#define TEST_DIR_RX false
void uart_dma_test(uint8_t lpUartClkSrc, uint32_t baud, bool testDir)
{
edma_tcd_t tcd;
lpuart_config_t lpuartConfig;
lpuart_transfer_t xfer;
uint8_t srcAddr[] = "LPUART EDMA";
uint8_t destAddr[BUFFER_LENGTH] = {0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U};
edma_transfer_config_t transferConfig;
edma_tcd_t *tcdMemoryPoolPtr;
edma_config_t userConfig;
BOARD_InitPins();
CLOCK_SetLpuartClock(lpUartClkSrc);
/* Initialize the LPUART. */
/*
* lpuartConfig.baudRate_Bps = 115200U;
* lpuartConfig.parityMode = kLPUART_ParityDisabled;
* lpuartConfig.stopBitCount = kLPUART_OneStopBit;
* lpuartConfig.txFifoWatermark = 0;
* lpuartConfig.rxFifoWatermark = 0;
* lpuartConfig.enableTx = false;
* lpuartConfig.enableRx = false;
*/
LPUART_GetDefaultConfig(&lpuartConfig);
lpuartConfig.baudRate_Bps = baud;
/* Configure DMA. */
DMAMGR_Init();
if(TEST_DIR_TX == testDir)
{
lpuartConfig.enableTx = true;
/* Request dma channels from DMA manager. */
DMAMGR_RequestChannel(LPUART_TX_DMA_REQUEST, LPUART_TX_DMA_CHANNEL, &g_lpuartTxEdmaHandle);
}
else
{
lpuartConfig.enableRx = true;
DMAMGR_RequestChannel(LPUART_RX_DMA_REQUEST, LPUART_RX_DMA_CHANNEL, &g_lpuartRxEdmaHandle);
}
/*
* userConfig.enableRoundRobinArbitration = false;
* userConfig.enableHaltOnError = true;
* userConfig.enableContinuousLinkMode = false;
* userConfig.enableDebugMode = false;
*/
EDMA_GetDefaultConfig(&userConfig);
EDMA_Init(DMA0, &userConfig);
/* This sets DMA_ERQ */
if(TEST_DIR_TX == testDir) {
EDMA_CreateHandle(&g_EDMA_Handle, DMA0, LPUART_TX_DMA_CHANNEL);
}
else {
EDMA_CreateHandle(&g_EDMA_Handle, DMA0, LPUART_RX_DMA_CHANNEL);
}
EDMA_ResetChannel(g_EDMA_Handle.base, g_EDMA_Handle.channel);
/* Allocate TCD memory pool */
tcdMemoryPoolPtr = (edma_tcd_t *)malloc(sizeof(edma_tcd_t) * (TCD_QUEUE_SIZE + 1));
if (tcdMemoryPoolPtr != NULL)
{
tcdMemoryPoolPtr = (edma_tcd_t *)((uint32_t)(tcdMemoryPoolPtr + 1) & (~0x1FU)); // align on 32-byte boundary
EDMA_InstallTCDMemory(&g_EDMA_Handle, tcdMemoryPoolPtr, TCD_QUEUE_SIZE);
EDMA_TcdReset(tcdMemoryPoolPtr);
if(TEST_DIR_TX == testDir)
{
xfer.data = srcAddr;
xfer.dataSize = sizeof(srcAddr) - 1;
/* Configure and submit transfer structure 1 */
EDMA_PrepareTransfer(&transferConfig,
xfer.data,
sizeof(uint8_t),
(void *)LPUART_GetDataRegisterAddress(DEMO_LPUART),
sizeof(uint8_t),
sizeof(uint8_t),
xfer.dataSize,
kEDMA_MemoryToPeripheral);
}else
{
/* Configure and submit transfer structure 1 */
EDMA_PrepareTransfer(&transferConfig,
(void *)LPUART_GetDataRegisterAddress(DEMO_LPUART),
sizeof(uint8_t),
destAddr,
sizeof(uint8_t),
sizeof(uint8_t),
BUFFER_LENGTH,
kEDMA_PeripheralToMemory);
}
EDMA_SubmitTransfer(&g_EDMA_Handle, &transferConfig);
/* Clear DREQ and INTMAJOR in HW */
if(TEST_DIR_TX == testDir)
{
DMA0->TCD[LPUART_TX_DMA_CHANNEL].CSR &= ~(DMA_CSR_DREQ_MASK | DMA_CSR_INTMAJOR_MASK);
DMA0->TCD[LPUART_TX_DMA_CHANNEL].CSR |= DMA_CSR_ESG_MASK;
}
else
{
DMA0->TCD[LPUART_RX_DMA_CHANNEL].CSR &= ~(DMA_CSR_DREQ_MASK | DMA_CSR_INTMAJOR_MASK);
DMA0->TCD[LPUART_RX_DMA_CHANNEL].CSR |= DMA_CSR_ESG_MASK;
}
tcdMemoryPoolPtr->CSR = DMA_CSR_ESG_MASK; // enable scatter gather
}
EDMA_StartTransfer(&g_EDMA_Handle);
/* This will set LPTMR0[CTRL] TE bit per lpuartConfig.enableTx setting */
LPUART_Init(LPUART0, &lpuartConfig, CLOCK_GetFreq(DEMO_LPUART_CLKSRC));
if(TEST_DIR_TX == testDir) {
/* Do not use periodic trigger */
DMAMUX0->CHCFG[LPUART_TX_DMA_CHANNEL] &= ~(DMAMUX_CHCFG_TRIG_MASK);
/* Enable LPUART TX EDMA. */
LPUART_EnableTxDMA(DEMO_LPUART, true);
}
else {
/* Do not use periodic trigger */
DMAMUX0->CHCFG[LPUART_RX_DMA_CHANNEL] &= ~(DMAMUX_CHCFG_TRIG_MASK);
/* Enable LPUART RX EDMA. */
LPUART_EnableRxDMA(DEMO_LPUART, true);
}
}
app_power_mode_t vlpw_4m_irclk_mid_baud_tx_dir_uart_test(void)
{
go_4m_0p8m_blpi_mode();
uart_idd_test(LPUART0SRC_MCGIRCLK, MID_UART_BAUD, TEST_DIR_TX);
return kAPP_PowerModeVlpw;
}
Hope it helps.