mx rt 1020 send 9bit over DMA

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

mx rt 1020 send 9bit over DMA

Jump to solution
1,647 Views
bp1979
Senior Contributor I

Hi 

I am using an imx rt 1020 and try to send 9bit data over dma, but having trouble sending the 9th bit.

 

status_t LPUART_SendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart_transfer_t *xfer)

 

 

the lpuart_transfer_t is defined as follows

 

typedef struct _lpuart_transfer
{
    uint8_t *data;   /*!< The buffer of data to be transfer.*/
    size_t dataSize; /*!< The byte count to be transfer. */
} lpuart_transfer_t;

 

I tried to split uint16_t bytes in two bytes and sent that over, but it doesn't work.

 

        uint32_t txIndex = 0;
        for (uint32_t i = 0; i < length; i++)
        {
                // T == uint16_t 
        	T d = data[i];

        	if (sizeof(T) == 2)
        	{
                _txBuffer[txIndex++] = d & 0xFF ;
                _txBuffer[txIndex++] = (d & 0x100) >> 8 ;
        	}
        	else
        	{
        		_txBuffer[txIndex++] = d;
        	}
        }

        _sendXfer.data = _txBuffer;
        _sendXfer.dataSize = length;
        

        LPUART_SendEDMA(_instance, &_uartDmaHandle, &_sendXfer);

 

 

this sends 

bp1979_0-1634911199353.png

but is should send one "9bit byte" 0x108.

I am obviously doing this wrong, how can I send 9bits over DMA?

 

 

0 Kudos
1 Solution
1,566 Views
Omar_Anguiano
NXP TechSupport
NXP TechSupport

Hello

Hope you are well and I apologize for my delayed reply.
Commonly the 9bit is used to send the parity bit and have 8 bits of data, this can be done in the example without the need of setting anything extra besides the 9th bit and parity enable.
I did some modifications to the example so it supports the 9bith data without parity:

1. Modified the data types from structure "lpuart_transfer_t" so the uint´s are of 16bits.

Omar_Anguiano_0-1636076857352.png

2. In LPUART_SendEDMA() modified the parameters from EDMA_PrepareTransfer() function, the parameters I modified are bytesEachRequest and transferBytes:

Omar_Anguiano_1-1636076877119.png
Here are my results:

Omar_Anguiano_2-1636076909711.png
Notes: xfer.dataSize needs to be in multiples of 2. If you write 4 to that variable then 2 9bit LPUART frames are sent.

Let me know if this is helpful, if you have more questions do not hesitate to ask me.
Best regards,
Omar

View solution in original post

6 Replies
734 Views
masterboy
Contributor III

Hello,

I am also addressing the 9-bit mode of LPUART via eDMA. I modified the code as Omar_Anguiano wrote. I am unable to send more than one 9-bit byte. Each byte sent has 1 at the beginning e.g. if I send 0x48 it sends 0x148, if I send 0x02 it sends 0x102.

#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "fsl_lpuart_edma.h"
#include "fsl_dmamux.h"
/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define DEMO_LPUART                    LPUART3
#define DEMO_LPUART_CLK_FREQ           BOARD_DebugConsoleSrcFreq()
#define LPUART_TX_DMA_CHANNEL          0U
#define LPUART_RX_DMA_CHANNEL          1U
#define LPUART_TX_DMA_REQUEST          kDmaRequestMuxLPUART3Tx
#define LPUART_RX_DMA_REQUEST          kDmaRequestMuxLPUART3Rx
#define EXAMPLE_LPUART_DMAMUX_BASEADDR DMAMUX
#define EXAMPLE_LPUART_DMA_BASEADDR    DMA0
#define ECHO_BUFFER_LENGTH 8

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/* LPUART user callback */
void LPUART_UserCallback(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData);

/*******************************************************************************
 * Variables
 ******************************************************************************/

lpuart_edma_handle_t g_lpuartEdmaHandle;
edma_handle_t g_lpuartTxEdmaHandle;
edma_handle_t g_lpuartRxEdmaHandle;
AT_NONCACHEABLE_SECTION_INIT(uint8_t g_tipString[]) =
    "LPUART EDMA example\r\nSend back received data\r\nEcho every 8 characters\r\n";
AT_NONCACHEABLE_SECTION_INIT(uint8_t g_txBuffer[ECHO_BUFFER_LENGTH]) = {0};
AT_NONCACHEABLE_SECTION_INIT(uint8_t g_rxBuffer[ECHO_BUFFER_LENGTH]) = {0};
AT_NONCACHEABLE_SECTION_INIT(uint16_t test[ECHO_BUFFER_LENGTH]) = {0};
volatile bool rxBufferEmpty                                          = true;
volatile bool txBufferFull                                           = false;
volatile bool txOnGoing                                              = false;
volatile bool rxOnGoing                                              = false;
edma_config_t config;

/*******************************************************************************
 * Code
 ******************************************************************************/
/* LPUART user callback */
void LPUART_UserCallback(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData)
{
    userData = userData;

    if (kStatus_LPUART_TxIdle == status)
    {
        txBufferFull = false;
        txOnGoing    = false;
    }

    if (kStatus_LPUART_RxIdle == status)
    {
        rxBufferEmpty = false;
        rxOnGoing     = false;
    }
}

/*!
 * @brief Main function
 */
int main(void)
{
    lpuart_config_t lpuartConfig;
    lpuart_transfer_t xfer;
    lpuart_transfer_t sendXfer;
    lpuart_transfer_t receiveXfer;

    BOARD_ConfigMPU();
    BOARD_InitBootPins();
    BOARD_InitBootClocks();

    /* Initialize the LPUART. */
    /*
     * lpuartConfig.baudRate_Bps = 115200U;
     * lpuartConfig.parityMode = kLPUART_ParityDisabled;
     * lpuartConfig.stopBitCount = kLPUART_OneStopBit;
     * lpuartConfig.txFifoWatermark = 0;
     * lpuartConfig.rxFifoWatermark = 0;
     * lpuartConfig.enableTx = false;
     * lpuartConfig.enableRx = false;
     */
    LPUART_GetDefaultConfig(&lpuartConfig);
    lpuartConfig.baudRate_Bps = BOARD_DEBUG_UART_BAUDRATE;
    lpuartConfig.enableTx     = true;
    lpuartConfig.enableRx     = true;

    LPUART_Init(DEMO_LPUART, &lpuartConfig, DEMO_LPUART_CLK_FREQ);

    /* Init DMAMUX */
    DMAMUX_Init(EXAMPLE_LPUART_DMAMUX_BASEADDR);
    /* Set channel for LPUART */
    DMAMUX_SetSource(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_TX_DMA_CHANNEL, LPUART_TX_DMA_REQUEST);
    DMAMUX_SetSource(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_RX_DMA_CHANNEL, LPUART_RX_DMA_REQUEST);
    DMAMUX_EnableChannel(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_TX_DMA_CHANNEL);
    DMAMUX_EnableChannel(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_RX_DMA_CHANNEL);

    /* Init the EDMA module */
    EDMA_GetDefaultConfig(&config);
    EDMA_Init(EXAMPLE_LPUART_DMA_BASEADDR, &config);
    EDMA_CreateHandle(&g_lpuartTxEdmaHandle, EXAMPLE_LPUART_DMA_BASEADDR, LPUART_TX_DMA_CHANNEL);
    EDMA_CreateHandle(&g_lpuartRxEdmaHandle, EXAMPLE_LPUART_DMA_BASEADDR, LPUART_RX_DMA_CHANNEL);

    /* Create LPUART DMA handle. */
    LPUART_TransferCreateHandleEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, LPUART_UserCallback, NULL, &g_lpuartTxEdmaHandle, &g_lpuartRxEdmaHandle);

    /* Send out. */
    test[0] = 0x48;
    xfer.data     = test;
    xfer.dataSize = 2;
    txOnGoing     = true;
    LPUART_SendEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &xfer);

    /* Wait send finished */
    while (txOnGoing)
    {
    }

    test[0] = 0x02;
    xfer.data     = test;
    xfer.dataSize = 2;
    txOnGoing     = true;
    LPUART_SendEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &xfer);

    while (1);
}

 

This is the result:

Snímek obrazovky 2023-03-07 v 8.26.20.png

I need the first byte to be 0x148 and the second only 0x02. There is also the problem of having to send each byte separately.

If I edit the code to send the data:

    /* Send out. */
    test[0] = 0x48;
    test[1] = 0x02;
    xfer.data     = test;
    xfer.dataSize = 4;
    txOnGoing     = true;
    LPUART_SendEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &xfer);

    /* Wait send finished */
    while (txOnGoing)
    {
    }

This is the result:

Snímek obrazovky 2023-03-07 v 8.34.00.png

What could be the problem?

Besides, this is only half of what I'm dealing with. The other is receiving data in 9-bit mode. Again, the first byte must have a flag of 1 and the other flags for the data are 0.

 

 

 

0 Kudos
724 Views
bp1979
Senior Contributor I

Hi @masterboy ,

Just had a real quick look at your code which looks fine at a first glance. One thing that you seem to miss is to configure the uart as 9bit

```

LPUART_Enable9bitMode

```

Does that fix anything? If not, I'll have another look

0 Kudos
1,567 Views
Omar_Anguiano
NXP TechSupport
NXP TechSupport

Hello

Hope you are well and I apologize for my delayed reply.
Commonly the 9bit is used to send the parity bit and have 8 bits of data, this can be done in the example without the need of setting anything extra besides the 9th bit and parity enable.
I did some modifications to the example so it supports the 9bith data without parity:

1. Modified the data types from structure "lpuart_transfer_t" so the uint´s are of 16bits.

Omar_Anguiano_0-1636076857352.png

2. In LPUART_SendEDMA() modified the parameters from EDMA_PrepareTransfer() function, the parameters I modified are bytesEachRequest and transferBytes:

Omar_Anguiano_1-1636076877119.png
Here are my results:

Omar_Anguiano_2-1636076909711.png
Notes: xfer.dataSize needs to be in multiples of 2. If you write 4 to that variable then 2 9bit LPUART frames are sent.

Let me know if this is helpful, if you have more questions do not hesitate to ask me.
Best regards,
Omar

1,498 Views
bp1979
Senior Contributor I

@Omar_Anguiano  Thank you very much! Took me a while before I could dip into this, but  finally got  this to work!  

0 Kudos
1,607 Views
bp1979
Senior Contributor I

Dear nxp

Would anybody care to give some guidance? How do i send 9bit over lpuart using dma? 

0 Kudos
1,603 Views
bp1979
Senior Contributor I

Dear NXP

if there is any better way, please let me know. For now just went for a hacky blocking write

    virtual void Write(T *data, uint32_t length)
    {
        projectAssert(sizeof(_txBuffer) > length, ErrorCodeUartTxMessageTooLarge);

        if (sizeof(T) == 2)
        {
            // If T is uint16_t, write to uart blocking
            // Waiting for answer how to send 9bit data over uart with DMA
        	// https://community.nxp.com/t5/i-MX-RT/mx-rt-1020-send-9bit-over-DMA/td-p/1360134
        	for (uint32_t i=0; i<length; i++)
        	{
        		while (!(_instance->STAT & LPUART_STAT_TDRE_MASK))
        		{
        			// Wait for transmit ready
        		}
                uint32_t temp = _instance->DATA & 0xFFFFFC00UL;
                temp |= (uint32_t)data[i];
                _instance->DATA = temp;
        	}
        }
        else if (sizeof(T) == 1)
        {
        	// Else... regular send data over DMA
            xSemaphoreTake(_txSemaphore, portMAX_DELAY);

            for (uint32_t i = 0; i < length; i++)
            {
                _txBuffer[i] = data[i];
            }

            _sendXfer.data = _txBuffer;
            _sendXfer.dataSize = length;

            LPUART_SendEDMA(_instance, &_uartDmaHandle, &_sendXfer);
        }
        else
        {
        	// For now we only support 8 bit and 16 bit data types
        	projectAssert(0, ErrorCodeUartUnsupportedType);
        }
    }
0 Kudos