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