Processor Expert Initialize Using DMA

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

Processor Expert Initialize Using DMA

1,865 Views
cskwon
Contributor I

hello

I have a question.

Data is exchanged using 921600 UART (About 500Byte ~ 1000Byte)

When using CAN-FD, there is a phenomenon that stops due to UART Data Loss.

I want to use DMA to solve that problem.

UART uses LINFlexD_1, and RX DMA Channel and TX DMA Channel are fixed to 0 in Processor Expert.

The above RX_DMA_Channel or TX_DMA_Channel is different from the channel number of the DMA controller.

Question 1.
- Is it okay if RX_DMA_Channel and TX DMA Channel of LINFlexd1 are different from Channel Number of DMA Controller? (Attach the picture below)

processor_exp_DMA.JPGprocessor_exp_UART.JPG

 

 

 

 

 

 

 

Question2

- Can I just enter the DMA initialization code below to connect the RX of the UART with the DMA?

(Main.c Initialize Routine)

EDMA_DRV_Init(&dmaController1_State, &dmaController1_InitConfig0, edmaChnStateArray, edmaChnConfigArray, EDMA_CONFIGURED_CHANNELS_COUNT);

(Uart1 Initialize Routine)

LINFLEXD_UART_DRV_Init(INST_WIFI_UART, &WiFi_uart_State, &WiFi_uart_InitConfig0);

// UART1 (LINFLEXD1) IRQ Disable
INT_SYS_DisableIRQ(LINFLEXD1_RX_IRQn); /* While UART RX is not in use */
INT_SYS_DisableIRQ(LINFLEXD1_RX_IRQn); /* While UART RX is not in use */
// UART1 Buffer Setting
LINFLEXD_UART_DRV_SetRxBuffer(INST_WIFI_UART, &WiFi_UART_RX_Buffer, 1U);
// UART1 Baudrate Setting
LINFLEXD_UART_DRV_SetBaudRate(INST_WIFI_UART, WiFi_BAUD_RATE);
// UART1 Abort Send Data
LINFLEXD_UART_DRV_AbortSendingData(INST_WIFI_UART);
// UART1 Abort Receive Data
LINFLEXD_UART_DRV_AbortReceivingData(INST_WIFI_UART);
// UART1 Remove RX Callback
LINFLEXD_UART_DRV_InstallRxCallback(INST_WIFI_UART, NULL, NULL);
// UART1 Install RX Callback
LINFLEXD_UART_DRV_InstallRxCallback(INST_WIFI_UART,(uart_callback_t) WiFi_UART_Callback, NULL);
LINFLEXD_UART_DRV_InstallErrorCallback(INST_WIFI_UART,(uart_callback_t) WiFi_UART_ErrorCallback, NULL);
// Receiving Start
LINFLEXD_UART_DRV_ReceiveData(INST_WIFI_UART, &WiFi_UART_RX_Buffer, 1);
// UART1 (LINFLEXD4) IRQ Enable
INT_SYS_EnableIRQ(LINFLEXD1_RX_IRQn);
INT_SYS_EnableIRQ(LINFLEXD1_TX_IRQn);

 

please answer about my question.

thank you

 

Best regards

0 Kudos
Reply
5 Replies

1,860 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

1) in LinflexD_1 component you need to select "DMA" as transfer type, then you will be able to choose RX and TX DMA channels, which have to be different. In DMA component you should have again 2 channels added, with same channel number as selected in LinflexD_1 component.

2) it is enough to call EDMA_DRV_Init before LINFLEXD_UART_DRV_Init as you have.

BR, Petr

0 Kudos
Reply

1,858 Views
cskwon
Contributor I

Thank you for answer. @PetrS 

The question was being edited.


Changed UART to use DMA in Processor Expert,
The DMA channel and the UART DMA channel are matched.

processor_exp_UART.JPGprocessor_exp_DMA.JPG

After DMA initialization is complete
UART has been initialized.

The UART initialization code is shown below.

 

 

 

void UART_Initial(void)
{

    	/*	UART1 Debug Uart Initilize */

		// UART1 Wi-Fi UART Initialize
		LINFLEXD_UART_DRV_Init(INST_WIFI_UART, &WiFi_uart_State, &WiFi_uart_InitConfig0);

		// UART1 (LINFLEXD1) IRQ Disable
	    INT_SYS_DisableIRQ(LINFLEXD1_RX_IRQn); /* While UART RX is not in use */
	    INT_SYS_DisableIRQ(LINFLEXD1_RX_IRQn); /* While UART RX is not in use */
	    // UART1 Buffer Setting
		LINFLEXD_UART_DRV_SetRxBuffer(INST_WIFI_UART, &WiFi_UART_RX_Buffer, 1U);
		// UART1 Baudrate Setting
	    LINFLEXD_UART_DRV_SetBaudRate(INST_WIFI_UART, WiFi_BAUD_RATE);
	    // UART1 Abort Send Data
	    LINFLEXD_UART_DRV_AbortSendingData(INST_WIFI_UART);
	    // UART1 Abort Receive Data
	    LINFLEXD_UART_DRV_AbortReceivingData(INST_WIFI_UART);
	    // UART1 Remove RX Callback
	    LINFLEXD_UART_DRV_InstallRxCallback(INST_WIFI_UART, NULL, NULL);
	    // UART1 Install RX Callback
		LINFLEXD_UART_DRV_InstallRxCallback(INST_WIFI_UART,(uart_callback_t) WiFi_UART_Callback, NULL);
		LINFLEXD_UART_DRV_InstallErrorCallback(INST_WIFI_UART,(uart_callback_t) WiFi_UART_ErrorCallback, NULL);
		// Receiving Start
    	LINFLEXD_UART_DRV_ReceiveData(INST_WIFI_UART, &WiFi_UART_RX_Buffer, 1);
		// UART1 (LINFLEXD4) IRQ Enable
    	INT_SYS_EnableIRQ(LINFLEXD1_RX_IRQn);
//    	INT_SYS_EnableIRQ(LINFLEXD1_TX_IRQn);


}

 

 

 

The received data was received by increasing the count value in WiFi_UART_Callback and the arrangement was checked.

+aaaagggfcccxx0888c000:666x,,,,wwww222mppp..++naaapuuum,,,cxxx0777c000:6666555apppcpppkk+aaaaAA

In this way, data is dropped in the middle, and it comes out as if it was received as a duplicate.

Removed UART_Install_Callback to fix the problem.


After that EDMA_DRV_InstallCallback(16,WiFi_UART_Callback,NULL );


I set it as InstallCallback to EDMA using

As above, the same data is duplicated in multiple cases.

Do I need to make any additional settings?

 

0 Kudos
Reply

1,851 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

not sure how do you use your WiFi_UART_Callback. But in case of DMA transfer, still you should install RX callback to have indication of complete reception. DMA channel setting is done in driver, also it installs DMA callback etc.
However if you are going to receive just 1 byte, DMA usage does not bring any benefit. Go through ReceiveData function to see how it is handled.
Call this function with expected number of bytes to be receive, and after whole bytes will be received RX callback should be invoked with RX buffer filled by DMA.

BR, Petr

0 Kudos
Reply

1,846 Views
cskwon
Contributor I

Thanks for your kind reply.

WiFi_UART_Callback works as follows
This is a classic way to increment the number of arrays after receiving 1 byte.
Data is received from a minimum of 400 bytes to a maximum of 800 bytes.

void WiFi_UART_Callback(void *driverState, uart_event_t event, void *userData)
{

	  LINFLEXD_UART_DRV_ReceiveData(INST_WIFI_UART, &WiFi_UART_RX_Buffer, 1);
	  WiFi_Received_Data[WiFi_Received_Count] = WiFi_UART_RX_Buffer;
	  WiFi_Received_Count++;

	  if(WiFi_Received_Data[WiFi_Received_Count-1] == '\r')
	  {
	  	  if(WiFi_Received_Data[WiFi_Received_Count-2] == '\n')
		  {
		    WiFi_Uart_Receive_Finish_Flag = 1;
		  }
	  }
}

 

After receiving up to the set bytes in the RX Buffer with the contents of your reply,
Does it mean that the data as much as the set byte do Stack DMA RX Callback?

Question 1.
- When stacking data in RX Buffer, use LINFLEXD_UART_DRV_InstallRxCallback function to install RX Callback. Whenever RX Callback is called, can it be stacked like the code attached above?

Question 2.
When RX Callback occurs, if it is processed as above,
The same data is duplicated multiple times and the problem is that it accumulates in the buffer. am i wrong?


Is there a Receive example that I can refer to developed with SDK_S32_PA?
(SDK basic example is TX DMA, so it is difficult to refer to)

 

Thanks

 

Best regards

0 Kudos
Reply

1,840 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

as far as I know, there is no SDK example showing RX DMA usage.

for your callback code; if DMA transfer type is used, this is useless, I think. For single byte receive it brings so much SW overhead. I can imagine DMA usage if you know how much bytes will be received, for example that 400 bytes. you will call 

 

LINFLEXD_UART_DRV_ReceiveData(INST_WIFI_UART, &WiFi_UART_RX_Buffer, 400);

 

and callback should be invoked after whole 400 bytes will be received, so you can process buffer in it or later.

For interrupt mode you can try to use way shown in uart_pal example.

/* UART rx callback for continuous reception, byte by byte */
void rxCallback(void *driverState, uart_event_t event, void *userData)
{
/* Unused parameters */
(void)driverState;
(void)userData;

/* Check the event type */
if (event == UART_EVENT_RX_FULL)
{
/* The reception stops when newline is received or the buffer is full */
if ((buffer[bufferIdx] != '\n') && (bufferIdx != (BUFFER_SIZE - 2U)))
{
/* Update the buffer index and the rx buffer */
bufferIdx++;
UART_SetRxBuffer(&uart_pal1_instance, &buffer[bufferIdx], 1U);
}
}
}

 

/* Infinite loop */
for( ;; )
{
/* Receive and store data byte by byte until new line character is received,
* or the buffer becomes full (256 characters received)
*/
UART_ReceiveData(&uart_pal1_instance, buffer, 1U);
/* Wait for transfer to be completed */
while(UART_GetReceiveStatus(&uart_pal1_instance, &bytesRemaining) == STATUS_BUSY);

....

BR, Petr 

0 Kudos
Reply