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

USB superspeed peripherals

Level 3
Level 3


I am working on a John Hyde example (Bidir GPIF Slave interface from GPIF_Example6) where I have a Debug console attached to UART, and I am modifying it to copy these debug messages to EP1 IN (Bulk configuration).

I also followed some DualConsole example where an equivalent work is performed to retarget messages to I2C.

What I did is that I defined a manual DMA this way

     /* DMA Definition */

    // Setup and flush the endpoint

    Status = CyU3PSetEpConfig(0x81, &epConfig);

    // Create a AUTO channel for the Status to USB transfer, CPU detects and COMMITs the last short packet

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

    dmaConfig.size           = CY_U3P_DEBUG_DMA_BUFFER_SIZE;         // Use same size buffers for all USB Speeds

    dmaConfig.count          = 15;

    dmaConfig.prodSckId      = CY_U3P_CPU_SOCKET_PROD;

    dmaConfig.consSckId      = CY_U3P_UIB_SOCKET_CONS_1;

    dmaConfig.dmaMode        = CY_U3P_DMA_MODE_BYTE;

    Status = CyU3PDmaChannelCreate(&CPU2USB_Handle, CY_U3P_DMA_TYPE_MANUAL_OUT, &dmaConfig);

    Status = CyU3PUsbFlushEp(0x81);

This DMA is then used at each call to mynew DualDebugPrint function largely inspired by John Hyde DualConsole example:

CyU3PReturnStatus_t DualDebugPrint(uint8_t Priority, char* Message, ...)


    // This takes the same parameters as CyU3PDebugPrint and my code is modeled on CyU3PDebugPrint

    // I format Message, including any parameters, into a DMA Buffer then Queue this buffer for EP1 IN

    // I check for Console Input after every Console Output

    // A Queue timeout is used to ensure that Console Input is called at least once a second

    CyU3PReturnStatus_t Status = CY_U3P_SUCCESS;

    va_list argp;

    CyU3PDmaBuffer_t CurrentDMABuffer;

    // First do some error checking

    if (Priority > glDebugTraceLevel) return CY_U3P_SUCCESS;

    if (CyU3PThreadIdentify() == NULL) return CY_U3P_ERROR_INVALID_CALLER;    // This function can only be called from a thread

    // OK to proceed, get a buffer then use a Cypress routine to do the Message interpretation

    CyU3PMutexGet(&EP1IN_DebugLock, CYU3P_WAIT_FOREVER);

    // Allocate the buffer for formatting the string.

    CurrentDMABuffer.buffer = CyU3PDmaBufferAlloc(CY_U3P_DEBUG_DMA_BUFFER_SIZE);

    if (CurrentDMABuffer.buffer == NULL) CheckStatus("CyU3PDmaBufferAlloc", CY_U3P_ERROR_MEMORY_ERROR);

    if (Status == CY_U3P_SUCCESS)


        CurrentDMABuffer.count = CurrentDMABuffer.size = CY_U3P_DEBUG_DMA_BUFFER_SIZE;

        CurrentDMABuffer.status = 0;

        va_start(argp, Message);

        // MyDebugSNPrint updates CurrentDMABuffer.count

        Status = MyDebugSNPrint(CurrentDMABuffer.buffer, &CurrentDMABuffer.count, Message, argp);


        // Increment the count to include the NULL character also.



    if (Status == CY_U3P_SUCCESS)


        // Copy the output to the UART Console also for this dual console example

        CyU3PDebugPrint(4, "%s", CurrentDMABuffer.buffer);

        // Push this message to EP1 IN

        Status = CyU3PDmaChannelSetupSendBuffer(&CPU2USB_Handle, &CurrentDMABuffer);

        //CheckStatus("CyU3PDmaChannelSetupSendBuffer", Status);

        // Wait there for DMA completion (actually a non-sense ?)

        //Status = CyU3PDmaChannelWaitForCompletion(&CPU2USB_Handle, CYU3P_WAIT_FOREVER);


    if (CurrentDMABuffer.buffer != NULL)





    return Status;


It works fine but what happens is that while UART messages are received OK, I loose frames sent to EP1 when I don't read them fast enough (via USB Control Center).

Also, looking at how loss occur, it seems that number of DMA buffers are actually lower than value configured (16 in my case).

Is there a way to make sure data are not lost within FX3 without "locking" the whole FW (eg using CyU3PDmaChannelWaitForCompletion function) and other DMAs execution ?

Thanks for help


1 Solution
Level 3
Level 3

Hi Sridhar,

Thanks for proposal.

I actually moved to a much easier solution, pushing debug messages to USB socket at initialisation :

CyU3PDebugInit(CY_U3P_UIB_SOCKET_CONS_4, 8);

This makes my code much more compact 🙂



View solution in original post

3 Replies