I am using DMA for UART receive interrupt. I have configured DMA as per example code provided to me from NXP team. The code has one issue, sometimes the code continuously loops in DMA interrupt. The uart interrupt is configured for IDLE timeout.
Following is code provided and just modified for UART1,
void DMA_init(void)
{
/* This is an initialization place holder for: */
/* 1. Enabling DMA MUX clock PCC_PCCn[PCC_DMAMUX_INDEX] (not needed when START bit used) */
/* 2. Enabling desired channels by setting ERQ bit (not needed when START bit used) */
PCC->PCCn[PCC_DMAMUX_INDEX] |= PCC_PCCn_CGC_MASK; // CGC=1: Clock enabled for DMAMUX0
DMAMUX->CHCFG[DMA_CHANNEL_LPUART0_RX] &= ~ DMAMUX_CHCFG_ENBL(1); // Disabling the DMA channel
DMAMUX->CHCFG[DMA_CHANNEL_LPUART0_RX] |= DMAMUX_CHCFG_SOURCE(4); // LPUART1 RX is the source of the DMA0 channel
DMAMUX->CHCFG[DMA_CHANNEL_LPUART0_RX] |= DMAMUX_CHCFG_ENBL(1); // Enabling the DMA channel
DMA->ERQ |= 1;//Enable Channel 0.
// DMAMUX->CHCFG[1] &= ~ DMAMUX_CHCFG_ENBL(1); // Disabling the DMA channel
// DMAMUX->CHCFG[1] |= DMAMUX_CHCFG_SOURCE(3); // LPUART0 TX is the source of the DMA0 channel
// DMAMUX->CHCFG[1] |= DMAMUX_CHCFG_ENBL(1); // Enabling the DMA channel
}
void DMA_TCD_init(void)
{
/*!
* TCD0: Transfers string to a single memory location
* ===================================================
*/
DMA->TCD[DMA_CHANNEL_LPUART0_RX].SADDR = DMA_TCD_SADDR_SADDR((uint32_t volatile) &LPUART1->DATA); /* Source Address. */
DMA->TCD[DMA_CHANNEL_LPUART0_RX].SOFF = DMA_TCD_SOFF_SOFF(0); /* Src. addr add 0 byte after Transfers */
DMA->TCD[DMA_CHANNEL_LPUART0_RX].ATTR = DMA_TCD_ATTR_SMOD(0) | /* Src. modulo feature not used */
DMA_TCD_ATTR_SSIZE(0) | /* Src. read 2**0 =1 byte per transfer */
DMA_TCD_ATTR_DMOD(0) | /* Dest. modulo feature not used */
DMA_TCD_ATTR_DSIZE(0); /* Dest. write 2**0 =1 byte per trans. */
DMA->TCD[DMA_CHANNEL_LPUART0_RX].NBYTES.MLNO = DMA_TCD_NBYTES_MLNO_NBYTES(1); /* Transfer 1 byte /minor loop */
DMA->TCD[DMA_CHANNEL_LPUART0_RX].SLAST = DMA_TCD_SLAST_SLAST(0); /* Src addr change after major loop */
DMA->TCD[DMA_CHANNEL_LPUART0_RX].DADDR = DMA_TCD_DADDR_DADDR(pRxBuff); /* Destination Address. */
DMA->TCD[DMA_CHANNEL_LPUART0_RX].DOFF = DMA_TCD_DOFF_DOFF(1); /* Dest adr offset 1 byte after transfer */
DMA->TCD[DMA_CHANNEL_LPUART0_RX].CITER.ELINKNO= DMA_TCD_CITER_ELINKNO_CITER(MAX_BYTE_PER_TRANSFER) | /* minor loop iterations */
DMA_TCD_CITER_ELINKNO_ELINK(0); /* No minor loop chan link */
DMA->TCD[DMA_CHANNEL_LPUART0_RX].DLASTSGA = DMA_TCD_DLASTSGA_DLASTSGA(0); /* No dest chg after major loop */
DMA->TCD[DMA_CHANNEL_LPUART0_RX].CSR = DMA_TCD_CSR_START(0) | /* Clear START status flag */
DMA_TCD_CSR_INTMAJOR(1) | /* IRQ after major loop */
DMA_TCD_CSR_INTHALF(0) | /* No IRQ after 1/2 major loop */
DMA_TCD_CSR_DREQ(1) | /* Disable chan after major loop */
DMA_TCD_CSR_ESG(0) | /* Disable Scatter Gather */
DMA_TCD_CSR_MAJORELINK(0) | /* No major loop chan link */
DMA_TCD_CSR_ACTIVE(0) | /* Clear ACTIVE status flag */
DMA_TCD_CSR_DONE(0) | /* Clear DONE status flag */
DMA_TCD_CSR_MAJORLINKCH(0) | /* Chan # if major loop ch link */
DMA_TCD_CSR_BWC(0); /* No eDMA stalls after R/W */
DMA->TCD[DMA_CHANNEL_LPUART0_RX].BITER.ELINKNO= DMA_TCD_BITER_ELINKNO_BITER(MAX_BYTE_PER_TRANSFER) | /* Initial iteration count */
DMA_TCD_BITER_ELINKNO_ELINK(0); /* No minor loop chan link */
}
#define MAX_BYTE_PER_TRANSFER 512, i tried increasing this to 768
Max data that is receive on UART is 427 bytes.
UART int handler
void uart1_irqHandler()
{
uint8_t lu8Data = 0;
LPUART_Type * base = LPUARTx[1];
if (base->STAT & LPUART_STAT_RDRF_MASK)
{
// receive data from uart if dma is disabled
lu8Data = base->DATA; // type cast to 8 bit data
callback_uart1_rx(lu8Data , 1);
}
// idle timeout
if (base->STAT & LPUART_STAT_IDLE_MASK)
{
base->STAT |= LPUART_STAT_IDLE_MASK; //clear the Idle flag.
g_number_of_bytes_Received = MAX_BYTE_PER_TRANSFER - DMA->TCD[DMA_CHANNEL_LPUART0_RX].CITER.ELINKNO;//calculate the total received data.
callback_uart1_rx(pRxBuff, g_number_of_bytes_Received );
/* reset the DMA for LPUART reception*/
DMA->TCD[DMA_CHANNEL_LPUART0_RX].CITER.ELINKNO = DMA_TCD_CITER_ELINKNO_CITER(MAX_BYTE_PER_TRANSFER) | /* minor loop iterations */
DMA_TCD_CITER_ELINKNO_ELINK(0); /* No minor loop chan link */
DMA->TCD[DMA_CHANNEL_LPUART0_RX].DADDR = DMA_TCD_DADDR_DADDR(pRxBuff); /* Destination Address. */
}
}
If any help is provided for diagnosing this behavior that would be much helpful