LPUART - eDMA configuration

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

LPUART - eDMA configuration

4,852 Views
alternativeunof
Contributor II

Hi, I'm working with the S32K144 evaluation board but I'm having some trouble using LPUART and eDMA modules. I want to implement something like that:

  1. LPUART receives a message
  2. eDMA transfers this message from LPUART peripheral to memory
  3. Step 1 and 2 are repeated for an established number of messages
  4. Once the last UART message has been moved to memory by the DMA, a callback function is called

I'm using the drivers provided by the S32K14x EAR 0.8.6 SDK. I generated all the code (processor code) for both eDMA and LPUART with the right configuration:

  • LPUART1 activated (which is connected to the OpenSDA USB interface permitting me to send messages from the PC)
  • LPUART1 transfer type = DMA
  • RX DMA channel and TX DMA channel are set
  • all peripherals are clocked

After eDMA and LPUART initialization, I call the function LPUART_ReceiveData provoking the following function call:

  • LPUART_DRV_StartSendDataUsingDma <-- so I'm using the DMA transfer
  • EDMA_DRV_ConfigMultiBlockTransfer <-- problem: it configures the number of block to 1 
  • EDMA_DRV_InstallCallback <-- this callback is called when the last block is transferred (This function would call also your LPUART end transfer callback, if you have installed it)
  • EDMA_DRV_StartChannel
  • LPUART_SetTxDmaCmd

 

So my questions are:

  1. I thought that LPUART_ReceiveData could be used to receive more than 1 block (i.e. UART message) before to call the callback function, but actually it seems able to accept only 1 block (i.e. 1 message) even if it activates the DMA transfer, loosing the only reason I have to use the DMA (I could use the normal interrupt if I can only transfer 1 byte). Is this true? If yes, there is any other function able to do that?
  2. If LPUART_ReceiveData can be used for this purpose (i.e. receive more than one message, transfer them in memory thanks to the DMA, call a callback function signaling the DMA transfer end) how do I have to install the callback function? Do I have to use driver function: LPUART_DRV_InstallRxCallback?

 

Thanks you all!

Bye.

Labels (1)
5 Replies

3,565 Views
c_joshi
Contributor II

Hi IgoI am trying to implement the same functionality but the issue is i am not able to read from console. Could you please tell me how you set up the communication from PC ? 

0 Kudos

3,565 Views
B46399
NXP Employee
NXP Employee

Hello,

The driver configures the DMA engine to transfer the number of bytes received as parameter to the send/receive function; each of these bytes will be then transferred by the DMA to/from the user buffer upon a request from the LPUART, with no CPU intervention.

Could you please share your project so we can take a look? Maybe there's something wrong in the configuration, I don't think I fully understood the problem.

Thanks,

Vlad

3,565 Views
alternativeunof
Contributor II

It's true. I was interpretating wrongly the driver function. Now I'm able to receive a block of UART messages without interrupting the CPU at each new message, but only when the last message of the block is moved in memory by the DMA. At this point a callback function is called, but there is a problem.

I'm using FreeRTOS and it seems that when I call LPUART_ReceiveData at a certain point the execution freezes on:

configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );

Above this command there is a comment:

/*

    The following assertion [i.e., configASSERT(...)] will fail if a service routine (ISR) for
    an interrupt that has been assigned a priority above
    configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
    function.  ISR safe FreeRTOS API functions must *only* be called
    from interrupts that have been assigned a priority at or below
    configMAX_SYSCALL_INTERRUPT_PRIORITY

    [...]

    Interrupts that use the FreeRTOS API must not be left at their
    default priority of zero as that is the highest possible priority,
    which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
    and therefore also guaranteed to be invalid.

*/

The problem is that I don't know which is the interrupt it is reffering to.

The LPUART_DRV_ReceiveDataBlocking performs the following things:

  1. calls The LPUART_DRV_StartReceiveDataUsingDma function which:
  • configures the block transfer
  • installs the callback LPUART_DRV_CompleteReceiveDataUsingDMA that invoke the callback I installed on the LPUART receiver
  • enables the overrun interrupt: LPUART_SetIntMode(base, LPUART_INT_RX_OVERRUN, true);
  • starts the DMA channel
  • enables the DMA requests for LPUART Receiver

   2. if LPUART_DRV_StartReceiveDataUsingDma returns with success, we have finished the block transfer.

In this code, I can't see where interrupt has been instantiated except for the overrun interrupt error, that should not occur since I'm transferring messages with the DMA.

I think that the callback functions are called inside the interrupt service routine referred to the dma end of transfer interrupt, but I can't see this in the code.

EDIT (SOLUTION)

I solved the problem by changing the priority of the DMA channel 0 (the one connected to the LPUART1_RX) to 2 instead of 0. Thanks anyway.

0 Kudos

3,565 Views
B46399
NXP Employee
NXP Employee

Hi,

Sorry for the delayed response, I'm glad it worked out. The DMA interrupt for the channel allocated for LPUART would be triggered when the transfer completed and, for blocking operation, would call the semaPost function in order to let the blocking function know that it can return (no timeout on the semaWait). If the priority of that interrupt was higher than the FreeRTOS max priority, the program would get stuck in the assert statement you mentioned. Hope this explanation clears things out, if necessary.

Regards,

Vlad

3,565 Views
amwilhite
Contributor III

I believe the issue in this case is that the EDMA driver does not actually set an interrupt priority for the DMA channels, so they default to 0. I found this same bug still exists in the 2.6 SDK for the iMX RT1050.

0 Kudos