LPC55S16 UART Sending via DMA and Receiving via FLEXCOMMx_IRQHandler() possible?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC55S16 UART Sending via DMA and Receiving via FLEXCOMMx_IRQHandler() possible?

Jump to solution
2,537 Views
Ralf_Rademacher
Contributor III

Hello Community,
I am trying to modify the usart_dma_transfer example so that I can send using USART_DMA. But since I don't know what amount of data will come back, I want to receive via interrupt. Unfortunately I didn't manage to use the FLEXCOMM0_IRQHandler together with the DMA. Because when I execute USART_TransferSendDMA(DEMO_USART, &g_uartDmaHandle, &xfer); I get into the FLEXCOMM0_IRQHandler afterwards and not out again.

I need urgent help. Maybe someone can provide me with a small example.

Best

Ralf

Labels (1)
0 Kudos
Reply
1 Solution
2,443 Views
Ralf_Rademacher
Contributor III

Hello Alice,

to 1.) i left it out, because i get into FLEXCOMMx_IRQHandler() instead of DMA_Handler()

and dont get out only if i clear the flag:

    if((kUSART_TxFifoEmptyFlag | kUSART_TxError) & flags)
    {
    	USART0->INTENCLR = USART_INTENCLR_TXIDLECLR_MASK;
        if(txOnGoing)
        	txOnGoing = false;
    }

But in the following i still did not get in the DMA_Handler. Thats why i left it out and called the Function with NULL.

You can try it by yourself.

to 2.) yes i wanted to echo every character to terminal, to have a live feedback.

if you try the code without calling

USART_TransferCreateHandleDMA(USART0, &g_uartDmaHandle, NULL, NULL, &g_uartTxDmaHandle, NULL);

before

USART_TransferSendDMA(USART0, &g_uartDmaHandle, &xfer);

you will see, that only once there is something echoed.

thats why i asked for it.

 

but because i got no good solution here, i got a better one from other side.

now i only use the USART_Init from SDK, everything else is done by FLEXCOMMx_IRQHandler(). I just need my pointer to the string and a length. is very performant instead of the examples from the sdk....

so thats why i mark now the request as solved. even if there was no satisfying solution here.

View solution in original post

0 Kudos
Reply
6 Replies
2,511 Views
Ralf_Rademacher
Contributor III

Hello Alice_Yang,
I have already tried this before your answer. However, here the behavior is different than expected. After sending, the FLEXCOMMx_IRQHandler is called instead of the DMA callback function. This is then permanently triggered if you don't check for kUSART_TxFifoEmptyFlag and disabled with USARTx->INTENCLR = USART_INTENCLR_TXIDLECLR_MASK. Also afterwards the DMA callback does not come up. What can I do about this?

Furthermore I didn't understand if, despite global handles of type dma_handle_t, usart_dma_handle_t and usart_handle_t every time before using by USART_TransferSendDMA in another function it is necessary to call USART_TransferCreateHandleDMA again, otherwise nothing will be sent. It is not clear to me why this is necessary, since the handles were created globally. In the usart_dma_transfer example it worked without the additional call.

I had also tried to modify the usart_dma_transfer example to realize the reception also by means of DMA. Because I don't know how big the amount of data to be received is, I had used a rxbuffer of one byte in this case. Unfortunately this variant was so unperformant that from strings with a length of 250 characters only 148 were captured and processed. Could this be made more performant? Then I would not need to mix interrupt operation with DMA operation and all my worries would be solved.

Can you tell me how I can deinitialize the whole thing again? So that I can build an interface, which I can also shut down and reinitialize? For some things like the Usart and DMA there are Deinit functions. Then there are also various disable functions. What do I do with the handles (this ones: DMA_CreateHandle(&g_uartTxDmaHandle, EXAMPLE_UART_DMA_BASEADDR, USART_TX_DMA_CHANNEL);)? Just set them to NULL? Or leave them and make the same call at reinit with the same vars?

Best regards and thanks in advance

0 Kudos
Reply
2,496 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello Ralf_Rademacher,

I think  you need analysis the issue step by step. the first step is making UART TX with DMA work well,

then working with UART RX.

 

BR

Alice

0 Kudos
Reply
2,486 Views
Ralf_Rademacher
Contributor III

Hi Alice,

i just have setup a little example:

#include "pin_mux.h"
#include "board.h"
#include "fsl_usart.h"
#include "fsl_usart_dma.h"
#include "fsl_dma.h"
#include "fsl_debug_console.h"
#include "fsl_usart_dma.h"
#include <stdbool.h>
#include "fsl_power.h"
/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define USART_TX_DMA_CHANNEL      5
/*******************************************************************************
 * Variables
 ******************************************************************************/
usart_dma_handle_t 	g_uartDmaHandle;
usart_handle_t 		g_usart_handle;
dma_handle_t 		g_uartTxDmaHandle;
uint8_t g_tipString[]                  	= "USART DMA example\r\nWrite this text and\r\nEcho every character immediatly\r\n";
uint8_t g_rxBuffer = 0;
volatile bool txOnGoing                	= false;
usart_config_t config;
usart_transfer_t xfer;

/*******************************************************************************
 * Code
 ******************************************************************************/
void FLEXCOMM0_IRQHandler(void)
{
    uint8_t data;
    uint32_t flags = USART_GetStatusFlags(USART0);
    /* If new data arrived. */
    if ((kUSART_RxFifoNotEmptyFlag | kUSART_RxError) & flags)
    {
    	g_tipString[0]=USART_ReadByte(USART0);
		DMA_EnableChannel(DMA0, USART_TX_DMA_CHANNEL);
		USART_TransferCreateHandleDMA(USART0, &g_uartDmaHandle, NULL, NULL, &g_uartTxDmaHandle, NULL);
		/* Send g_tipString out. */
		xfer.data     	= g_tipString;
		xfer.dataSize 	= 1;
		txOnGoing     	= true;
		USART_TransferSendDMA(USART0, &g_uartDmaHandle, &xfer);
    }
    if((kUSART_TxFifoEmptyFlag | kUSART_TxError) & flags)
    {
    	USART0->INTENCLR = USART_INTENCLR_TXIDLECLR_MASK;
        if(txOnGoing)
        	txOnGoing = false;
    }
    SDK_ISR_EXIT_BARRIER;
}

int main(void)
{

    BOARD_InitBootPins();
    BOARD_InitBootClocks();
    BOARD_InitDebugConsole();
    USART_GetDefaultConfig(&config);
    config.baudRate_Bps = BOARD_DEBUG_UART_BAUDRATE;
    config.enableTx     = true;
    config.enableRx     = true;
    USART_Init(USART0, &config, CLOCK_GetFlexCommClkFreq(0U));
    /* Configure DMA. */
    DMA_Init(DMA0);
    DMA_EnableChannel(DMA0, USART_TX_DMA_CHANNEL);
    DMA_CreateHandle(&g_uartTxDmaHandle, DMA0, USART_TX_DMA_CHANNEL);
    USART_TransferCreateHandleDMA(USART0, &g_uartDmaHandle, NULL, NULL, &g_uartTxDmaHandle, NULL);
    /* Send g_tipString out. */
    xfer.data     = g_tipString;
    xfer.dataSize = sizeof(g_tipString) - 1;
    txOnGoing     = true;
    USART_TransferSendDMA(USART0, &g_uartDmaHandle, &xfer);
    /* Wait send finished */
    while (txOnGoing)
    {
    }
	USART_TransferCreateHandle(USART0, &g_usart_handle, NULL, NULL);
    USART_EnableInterrupts(USART0, kUSART_RxLevelInterruptEnable | kUSART_RxErrorInterruptEnable);
	EnableIRQ(FLEXCOMM0_IRQn);
    while (1)
    {
        __NOP();
    }
}

 

How can i suppress to get into the FLEXCOMM0_IRQHandler() after finishing transmit?

Why i need to call USART_TransferCreateHandleDMA(USART0, &g_uartDmaHandle, NULL, NULL, &g_uartTxDmaHandle, NULL); every time, although I have already created the handles globally and called the function already in the main routine?

Also, I left out the DMA_Callback function for TX in the example, since it is not called anyway. Since the FLEXCOMM0_IRQHandler() is always called before. If I don't clear the TXIDLE flag in the FLEXCOMM0_IRQHandler(), I don't get out of the FLEXCOMM0_IRQHandler() at all.

    if((kUSART_TxFifoEmptyFlag | kUSART_TxError) & flags)
    {
    	USART0->INTENCLR = USART_INTENCLR_TXIDLECLR_MASK;
        if(txOnGoing)
        	txOnGoing = false;
    }

If the TXIDLE flag is cleared, the DMA_Callback function for TX is not called anymore. Is there anything that can be done about this?

BR

Ralf

0 Kudos
Reply
2,455 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello Ralf_Rademacher,

1) I think you shouldn't left out DMA callback, because you TX use DMA, not use interrupt.

so I think there is issue with below code:

  USART_TransferCreateHandleDMA(USART0, &g_uartDmaHandle, NULL, NULL, &g_uartTxDmaHandle, NULL);

 2) Do you want, in the receive interrupt send data using 

USART_TransferSendDMA(USART0, &g_uartDmaHandle, &xfer);

 if yes, I don't think you need  call USART_TransferCreateHandleDMA(USART0, &g_uartDmaHandle, NULL, NULL, &g_uartTxDmaHandle, NULL); every time.

 

BR

Alice

0 Kudos
Reply
2,444 Views
Ralf_Rademacher
Contributor III

Hello Alice,

to 1.) i left it out, because i get into FLEXCOMMx_IRQHandler() instead of DMA_Handler()

and dont get out only if i clear the flag:

    if((kUSART_TxFifoEmptyFlag | kUSART_TxError) & flags)
    {
    	USART0->INTENCLR = USART_INTENCLR_TXIDLECLR_MASK;
        if(txOnGoing)
        	txOnGoing = false;
    }

But in the following i still did not get in the DMA_Handler. Thats why i left it out and called the Function with NULL.

You can try it by yourself.

to 2.) yes i wanted to echo every character to terminal, to have a live feedback.

if you try the code without calling

USART_TransferCreateHandleDMA(USART0, &g_uartDmaHandle, NULL, NULL, &g_uartTxDmaHandle, NULL);

before

USART_TransferSendDMA(USART0, &g_uartDmaHandle, &xfer);

you will see, that only once there is something echoed.

thats why i asked for it.

 

but because i got no good solution here, i got a better one from other side.

now i only use the USART_Init from SDK, everything else is done by FLEXCOMMx_IRQHandler(). I just need my pointer to the string and a length. is very performant instead of the examples from the sdk....

so thats why i mark now the request as solved. even if there was no satisfying solution here.

0 Kudos
Reply
2,515 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello Ralf,

 

It is recommend to combine the two demos "lpcxpresso55s16_usart_interrupt" " and "/lpcxpresso55s16_usart_dma_transfer" to develop your own project.  Demo usart_interrupt includes 

UART receiving interrupt. 

 

BR

Alice

0 Kudos
Reply