No callback call with CU_U3P_DMA_CB_CONS_SUSP event in AUTO DMA mode

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

cross mob
deloc_2993276
Level 1
Level 1

Hi! I am trying to do next thing:

  After receiving some signal over GPIO, I have to suspend data flow from GPIF to USB in AUTO DMA mode. But I can“t get access buffer to write a signature of that signal. My code is like this/


 


 

// Notification event callback

void DmaNotificationEvent(CyU3PDmaChannel *handle, CyU3PDmaCbType_t type, CyU3PDmaCBInput_t *input)

{

  if(type == CY_U3P_DMA_CB_CONS_SUSP)

  {

  }

}


 

That is code where I“m configuring AUTO DMA channel:


 

  /* Create a DMA AUTO channel for the GPIF to USB transfer. */

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

  dmaCfg.size = CY_FX_DMA_BUF_SIZE;

  dmaCfg.count = CY_FX_DMA_BUF_COUNT;

  dmaCfg.prodSckId = CY_FX_GPIF_PRODUCER_SOCKET;

  dmaCfg.consSckId = CY_FX_EP_CONSUMER_SOCKET;

  dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;

dmaCfg.notification = CY_U3P_DMA_CB_CONS_SUSP;

  dmaCfg.cb = DmaNotificationEvent;

dmaCfg.prodHeader = 0;

dmaCfg.prodFooter = 0;

dmaCfg.consHeader = 0;

dmaCfg.prodAvailCount = 0;


 

  apiRetStatus = CyU3PDmaChannelCreate (&glDmaChHandle, CY_U3P_DMA_TYPE_AUTO, &dmaCfg);

  if (apiRetStatus != CY_U3P_SUCCESS)

  {

CyU3PDebugPrint (4, "CyU3PDmaChannelCreate failed, Error code = %d\n", apiRetStatus);

CyFxAppErrorHandler(apiRetStatus);

  }


 

  /* Set DMA Channel transfer size */

  apiRetStatus = CyU3PDmaChannelSetXfer (&glDmaChHandle, CY_FX_GPIFTOUSB_DMA_TX_SIZE);

  if (apiRetStatus != CY_U3P_SUCCESS)

  {

CyU3PDebugPrint (4, "CyU3PDmaChannelSetXfer failed, Error code = %d\n", apiRetStatus);

CyFxAppErrorHandler(apiRetStatus);

  }

 
  From my thread routine I“m calling that function:

  apiRetStatus = CyU3PDmaChannelSetSuspend(&glDmaChHandle,   CY_U3P_DMA_SCK_SUSP_NONE,   CY_U3P_DMA_SCK_SUSP_CONS_PARTIAL_BUF);


  and nothing happens. No call to DmaNotificationEvent() with CY_U3P_DMA_CB_CONS_SUSP event. What is the reason? I could not find any information on that situation. Thank you for your reply in advance!

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

Hello,

- I have attached the USBBulkLoopAuto example that comes with the FX3 SDK with two additional vendor commands (0xFF) and (0xFB).

    - 0xFF -> This vendor request suspends the DMA channel consumer with the suspend type set as CY_U3P_DMA_SCK_SUSP_CONS_PARTIAL_BUF using the CyU3PDmaChannelSetSuspend() API.

    - 0xFB -> This vendor request gets the buffer from suspended DMA channel and modifies the data present in it. (I have modified the buffer contents to be 0xFF, 0xEE, 0xDD). The modified buffer is then committed to the host. The CyU3PDmaChennalSetSuspend() API is called again with the consumer suspend type set as CY_U3P_DMA_SCK_SUSP_NONE. The channel is then resumed using the CyU3PDmaChannelResume() API.

Test Procedure:

- Test if you are able to send and receive the same data using the OUT and IN endpoints.

- Using Cypress USB Control Center, issue 0xFF vendor command with the 'Bytes to Transfer' field set to 0.

(The DMA channel consumer is now configured to be suspended when there is a partial buffer)

- On the OUT endpoint, send bytes of data that is fewer(say 100 bytes) than the DMA buffer size, which is set to 1024 in this firmware. This will trigger the suspend on the DMA channel consumer.

- Try reading data from IN endpoint. This will result in failure indicating that the channel is suspended.

- Issue the 0xFB vendor command to commit the data (0xFF, 0xEE, 0xDD) and to revert back the suspend condition and resume the channel.

- Perform read data from the IN endpoint. 0xFF, 0xEE, 0xDD data will be transferred.

Regarding your statement on CY_U3P_ERROR_INVALID_SEQUENCE error:

CyU3PDmaChannelGetBuffer() API returns this error because the firmware does not have any handle to obtain the buffer. The API can be successful only when the firmware gets control over the DMA channel which is performed by the CyU3PDmaChannelSetSuspend() API.

Kindly, test the attached firmware with the mentioned procedure and let me know if you still have queries.

Best regards,

Srinath S

View solution in original post

0 Likes
5 Replies
SrinathS_16
Moderator
Moderator
Moderator
1000 replies posted 750 replies posted 500 replies posted

Hello,

When using AUTO DMA channel, the CyU3PDmaChannelCreate() API sets up the buffers for DMA channel and the hardware takes care of the data transfer between the producer and the consumer sockets. There are no event signals handled by the firmware in this mode. To include the event signalling along with the AUTO DMA channel, please use the AUTO - SIGNAL mode. For documentation, please refer to the FX3 Programmer's Manual from the FX3 SDK.

Best regards,
Srinath S

0 Likes

Hi, again! Yes, I know that! But than what means next information taken from EZ-USB FX3 SDK Firmware API Guide:

5.17.4.7 CyU3PReturnStatus_t CyU3PDmaChannelGetBuffer ( CyU3PDmaChannel ∗ handle, CyU3PDmaBuffer_t ∗

buffer p, uint32 t waitOption )

Get the current buffer pointer.

Description

This function waits until a buffer is ready on the channel, and then returns a pointer to the buffer status.

The ready condition is defined differently for different DMA channel types:

1. For MANUAL and MANUAL_IN DMA channels, a ready buffer is one which has been filled with data by the

producer.

2. For MANUAL_OUT channels, a ready buffer is an empty buffer that can be filled by the firmware.

3. For AUTO channels, this API can only be called when the consumer socket is suspended. This mechanism

is supported to facilitate reading the buffer status when the channel has been suspended using the CY_U3-

P_DMA_SCK_SUSP_CONS_PARTIAL_BUF option.

I've tryed to use that function also, after calling CyU3PDmaChannelSetSuspend() of course, from my working thread, but it return code was CY_U3P_ERROR_INVALID_SEQUENCE. How to understand that marked text? So, AUTO channel could be suspended, but how can I get access to buffer than? That is the question. Thank you for your support!

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

Hello,

- I have attached the USBBulkLoopAuto example that comes with the FX3 SDK with two additional vendor commands (0xFF) and (0xFB).

    - 0xFF -> This vendor request suspends the DMA channel consumer with the suspend type set as CY_U3P_DMA_SCK_SUSP_CONS_PARTIAL_BUF using the CyU3PDmaChannelSetSuspend() API.

    - 0xFB -> This vendor request gets the buffer from suspended DMA channel and modifies the data present in it. (I have modified the buffer contents to be 0xFF, 0xEE, 0xDD). The modified buffer is then committed to the host. The CyU3PDmaChennalSetSuspend() API is called again with the consumer suspend type set as CY_U3P_DMA_SCK_SUSP_NONE. The channel is then resumed using the CyU3PDmaChannelResume() API.

Test Procedure:

- Test if you are able to send and receive the same data using the OUT and IN endpoints.

- Using Cypress USB Control Center, issue 0xFF vendor command with the 'Bytes to Transfer' field set to 0.

(The DMA channel consumer is now configured to be suspended when there is a partial buffer)

- On the OUT endpoint, send bytes of data that is fewer(say 100 bytes) than the DMA buffer size, which is set to 1024 in this firmware. This will trigger the suspend on the DMA channel consumer.

- Try reading data from IN endpoint. This will result in failure indicating that the channel is suspended.

- Issue the 0xFB vendor command to commit the data (0xFF, 0xEE, 0xDD) and to revert back the suspend condition and resume the channel.

- Perform read data from the IN endpoint. 0xFF, 0xEE, 0xDD data will be transferred.

Regarding your statement on CY_U3P_ERROR_INVALID_SEQUENCE error:

CyU3PDmaChannelGetBuffer() API returns this error because the firmware does not have any handle to obtain the buffer. The API can be successful only when the firmware gets control over the DMA channel which is performed by the CyU3PDmaChannelSetSuspend() API.

Kindly, test the attached firmware with the mentioned procedure and let me know if you still have queries.

Best regards,

Srinath S

0 Likes

Hi, again! Thank`s a lot for sended example project. It`s working perfectly. But there is a difference between what you explained and what I need.


 

1) My firmware receiving data from GPIF, not from CY_FX_EP_PRODUCER_SOCKET, producer is CY_FX_GPIF_PRODUCER_SOCKET.


 

2) I have to interrupt data flow when GPIO signal on IKD_PIN is hi and resume it when IND_PIN is hi. But it is not possible to call CyU3PDmaChannelSetSuspend() from GPIO handler, as documentation says. In that case I`m using event handling by means of CyU3PEventSet() and CyU3PEventGet() functions. In GPIO handler I`m setting event, in main thread get it. It looks like this:


 

/* GPIO interrupt callback handler. This is received from

* the interrupt context. So DebugPrint API is not available

* from here. Set an event in the event group so that the

* GPIO thread can print the event information. */

void CyFxGpioIntrCb (uint8_t gpioId)

{

  if(gpioId == IKD_PIN)

  {

CyU3PEventSet(&glFxGpioAppEvent, CY_FX_IKD_EVENT, CYU3P_EVENT_OR);

  }

  if(gpioId == IND_PIN)

  {

CyU3PEventSet(&glFxGpioAppEvent, CY_FX_IND_EVENT, CYU3P_EVENT_OR);

  }

}


 

/* Entry function for the glAppThread. */

void CyFxAppThread_Entry(uint32_t input)

{

CyU3PReturnStatus_t stat;

CyU3PUsbLinkPowerMode curState;


 

  /* Initialize the debug module */

CyFxApplnDebugInit();

  CyU3PDebugPrint (1, "\n\ndebug initialized\r\n");


 

  /* Initialize the application */

  CyFxApplnInit();


 

  for (;;)

  { stat = CyU3PEventGet(&glFxGpioAppEvent,

(CY_FX_IKD_EVENT | CY_FX_IND_EVENT),

CYU3P_EVENT_OR_CLEAR, &eventFlag, CYU3P_WAIT_FOREVER);

  if (stat == CY_U3P_SUCCESS)

  {

  if (eventFlag & CY_FX_IKD_EVENT)

  {

  stat = CyU3PDmaChannelSetSuspend(&glDmaChHandle,

CY_U3P_DMA_SCK_SUSP_NONE,

CY_U3P_DMA_SCK_SUSP_CONS_PARTIAL_BUF);

if(stat != CY_U3P_SUCCESS)

continue;

CyU3PDmaBuffer_t buffer;

  stat = CyU3PDmaChannelGetBuffer(&glDmaChHandle, &buffer, CYU3P_NO_WAIT);

if(stat != CY_U3P_SUCCESS)

continue;

  }

  if (eventFlag & CY_FX_IND_EVENT)

  {

stat = CyU3PDmaChannelSetSuspend(&glDmaChHandle,

CY_U3P_DMA_SCK_SUSP_NONE,

CY_U3P_DMA_SCK_SUSP_NONE);

if(stat != CY_U3P_SUCCESS)

continue;

  stat = CyU3PDmaChannelResume(&glDmaChHandle, CyTrue, CyTrue);

if(stat != CY_U3P_SUCCESS)

continue;

  }

  }

  }

}


 

The call to CyU3PDmaChannelSetSuspend(&glDmaChHandle, CY_U3P_DMA_SCK_SUSP_NONE, CY_U3P_DMA_SCK_SUSP_CONS_PARTIAL_BUF) is successfull, but next call to CyU3PDmaChannelGetBuffer(&glDmaChHandle, &buffer, CYU3P_NO_WAIT) returning error code CY_U3P_ERROR_INVALID_SEQUENCE. In your example that functions calls handling by different messages. May be that situaion should be solved by means of GPIF designer. So, I need to know what you are thinking about that.

Thank you in advance!

0 Likes

Hello,

CyU3PDmaChannelGetBuffer() API can be called only when the socket has been suspended. In your case, since you have set the suspend type as CY_U3P_DMA_SCK_SUSP_CONS_PARTIAL_BUF, the socket is actually not suspended immediately after the API is called rather it gets suspended only on the reception of the next partial buffer. So, the CyU3PDmaChannelGetBuffer() API will fail since the channel is not suspended. Kindly, ensure that the CyU3PDmaChannelGetBuffer() API is called only after the socket is actually suspended.

Best regards,

Srinath S

0 Likes