FX3 : UART to USB minimal DMA size workaround

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

cross mob
ChRO_4339966
Level 3
Level 3

Hello,

On my FX3 project I created an EP discussing with a FPGA through UART link.

UART is configured on both sides to work with Byte mode DMA (dmaConfig.dmaMode = CY_U3P_DMA_MODE_BYTE)

All this works like a charm, except that I live with a limitation that I would like to fix : at reception (FPGA->FX3), DMA requires a minimal of 16 bytes to operate, which seems to be a limitation of FX3 (UART?) DMA engine.

This means if my FPGA sends less than 16 bytes of data they will not be forwarded to my USB endpoint.

I would like to keep it as simple as possible to avoid having FX3 firmware sniffing at UART events and processing packets. Is there a simple solution for that ?

Hereunder is my UART configuration :

CyU3PReturnStatus_t ConfigureUartDma(void) {

    CyU3PReturnStatus_t Status = CY_U3P_SUCCESS;

    CyU3PDmaChannelConfig_t dmaConfig;

    // Create a AUTO channel for the USB to UART transfer

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

    dmaConfig.size           = 128; // Maximal number of bytes allowed per DMA buffer.

                                    // A larger message would stuck the EP

    dmaConfig.count          = 32;  // Store up to 32 words in DMA buffers

    dmaConfig.prodSckId      = FPGA_CONFIG_ENDPOINT_SOCKET;

    dmaConfig.consSckId      = UART_CONSUMER_SOCKET;

    dmaConfig.dmaMode        = CY_U3P_DMA_MODE_BYTE;

    Status = CyU3PDmaChannelCreate(&Usb2Uart_Handle, CY_U3P_DMA_TYPE_AUTO, &dmaConfig);

    // Start the DMA Channel with transfer size to Infinite

    Status = CyU3PDmaChannelSetXfer(&Usb2Uart_Handle, 0);

    // Create a AUTO channel for the UART to USB transfer

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

    dmaConfig.size          = 16;   // Minimal value allowed by DMA.

                                    // Any UART message longer than this will be split in 16 bytes "packets"

    dmaConfig.count         = 32;   // Up to 32 words can be stored in DMA buffers

    dmaConfig.prodSckId     = UART_PRODUCER_SOCKET;

    dmaConfig.consSckId     = FPGA_STATUS_ENDPOINT_SOCKET;

    dmaConfig.dmaMode       = CY_U3P_DMA_MODE_BYTE;

    Status = CyU3PDmaChannelCreate(&Uart2Usb_Handle, CY_U3P_DMA_TYPE_AUTO_SIGNAL, &dmaConfig);

    // Start the DMA Channel with transfer size to Infinite

    Status = CyU3PDmaChannelSetXfer(&Uart2Usb_Handle, 0);

    return Status;

}

Thanks in advance

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.

Hello Christophe,

I didn't get the question. Can you restate it?

From the previous post what i understood was that you want to commit the partial buffer.

As per your previous response, DMA channel from UART to USB is AUTO_SIGNAL. Still you can use CyU3PDmaChannelSetWrapUp API in the for{}. But you need to register a call back and handle the PROD_EVENT. In the PROD_EVENT the partial buffer can be committed. (Refer to the modified UsbUart example with DMA_TYPE_ AUTO_SIGNAL channel between uart and usb). You can check the working of the  attached firmware and make changes to your firmware accordingly.

If you wan to use DMA Manual channel you need to commit the data manually to the consumer socket. This is done when the buffer is full or PROD_EVENT occurs and in DMA channel you commit that buffer.

But when the buffer is partially filled there will not be any PROD_EVENTS. So when you call  CyU3PDmaChannelSetWrapUp there will be PROD_EVENT even when the buffer is partially filled. In the callback, this buffer will then be committed to the consumer socket.

We use this API in the for{} (as per usbuart example) to continuously check for partial buffer and commit it.

Regards,

Rashi

Regards,
Rashi

View solution in original post

0 Likes
17 Replies