CX3 UART RX mode + DMA setting

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
wayu_4276666
Level 3
Level 3
25 replies posted 10 replies posted 10 questions asked

Hi Sir,

I have an application to use the UART Rx +DMA,

If I send an ASCII to UART Rx,  I hope sent an ASCII and CX3 go into the callback function once.

but now I must sent 16 times ASCII, the CX3 can go into the callback function once.

my setting as below:

void UART_and_DMA_Init(void)
{
    CyU3PUartConfig_t uartConfig;
    CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
    CyU3PDmaChannelConfig_t dmaCfg;

    status = CyU3PUartInit();
    if (status != CY_U3P_SUCCESS)
    {
        return;
    }

    CyU3PMemSet ((uint8_t *)&uartConfig, 0, sizeof(uartConfig));

    uartConfig.baudRate = CY_U3P_UART_BAUDRATE_230400;
    uartConfig.stopBit = CY_U3P_UART_ONE_STOP_BIT;
    uartConfig.parity = CY_U3P_UART_NO_PARITY;
    uartConfig.txEnable = CyTrue;
    uartConfig.rxEnable = CyTrue;
    uartConfig.flowCtrl = CyFalse;
    uartConfig.isDma = CyTrue;

    /* Set the UART configuration */
    status = CyU3PUartSetConfig (&uartConfig, NULL);

    if (status != CY_U3P_SUCCESS)
    {
        return;
    }

    /* Set the UART transfer */
    status = CyU3PUartTxSetBlockXfer (0xFFFFFFFF);
    if (status != CY_U3P_SUCCESS)
    {
        return;
    }

    status = CyU3PUartRxSetBlockXfer (0xFFFFFFFF);
    if (status != CY_U3P_SUCCESS)
    {
          /* Error handling */
          CyCx3UvcAppErrorHandler(status);
    }

    /* Initialize the debug application */
    status = CyU3PDebugInit (CY_U3P_LPP_SOCKET_UART_CONS, 8);
    if (status != CY_U3P_SUCCESS)
    {
          return;
    }

    CyU3PDebugPreamble (CyFalse);

/*
***********************
** DMA UART setting **
***********************/
    CyU3PMemSet ((uint8_t *)&dmaCfg, 0, sizeof(dmaCfg));

    dmaCfg.size = 16;
    dmaCfg.count = 1;
    dmaCfg.prodSckId = CY_U3P_LPP_SOCKET_UART_PROD;
    dmaCfg.consSckId = CY_U3P_CPU_SOCKET_CONS;
    dmaCfg.prodAvailCount = 0;
    dmaCfg.prodHeader = 0;
    dmaCfg.prodFooter = 0;
    dmaCfg.consHeader = 0;
    dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;
    dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT;
    dmaCfg.cb = UART_RX_DAM_Callback;

    // Create the channel
    status = CyU3PDmaChannelCreate (&glUartLpChHandle,
    CY_U3P_DMA_TYPE_MANUAL_IN, &dmaCfg);

    if (status != CY_U3P_SUCCESS)
    {
          //Error handling
          CyCx3UvcAppErrorHandler(status);
    }

// Set DMA Channel transfer size
    status = CyU3PDmaChannelSetXfer (&glUartLpChHandle, 0);
    if (status != CY_U3P_SUCCESS)
    {
        // Error handling //
        CyCx3UvcAppErrorHandler(status);
    }

}

 Now, I guess the 16 times ASCII  go into call back function once is     "dmaCfg.size = 16;"

I have tried to set the dmaCfg.size = 1, but the CX3 does not work. 

How to modify the setting to achieve one ASCII make the CX3 go into the callback function once? 

BR

Ben

 

 

0 Likes
1 Solution
JayakrishnaT_76
Moderator
Moderator
Moderator
First question asked 1000 replies posted 750 replies posted

Hello Ben,

Yes, your understanding is correct. The issue is related to the DMA buffer size that you have used in the firmware.

The following are the reasons for the issue that you are facing:

1. If the DMA buffer size is 16, then the DMA buffer will be sent out to the consumer socket only after the 16 bytes are filled by the producer.

2. The DMA buffer size cannot be 1 as the DMA buffer size should be a multiple of 16 bytes.

Please refer to the example project cyfxusbuart that comes along with FX3 SDK. The example project can be found in the following location:

C:\Program Files (x86)\Cypress\EZ-USB FX3 SDK\1.3\firmware\serialif_examples\cyfxusbuart

This project has a mechanism to wrap up the DMA buffer before it becomes full. This is done by using the API CyU3PDmaChannelSetWrapUp (). You can find the complete implementation of this mechanism inside the infinite for loop. Please refer to this project and make the same modifications on your project. Please let me know if this suggestion can fix the issue seen or not.

Best Regards,
Jayakrishna

View solution in original post

0 Likes
6 Replies
JayakrishnaT_76
Moderator
Moderator
Moderator
First question asked 1000 replies posted 750 replies posted

Hello Ben,

Yes, your understanding is correct. The issue is related to the DMA buffer size that you have used in the firmware.

The following are the reasons for the issue that you are facing:

1. If the DMA buffer size is 16, then the DMA buffer will be sent out to the consumer socket only after the 16 bytes are filled by the producer.

2. The DMA buffer size cannot be 1 as the DMA buffer size should be a multiple of 16 bytes.

Please refer to the example project cyfxusbuart that comes along with FX3 SDK. The example project can be found in the following location:

C:\Program Files (x86)\Cypress\EZ-USB FX3 SDK\1.3\firmware\serialif_examples\cyfxusbuart

This project has a mechanism to wrap up the DMA buffer before it becomes full. This is done by using the API CyU3PDmaChannelSetWrapUp (). You can find the complete implementation of this mechanism inside the infinite for loop. Please refer to this project and make the same modifications on your project. Please let me know if this suggestion can fix the issue seen or not.

Best Regards,
Jayakrishna
0 Likes
wayu_4276666
Level 3
Level 3
25 replies posted 10 replies posted 10 questions asked

Hi Sir,

Use your recommend example , it can wrap up the data  which is resident in DMA Buffer.

But I just can into callback cb first time, after first time CX3 can not into callback anymore. 

How do I fix this situation?

 

0 Likes

Hello,

Please elaborate the issue seen now so that I can understand it better. As per my understanding, the CX3 is able to wrap up the data in the DMA buffer associated with the UART socket only once. After this, CX3 does not wrap up the data in the DMA buffer associated with the UART socket. The data will be sent out only when the DMA buffer gets full instead of sending 1 byte at a time. Please confirm if my understanding is correct or not. Please correct me if my understanding is wrong.

Also, please share the source code of your project so that I can verify the changes made on it.

Best Regards,
Jayakrishna
0 Likes
wayu_4276666
Level 3
Level 3
25 replies posted 10 replies posted 10 questions asked

 

Hi Sir,

As per my understanding, the CX3 is able to wrap up the data in the DMA buffer associated with the UART socket only once. After this, CX3 does not wrap up the data in the DMA buffer associated with the UART socket.

>>Yes.

The data will be sent out only when the DMA buffer gets full instead of sending 1 byte at a time.

>>1.After CX3 first time into DMA callback,  even Terminal send 16 Byte data, CX3 would not into DMA callback anymore.

>> 2.After CX3 first time into DMA callback, Terminal send 3 Byte data, CX3 execute  the CyU3PDmaChannelSetWrapUp(), CX3 would not into DMA callback anymore.

My setting as below:

void UART_and_DMA_Init(void)
{
    CyU3PUartConfig_t uartConfig;
    CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
    CyU3PDmaChannelConfig_t dmaCfg;

    status = CyU3PUartInit();
    if (status != CY_U3P_SUCCESS)
    {
        return;
    }

    CyU3PMemSet ((uint8_t *)&uartConfig, 0, sizeof(uartConfig));

    uartConfig.baudRate = CY_U3P_UART_BAUDRATE_230400;
    uartConfig.stopBit = CY_U3P_UART_ONE_STOP_BIT;
    uartConfig.parity = CY_U3P_UART_NO_PARITY;
    uartConfig.txEnable = CyTrue;
    uartConfig.rxEnable = CyTrue;
    uartConfig.flowCtrl = CyFalse;
    uartConfig.isDma = CyTrue;

    /* Set the UART configuration */
    status = CyU3PUartSetConfig (&uartConfig, NULL);

    if (status != CY_U3P_SUCCESS)
    {
        return;
    }

    /* Set the UART transfer */
    status = CyU3PUartTxSetBlockXfer (0xFFFFFFFF);
    if (status != CY_U3P_SUCCESS)
    {
        return;
    }

    status = CyU3PUartRxSetBlockXfer (0xFFFFFFFF);
    if (status != CY_U3P_SUCCESS)
    {
          /* Error handling */
          CyCx3UvcAppErrorHandler(status);
    }

    /* Initialize the debug application */
    status = CyU3PDebugInit (CY_U3P_LPP_SOCKET_UART_CONS, 8);
    if (status != CY_U3P_SUCCESS)
    {
          return;
    }

    CyU3PDebugPreamble (CyFalse);

/*
***********************
** DMA UART setting **
***********************/
    CyU3PMemSet ((uint8_t *)&dmaCfg, 0, sizeof(dmaCfg));

    dmaCfg.size = 16;
    dmaCfg.count = 1;
    dmaCfg.prodSckId = CY_U3P_LPP_SOCKET_UART_PROD;
    dmaCfg.consSckId = CY_U3P_CPU_SOCKET_CONS;
    dmaCfg.prodAvailCount = 0;
    dmaCfg.prodHeader = 0;
    dmaCfg.prodFooter = 0;
    dmaCfg.consHeader = 0;
    dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;
    dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT;
    dmaCfg.cb = UART_RX_DAM_Callback;

    // Create the channel
    status = CyU3PDmaChannelCreate (&glUartLpChHandle,
    CY_U3P_DMA_TYPE_MANUAL_IN, &dmaCfg);

    if (status != CY_U3P_SUCCESS)
    {
          //Error handling
          CyCx3UvcAppErrorHandler(status);
    }

// Set DMA Channel transfer size
    status = CyU3PDmaChannelSetXfer (&glUartLpChHandle, 0);
    if (status != CY_U3P_SUCCESS)
    {
        // Error handling //
        CyCx3UvcAppErrorHandler(status);
    }

}

UART_RX_DAM_Callback (
CyU3PDmaChannel *chHandle, /* Handle to the DMA channel. */
CyU3PDmaCbType_t type, /* Callback type. */
CyU3PDmaCBInput_t *input) /* Callback status. */
{

    uint8_t rxData;
    uint32_t count;
    CyU3PReturnStatus_t status = CY_U3P_SUCCESS;

    uint8_t i;


    g_dma_event_flag++;

    CyU3PDebugPrint (4, "\n\rtype=%d",type);

    if (type == CY_U3P_DMA_CB_PROD_EVENT)
    {
        CyU3PDmaChannelCommitBuffer (&glUartLpChHandle, input->buffer_p.count, 0);

        CyU3PMemCopy ( &gl_UART_Rx_Buffer[0], &input->buffer_p.buffer[0] , input->buffer_p.count);

        glPktsPending++;
    }

    return;

}

BR

Ben

 

 

 

 

0 Likes

Hello,

Please test your hardware using the example project cyfxusbuart. As mentioned before, this project will wrap up the DMA buffers automatically after 50ms. Please check if you are getting the data transmitted properly with this project.

Also, please share the complete project so that I can have a look at it. It seems like there is some problem with the implementation of the wrap up logic.

Best Regards,
Jayakrishna
0 Likes

Hello,

After referring to the code, it was found that the customer was using MANUAL IN channel (producer: UART and consumer: CPU). Inside the DMA callback function, the customer was copying the data from the DMA buffers into a global buffer. But, the buffers were not discarded. The API CyU3PDmaChannelDiscardBuffer() was used to discard the DMA buffer after copying it into a global buffer. With this modification, the customer was able to wrap up the data in the DMA buffer associated with the UART channel again.

Best Regards,

Jayakrishna

Best Regards,
Jayakrishna
0 Likes