S32K146 UART DMA usage problems

cancel
Showing results for 
Search instead for 
Did you mean: 

S32K146 UART DMA usage problems

1,573 Views
xiaoyuwang
Contributor II

Project Brief Introduction:
1. Using S32K146 MCU;
2. Using many MCU peripherals, such as UART(BR: 230000bps), CAN, I2C, GPIO, LPIT, LPTMR, FTM(2 modules, 12 channels IC, ) etc, and we also use FreeRTOS.
3. All of peripherals above but GPIO using interrupt mode.

My problem:
1. Data size on UART is about 9KB/s, we configure UART interrupt every byte, so too many interrupts performed and our application functions will be affected.
2. Now I want to use DMA to take over UART TX interrupts firstly, but I don't know whether I can sperate the UART communication(TX/RX) and use DMA on only one direction.
3. If answer for 2 is yes, then may I use SDK to implement this(currently, we use SDK to configure the UART module)? May I know the steps?
4. If answer for 2 is no, then do you have any other suggestion which can reduce my interrupts obviously.

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

198 Views
paul12345
Contributor II

I would like to revive this thread; I too am having a lot of difficulty using UART DMA mode on a S32K1xx device (S32K148).

I found that although configuration succeeds and the return values look good for all driver functions, the TX callback function is never called and nothing is transmitted. I have configured the eDMA in advance, very similar to all the examples I can find for SPI/DMA, but clearly something is missing. I have uart1 working with interrupt mode and I am trying to add uart2 in DMA mode (using uart1 to debug). I have also tried going straight to uart1 being in DMA mode but see nothing coming out and lose my debugging statements/assertions that way.

The basics are the following (edited for brevity):

```

CLOCK_DRV_Init(...)
PINS_DRV_Init(...)

edma_user_config_t user_config = {
.chnArbitration = EDMA_ARBITRATION_FIXED_PRIORITY,
.haltOnError = false
};
EDMA_DRV_Init(...)

edma_channel_config_t tx_dma_ch_config = {
.channelPriority = EDMA_CHN_DEFAULT_PRIORITY,
.virtChnConfig = edma_tx_ch_,
.source = get_tx_dma_source(uart_ch_),
.callback = NULL,
.callbackParam = NULL,
.enableTrigger = true,
};

...
EDMA_DRV_ChannelInit(...);
EDMA_DRV_ConfigureInterrupt(edma_tx_ch_, EDMA_CHN_MAJOR_LOOP_INT, true);
EDMA_DRV_ConfigureInterrupt(edma_tx_ch_, EDMA_CHN_ERR_INT, true);

lpuart_user_config_t lpuart_config = {
.baudRate = baud,
.parityMode = LPUART_PARITY_DISABLED,
.stopBitCount = LPUART_ONE_STOP_BIT,
.bitCountPerChar = LPUART_8_BITS_PER_CHAR,
.transferType = LPUART_USING_DMA,
.rxDMAChannel = edma_rx_ch_,
.txDMAChannel = edma_tx_ch_};

LPUART_DRV_Init(...);

...

LPUART_DRV_InstallTxCallback(
uart_ch_, &someFunction, someParams);

...

LPUART_DRV_SendData(uart_ch_, buf_, num_bytes_);

```

 

Basically, someFunction() never gets called, as far as I can tell. I'm capturing all the status_t return values of the configuration functions (although it is omitted above), and they are all STATUS_SUCCESS. I also tried LPUART_DRV_SendDataBlocking() and still using DMA mode, since that appears to be a supported combination, and it results in timeouts. So clearly something is wrong with the DMA UART driver or my [mis]use of it.

0 Kudos

177 Views
paul12345
Contributor II

I solved my issue (after 2+ days struggling with this driver) and documented the changes in this thread:

https://community.nxp.com/t5/S32-SDK/S32K148-UART-eDMA-driver-hangs-at-LPUART-SetTxDmaCmd/m-p/136699...

0 Kudos

1,337 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hello xiaoyuwang,

2. The LPUART allows to use DMA only for the transmitter.

pastedImage_2.png

pastedImage_3.png

3. No, the LPUART SDK driver can be used either in Interrupt or DMA mode.

4. The FIFO WATER marks can be used (FIFO, WATER).
But the SDK driver does no use it, TXWATER = RXWATER = 0.

BR, Daniel

0 Kudos

1,262 Views
lzjregister
Contributor I

he LPUART allows to use DMA only for the transmitter.”  Are you sure? 

0 Kudos

1,337 Views
xiaoyuwang
Contributor II

hello Daniel,

Thank you so much for your answer.

for question 3, I cannot understand clearly.

You mean I cannot implement only UART TX use DMA mode with current SDK?

If so, is it possible for me to implement by modify current SDK? What should I do?

Thank you~~

0 Kudos

1,337 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hello xiaoyuwang,

Yes, it is not possible to use DMA only for the transmitter (LPUART TX) with the SDK LPUART driver.

There is no simple modification of the driver that you can do.

Why you don't use DMA for both the transmitter and the receiver?

Regards,

Daniel

0 Kudos

1,337 Views
xiaoyuwang
Contributor II

hello Daniel,

We have a UART communication protocol, and communication frames length are not fixed value. 

If I use DMA for UART reception, DMA will transfer communication bytes only one every time, currently I don't know how to increase the transfer efficiency.

One more question, I tried UART transmission with DMA, but I found a problem: My transmission success ratio only about 60%.

企业微信截图_1555555.png

Picture above show you that I pack my data and call function interface "LPUART_DRV_SendDataBlocking" for transmission.

企业微信截图_15889035838073.png

As shown in picture, I use default source code in SDK. I wonder how to increase the transfer success ratio.

Thanks again~~

0 Kudos

1,337 Views
nxf58909
NXP Employee
NXP Employee

Hi Xiaoyu, for your concern that using UART Rx receiving not fixed-length value. Below is a method suggested using DMA+ UART RX IDLE interrupt. For example, setting DMA BITER = 100, which means every 100 bytes received a DMA complete IRQ will be triggered. Set a counter ++ in the DMA complete callback, calculate the rest bytes in the UART RX IDLE callback by reading the CITER register of DMA, and take out the (100-CITER bytes) length of data.  When you are receiving 770 bytes of data, 7 times of DMA complete callback will be called, so the counter is 7. When RX IDLE callback is called(Which means all frames are sent), CITER should be 30. And only 7+1=8 times of IRQ occurred. 

0 Kudos

1,274 Views
lzjregister
Contributor I

hello, could you show some code example, thank you very much!

0 Kudos

1,337 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hello xiaoyuwang,

Could you please elaborate on the description.

What exactly do you mean by the success ratio?

Thanks,

BR, Daniel

0 Kudos

1,337 Views
xiaoyuwang
Contributor II

hi Daniel,

In my ECU, my MCU will communication with SOC chip with UART, and both Tx and Rx frames will observe the same communication protocol.

MCU will send frames to SOC according to task need. But currently, when I use send interface which mentioned above to send my frames, about 60% of them(Tx frames) are transferred failed. Which means only 40% of my Tx-Frames are send successfully. This is my success ratio.

For problem described above, I guess that is because of the 5th parameter of interface "EDMA_DRV_ConfigMultiBlockTransfer".  Currently, it is filled with "EDMA_TRANSFER_SIZE_1B", it is because of the byte width of DATA register of LPUART. But I think it is too slow that DMA will transfer only 1 byte every time. Can it be values other than  "EDMA_TRANSFER_SIZE_1B"?  How to configure?

Thank you ~~

0 Kudos

1,337 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi xiaoyuwang

As it was already discussed, the LPUART – DMA SDK implementation does not use LPUART FIFO, so, only the EDMA_TRANSFER_SIZE_1B can be used.
But the EDMA_TRANSFER_SIZE_1B parameter should not cause these issues.
Once the DMA transfer starts, it transfers one byte per a LPUART request, but it should not fail to transfer them.

What is the return status of the LPUART_DRV_SendDataBlocking() function?
Does it return TIMEOUT or any other error message?
Do you use other DMA channels with higher priorities?

Regards,

Daniel

0 Kudos