FX3: UART - receive data with DMA into CPU's buffer causes Error 73 CY_U3P_ERROR_DMA_FAILURE

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

cross mob
GrHa_3282776
Level 1
Level 1
5 replies posted 5 questions asked First reply posted

I have FX3 CYUSB2014 / 3014 and I'm trying to make UART work in DMA mode to receive and process data from UART.  Using a Manual DMA Channel to read data, and process in a callback.  Right now, it just sends the data over the host USB (CDC Interface)  I've tried different buffer sizes and counts.

Sending "packets" of 32 bytes at a time to test, After about 4-16 packets it fails with error 73, CY_U3P_ERROR_DMA_FAILURE.  Any later calls to CyU3PDmaChannelSetWrapUp return error 71 - CY_U3P_ERROR_INVALID_SEQUENCE.

Wondering why it fails in the first place, or what can be done to reset, and recover the data.

Thanks-Greg

INIT:

CyU3PReturnStatus_t InitializeDebugConsole(void)
{
CyU3PUartConfig_t uartConfig;
CyU3PDmaChannelConfig_t dmaConfig;
CyU3PReturnStatus_t Status = CY_U3P_SUCCESS;

Status = CyU3PUartInit(); // Start the UART driver
CheckStatus("CyU3PUartInit", Status);

CyU3PMemSet ((uint8_t *)&uartConfig, 0, sizeof (uartConfig));
uartConfig.baudRate = CY_U3P_UART_BAUDRATE_115200; //default buad of UART
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;
Status = CyU3PUartSetConfig(&uartConfig, UartCallback); // Configure the UART hardware
CheckStatus("CyU3PUartSetConfig", Status);

Status = CyU3PUartTxSetBlockXfer(0xFFFFFFFF); // Send as much data as I need to
CheckStatus("CyU3PUartTxSetBlockXfer", Status);
Status = CyU3PDebugInit(CY_U3P_LPP_SOCKET_UART_CONS, 6); // Attach the Debug driver above the UART driver
if (Status == CY_U3P_SUCCESS) glDebugTxEnabled = CyTrue;
CheckStatus("ConsoleOutEnabled", Status);
CyU3PDebugPreamble(CyFalse); // Skip preamble, debug info is targeted for a person

// Now setup a DMA channel to receive characters from the Uart Rx
Status = CyU3PUartRxSetBlockXfer(1); //was 1 GH 7/1/2021
CheckStatus("CyU3PUartRxSetBlockXfer", Status);
CyU3PMemSet((uint8_t *)&dmaConfig, 0, sizeof(dmaConfig));
dmaConfig.size = 128; // 16 is Minimum size allowed, I only need 1 byte. sb multiples of 16
dmaConfig.count = 8; // I can't type faster than the Uart Callback routine!
dmaConfig.prodSckId = CY_U3P_LPP_SOCKET_UART_PROD;
dmaConfig.consSckId = CY_U3P_CPU_SOCKET_CONS;
dmaConfig.dmaMode = CY_U3P_DMA_MODE_BYTE;
dmaConfig.notification = CY_U3P_DMA_CB_PROD_EVENT;
Status = CyU3PDmaChannelCreate(&glUARTtoCPU_Handle, CY_U3P_DMA_TYPE_MANUAL_IN, &dmaConfig);
CheckStatus("CreateDebugRxDmaChannel", Status);
if (Status != CY_U3P_SUCCESS) CyU3PDmaChannelDestroy(&glUARTtoCPU_Handle);
else
{
Status = CyU3PDmaChannelSetXfer(&glUARTtoCPU_Handle, 0); //Zero for infinite transfer
CheckStatus("ConsoleInEnabled", Status);
}
return Status;
}

 

 

CALLBACK:

 

void UartCallback(CyU3PUartEvt_t Event, CyU3PUartError_t Error)
// Handle characters typed in by the developer
{
CyU3PDmaBuffer_t ConsoleInDmaBuffer;
CyU3PReturnStatus_t Status = CY_U3P_SUCCESS;
char pInputChar[32] = ""; 
uint16_t bufferlen ;

if (Event == CY_U3P_UART_EVENT_RX_DONE)
{
Status = CyU3PDmaChannelSetWrapUp(&glUARTtoCPU_Handle);
CheckStatus("CyU3PDmaChannelSetWrapUp", Status);

if(Status == CY_U3P_SUCCESS)
{
Status = CyU3PDmaChannelGetBuffer(&glUARTtoCPU_Handle, &ConsoleInDmaBuffer, CYU3P_NO_WAIT);
CheckStatus("CyU3PDmaChannelGetBuffer", Status);

if(Status == CY_U3P_SUCCESS)
{
if (ConsoleInDmaBuffer.count > 0)
{
if (ConsoleInDmaBuffer.count > 31) //max of 31 to prevent filling the string.
{
bufferlen = 31;
}
else
{
bufferlen = ConsoleInDmaBuffer.count;
}

strncpy(pInputChar,(char*)ConsoleInDmaBuffer.buffer,bufferlen);

if (gUartEcho)
{
DebugPrint(0, "%s", pInputChar); // Echo the character
}
// If True, the characters typed on the debug console are sent to the PC Host via the CDC Interface
if (gUartReTransOnCDC)
{
SendString(pInputChar);
}
}
}
}

CyU3PDmaChannelDiscardBuffer(&glUARTtoCPU_Handle);
}
CyU3PUartRxSetBlockXfer(1); //Set back to 1 to reset
}

 

 

 

 

 

 

0 Likes
1 Solution

Hello,

CY_U3P_ERROR_DMA_FAILURE comes from API version 1.3  function: CyU3PDmaChannelGetBuffer()

>> I understand that this error is returned by CyU3PDmaChannelGetBuffer API called in UartCallback

If yes and if you want to use UART in DMA mode, please try the following

- Call only CyU3PDmaChannelSetWrapUp API in the UartCallback and set an event using  CyU3PEventSet API

- Call CyU3PEventGet in the thread entry function for loop and call CyU3PDmaChannelGetBuffer and then continue the rest of the processing in the for loop and at the end of the processing call CyU3PUartRxSetBlockXfer to enable receiving 1 byte for the next transfer.

Regards,
Rashi

View solution in original post

0 Likes
3 Replies
Rashi_Vatsa
Moderator
Moderator
Moderator
5 likes given 500 solutions authored 1000 replies posted

Hello,

From the description I understand that the data transfer is done from UART > CPU >  USB. And after some successful data transfer there are failures seen.

Sending "packets" of 32 bytes at a time to test, After about 4-16 packets it fails with error 73, CY_U3P_ERROR_DMA_FAILURE. 

>> Please let me know the API which returns CY_U3P_ERROR_DMA_FAILURE.

Also, as only 1 byte is committed at a time, the DMA buffer size can be kept as 16 bytes and the DMA buffer count can be increased. 

Please confirm if MANUAL OUT (CPU to USB) channel is used for sending data through CDC interface.

Also, please let me know the reason of using DMA transfer. Usually, when transfer size is less (32 bytes) , we recommend to use register mode as done the UsbUart example of he SDK

Regards,
Rashi
0 Likes
GrHa_3282776
Level 1
Level 1
5 replies posted 5 questions asked First reply posted

Yes, Manual In and Manual Out for USB to CPU.  I will switch to register mode, its actually in example named uartlpregmode.   CY_U3P_ERROR_DMA_FAILURE comes from API version 1.3  function: CyU3PDmaChannelGetBuffer()

 

0 Likes

Hello,

CY_U3P_ERROR_DMA_FAILURE comes from API version 1.3  function: CyU3PDmaChannelGetBuffer()

>> I understand that this error is returned by CyU3PDmaChannelGetBuffer API called in UartCallback

If yes and if you want to use UART in DMA mode, please try the following

- Call only CyU3PDmaChannelSetWrapUp API in the UartCallback and set an event using  CyU3PEventSet API

- Call CyU3PEventGet in the thread entry function for loop and call CyU3PDmaChannelGetBuffer and then continue the rest of the processing in the for loop and at the end of the processing call CyU3PUartRxSetBlockXfer to enable receiving 1 byte for the next transfer.

Regards,
Rashi
0 Likes