How to set the DMA uart receive size dynamically

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

How to set the DMA uart receive size dynamically

2,995件の閲覧回数
hanmant
Contributor III

Hi,

Board - Custom board based on RT1020

Currently I'm using DMA uart for the communication between two board.

Communication is works fine but i want to set uart receive size is dynamically.

Currently I set like this,

receiveXfer.data = rxBuff;

receiveXfer.dataSize = 10;

 

but, this receiveXfer.dataSize will have to change dynamically based on request by sender ,but I'm not able to set this size; because sender sometimes sends 32 bytes sometimes 22 bytes .

Suppose if I set receiveXfer.dataSize fixed size to 22 and exchanging of data works fine till 22 bytes receive ,but when sender send size of data different than 22 bytes then communication gets stuck means it will stop the exchanging data.

e.g.

when, this way i want set or other you can suggest.

if(rxBuff[0] == 0x22)

{

//receiveXfer.dataSize size will be 22

}

if(rxBuff[0] == 0x24)

{

//receiveXfer.dataSize size will be 32

}

 Is it possible to resolve this issue.



  

ラベル(1)
タグ(1)
0 件の賞賛
返信
11 返答(返信)

2,960件の閲覧回数
Sam_Gao
NXP Employee
NXP Employee

Hi @hanmant 

There are serval method to reach it.

1. Use interrupt or callback function to dynamically adjust the receive size:

When the first byte is received, determine the data length through the interrupt or callback function, and then dynamically adjust the size of the receive buffer. Sample code for reference:

void UART_ReceiveCallback(UART_HandleTypeDef *huart) {
    if (huart->Instance == UARTx) {
        if (rxBuff[0] == 0x22) {
            receiveXfer.dataSize = 22;
        } else if (rxBuff[0] == 0x24) {
            receiveXfer.dataSize = 32;
        }
        HAL_UART_Receive_DMA(huart, rxBuff + 1, receiveXfer.dataSize - 1);
    }
}

// inital callback functions
HAL_UART_RegisterCallback(&huart1, HAL_UART_RX_COMPLETE_CB_ID, UART_ReceiveCallback);

2. Receive one byte first to determine the data length, and then receive the remaining data

uint8_t rxBuff[32]; // assume maxlen is 32 bytes

void start_receive() {
    HAL_UART_Receive_DMA(&huart1, rxBuff, 1);
}

void UART_ReceiveCallback(UART_HandleTypeDef *huart) {
    if (huart->Instance == UARTx) {
        if (rxBuff[0] == 0x22) {
            receiveXfer.dataSize = 22;
        } else if (rxBuff[0] == 0x24) {
            receiveXfer.dataSize = 32;
        }
        HAL_UART_Receive_DMA(huart, rxBuff + 1, receiveXfer.dataSize - 1);
    }
}

// inital callback
HAL_UART_RegisterCallback(&huart1, HAL_UART_RX_COMPLETE_CB_ID, UART_ReceiveCallback);

// receive
start_receive();

3. By using ring buffer to get solve fixed lenght issue.

0 件の賞賛
返信

2,947件の閲覧回数
hanmant
Contributor III
Hi @Sam_Gao,

Thanks for update.
below is my uart dma callback method:
/* 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;
}
}
Please let me know how to handle this function.
0 件の賞賛
返信

2,895件の閲覧回数
Sam_Gao
NXP Employee
NXP Employee

Here is only sample code, only for reference.

 

typedef struct
{
    uint16_t length; 
    // others in packet
} packet_header_t;

#define MAX_RX_BUFFER_SIZE 128  // max buff for example
uint8_t rxBuff[MAX_RX_BUFFER_SIZE];
lpuart_transfer_t receiveXfer;

void init_UART_DMA(LPUART_Type *base, lpuart_edma_handle_t *handle)
{
    receiveXfer.data = rxBuff;
    receiveXfer.dataSize = sizeof(packet_header_t); 
    LPUART_TransferReceiveEDMA(base, &receiveXfer, handle);
}

/* 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;

        // Check if the received data contains a complete header
        if (receiveXfer.dataSize >= sizeof(packet_header_t))
        {
            packet_header_t *header = (packet_header_t *)rxBuff;
            uint32_t packetLength = header->length;  // Get the packet length

            // If the current receive buffer size is smaller than the actual packet length, reconfigure the receive buffer
            if (receiveXfer.dataSize < packetLength)
            {
                receiveXfer.dataSize = packetLength;
                LPUART_TransferReceiveEDMA(base, &receiveXfer, handle);
            }
            else
            {
                // Processing received data
                processReceivedData(rxBuff, packetLength);

                // Reconfigure the receive buffer to the initial size and prepare to the next data packet
                receiveXfer.dataSize = sizeof(packet_header_t);
                LPUART_TransferReceiveEDMA(base, &receiveXfer, handle);
            }
        }
    }
}

void processReceivedData(uint8_t *data, uint32_t length)
{
    // FYI
    for (uint32_t i = 0; i < length; i++)
    {
        printf("%02X ", data[i]);
    }
    printf("\n");
}

int main(void)
{
    lpuart_edma_handle_t handle;

    LPUART_Init(LPUART1, &uartConfig);
    LPUART_TransferCreateHandleEDMA(LPUART1, &handle, LPUART_UserCallback, NULL);
    EDMA_CreateHandle(&dmaHandle, DMA0, 1);

    init_UART_DMA(LPUART1, &handle);

    while (1)
    {
        // FYI.
    }

    return 0;
}
0 件の賞賛
返信

2,884件の閲覧回数
hanmant
Contributor III
Hi @Sam_Gao,

Thank for reply.
Below is my edma 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;


edma_config_t userConfig = {0};
uint32_t uiCnt = 0;


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;

/*set RX IDLE parameters*/
lpuartConfig.rxIdleType = kLPUART_IdleTypeStopBit;
lpuartConfig.rxIdleConfig = kLPUART_IdleCharacter32;

/*set LPUART tx rx fifo, receive doesn't use FIFO*/
lpuartConfig.rxFifoWatermark = 0;
/*
If doesn't use tramsmit fifo, set txFifoWatermark=0
Must be care, the maximum fifo depth doesn't exceed allowed
*/
lpuartConfig.txFifoWatermark = FSL_FEATURE_LPUART_FIFO_SIZEn(DEMO_LPUART) - 1;

LPUART_Init(DEMO_LPUART, &lpuartConfig, DEMO_LPUART_CLK_FREQ);

#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
/* 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);
#endif
/* Init the EDMA module */
EDMA_GetDefaultConfig(&userConfig);
#if defined(BOARD_GetEDMAConfig)
BOARD_GetEDMAConfig(userConfig);
#endif
EDMA_Init(EXAMPLE_LPUART_DMA_BASEADDR, &userConfig);
EDMA_CreateHandle(&g_lpuartTxEdmaHandle, EXAMPLE_LPUART_DMA_BASEADDR, LPUART_TX_DMA_CHANNEL);
EDMA_CreateHandle(&g_lpuartRxEdmaHandle, EXAMPLE_LPUART_DMA_BASEADDR, LPUART_RX_DMA_CHANNEL);
#if defined(FSL_FEATURE_EDMA_HAS_CHANNEL_MUX) && FSL_FEATURE_EDMA_HAS_CHANNEL_MUX
EDMA_SetChannelMux(EXAMPLE_LPUART_DMA_BASEADDR, LPUART_TX_DMA_CHANNEL, DEMO_LPUART_TX_EDMA_CHANNEL);
EDMA_SetChannelMux(EXAMPLE_LPUART_DMA_BASEADDR, LPUART_RX_DMA_CHANNEL, DEMO_LPUART_RX_EDMA_CHANNEL);
#endif

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

/* Start to echo. */
char buff[100];
// LPUART_SendEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &sendXfer);
//
// /* Wait send finished */
// while (txOnGoing)
// {
// }

/* Start to echo. */

sendXfer.dataSize = 52;
receiveXfer.data = g_rxBuffer;
receiveXfer.dataSize = 32;// sometimes i receive different len


while (1)
{

/* If RX is idle and g_rxBuffer is empty, start to read data to g_rxBuffer. */
// sometimes i receive different len
if ((!rxOnGoing) && (rxBufferEmpty))
{
rxOnGoing = true;
LPUART_ReceiveEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &receiveXfer);
ProcessReceivedData();

}
if ((!txOnGoing) && (txBufferFull))
{
txOnGoing = true;
LPUART_SendEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &sendXfer);

// while(txOnGoing)
// {
//
// }
//SDK_DelayAtLeastUs(1000, CLOCK_GetFreq(kCLOCK_CpuClk));


}
/* If g_txBuffer is empty and g_rxBuffer is full, copy g_rxBuffer to g_txBuffer. */
if ((!rxBufferEmpty) && (!txBufferFull))
{
//memcpy(g_txBuffer, g_rxBuffer, ECHO_BUFFER_LENGTH);
rxBufferEmpty = true;
txBufferFull = true;
}



}
}
how to deal with this
0 件の賞賛
返信

2,851件の閲覧回数
Sam_Gao
NXP Employee
NXP Employee

what is your issues? 

0 件の賞賛
返信

2,848件の閲覧回数
hanmant
Contributor III
Thank for reply @Sam_Gao,
Uart dma used for rs485 communication.
So continue sender sending continuously frames and size of this frame is 52 bytes and this frame contains system related data exchange.
But at run time sender send request for firmware update and size of this frame is 11 bytes .
Whenever I request for other 52 bytes communication stops means it dma uart got stuck.
So currently I'm not able to receive request of firmware update because of i don't know how to set size.
0 件の賞賛
返信

2,758件の閲覧回数
Sam_Gao
NXP Employee
NXP Employee

Hi @hanmant 

I did know the frame size is changeable, so I try to provide some useful methods for reference, such as interrupt , callback function or ring buffer to dynamically adjust the size, I can't support to provide whole dedicated customized applications.

BTW, you can also refer to the example(DMA, ringbuff) 'evkminxrt1024_lpuart_edma_rb_transfer' which used ring buf and updated in its callback functions.

0 件の賞賛
返信

2,754件の閲覧回数
hanmant
Contributor III
Hi @Sam_Gao,

Thanks for reply .
Whatever you suggested i have tried but those were not useful.
0 件の賞賛
返信

2,809件の閲覧回数
hanmant
Contributor III
Hi @Sam_Gao,

Any update on this?
0 件の賞賛
返信

2,762件の閲覧回数
hanmant
Contributor III

Hi @Sam_Gao 

I have received any response.

0 件の賞賛
返信

2,910件の閲覧回数
hanmant
Contributor III
0 件の賞賛
返信