SDK DMA uart

cancel
Showing results for 
Search instead for 
Did you mean: 

SDK DMA uart

1,203 Views
pietrodicastri
Senior Contributor I

Good morning

I need to install the dma for receiving on the serial port CONTINUOUSLY.

There are examples for using the uart for SDK 2.0, but after the first fill up of the buffer

they stop the service. Is there an example for SDK 2.0 to have a continuous running DMA for receiving??

Or other suggestions welcomed....

 

Thank You

 

Pietro

Labels (1)
Tags (2)
0 Kudos
3 Replies

145 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Pietro,

I think the example code located at the following directory is the UART continuously receiving example:

C:\DriverE\Freescale\SDK2.0_K64F\boards\frdmk64f\driver_examples\uart\edma_transfer\kds

BR

XiangJun Rong

The following code is a forever loop for receiving:

while (1)

    {

        /* If RX is idle and g_rxBuffer is empty, start to read data to g_rxBuffer. */

        if ((!rxOnGoing) && rxBufferEmpty)

        {

            rxOnGoing = true;

            UART_ReceiveEDMA(DEMO_UART, &g_uartEdmaHandle, &receiveXfer);

        }

        /* If TX is idle and g_txBuffer is full, start to send data. */

        if ((!txOnGoing) && txBufferFull)

        {

            txOnGoing = true;

            UART_SendEDMA(DEMO_UART, &g_uartEdmaHandle, &sendXfer);

        }

        /* If g_txBuffer is empty and g_rxBuffer is full, copy g_rxBuffer to g_txBuffer. */

        if ((!rxBufferEmpty) && (!txBufferFull))

        {

            memcpy(g_txBuffer, g_rxBuffer, ECHO_BUFFER_LENGTH);

            rxBufferEmpty = true;

            txBufferFull = true;

        }

    }

0 Kudos

145 Views
pietrodicastri
Senior Contributor I

Hello lxiangjun.rong

Thank You for follow up.

I see the example code. The calls to UART_ReceiveEDMA reinitialize the service for receiving an amount of data than

the dma is stopped the the same UART_ReceiveEDMA need to be recalled.

I need an always active receiving, with an interrupt in the middle and end of the buffer, endless..

I do not want to waste time to reinit the DMA service every time.

Additionally if I need to stop and restart I want to set just the qualified bits without a global reinitialization.

I refer of course to a service having the same size and transfer addresses..

If you have a solution I would be very happy.

Best Regards

Pietro

0 Kudos

145 Views
angusgalloway-b
NXP Employee
NXP Employee

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.

Angus

0 Kudos