Hello,
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);
va_end(argp);
// Increment the count to include the NULL character also.
CurrentDMABuffer.count++;
}
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)
{
CyU3PDmaBufferFree(CurrentDMABuffer.buffer);
}
CyU3PMutexPut(&EP1IN_DebugLock);
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
Christophe
Solved! Go to Solution.
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 🙂
Regards
Christophe