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
Solved! Go to Solution.
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.
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
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
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
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
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.
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