cancel
Showing results for 
Search instead for 
Did you mean: 

USB Superspeed Peripherals

New Contributor II

Hi everyone,

I'm developing an application based on the MSC example for the FX3S. In some cases, I need to manually read/write data to the storage.

This is the DMA configuration:

CyU3PDmaChannelConfig_t dmaConfig;

dmaConfig.size = 512;

dmaConfig.count = CY_FX_MSC_DMA_BUF_COUNT;

dmaConfig.prodSckId = (CyU3PDmaSocketId_t) (CY_U3P_UIB_SOCKET_PROD_0 | CY_FX_MSC_EP_BULK_OUT_SOCKET);

dmaConfig.consSckId = CY_U3P_SIB_SOCKET_0;

dmaConfig.dmaMode = CY_U3P_DMA_MODE_BYTE;

dmaConfig.notification = CY_U3P_DMA_CB_RECV_CPLT | CY_U3P_DMA_CB_SEND_CPLT | CY_U3P_DMA_CB_PROD_EVENT | CY_U3P_DMA_CB_CONS_EVENT;

dmaConfig.cb = UsbStorage_DmaStorageWriteCb;

dmaConfig.prodHeader = 0;

dmaConfig.prodFooter = 0;

dmaConfig.consHeader = 0;

dmaConfig.prodAvailCount = 0;

status = CyU3PDmaChannelCreate(&glChHandleMscOut, CY_U3P_DMA_TYPE_MANUAL, &dmaConfig);

dmaConfig.prodSckId = CY_U3P_SIB_SOCKET_1;

dmaConfig.consSckId = (CyU3PDmaSocketId_t) (CY_U3P_UIB_SOCKET_CONS_0 | CY_FX_MSC_EP_BULK_IN_SOCKET);

dmaConfig.notification = CY_U3P_DMA_CB_RECV_CPLT | CY_U3P_DMA_CB_SEND_CPLT | CY_U3P_DMA_CB_PROD_EVENT | CY_U3P_DMA_CB_CONS_EVENT;

dmaConfig.cb = UsbStorage_DmaStorageReadCb;

status = CyU3PDmaChannelCreate(&glChHandleMscIn, CY_U3P_DMA_TYPE_MANUAL, &dmaConfig);

I am using the following command sequence to initiate a read/write request. (Each return status check here is omitted for brevity: every call returns SUCCESS until WaitForCompletion).

// Prepare the DMA Buffer

CyU3PDmaBuffer_t dmaBuf;

dmaBuf.buffer = buf;

dmaBuf.status = 0;

dmaBuf.size = (len + 15) & 0xFFF0; // Round up to a multiple of 16.

dmaBuf.count = len;

CyU3PDmaChannel *handle = (isRead) ? &glChHandleMscIn : &glChHandleMscOut;

if(isRead)

    CyU3PDmaChannelSetupRecvBuffer(handle, &dmaBuf);

else

    CyU3PDmaChannelSetupSendBuffer(handle, &dmaBuf);

CyU3PSibReadWriteRequest(isRead, ((lun >= CY_FX_SIB_PARTITIONS) ? 1 : 0), glLunUnit[lun], len / CY_FX_SIB_MAX_BLOCK_SIZE, startAddr, 1);

ret = CyU3PDmaChannelWaitForCompletion(handle, CYU3P_WAIT_FOREVER); // ret == "ABORTED" when trying to write!

Reads are successful. When trying to WRITE, the DmaStorageWriteCb callback is not called and the WaitForCompletion function returns ABORTED.

I've checked the docs and the forums and couldn't find an answer. Can you help me?

Thanks,
Salvatore

0 Likes
Reply
1 Solution
New Contributor II

Hello everyone,

I've solved it. I've added a check before the CyU3PDmaChannelSetupRecvBuffer()/CyU3PDmaChannelSetupSendBuffer() calls:

CyU3PDmaState_t state; uint32_t prodCount, consCount;

CyU3PDmaChannelGetStatus(handle, &state, &prodCount, &consCount);

while(state != CY_U3P_DMA_CONFIGURED && state != CY_U3P_DMA_RECV_COMPLETED && state != CY_U3P_DMA_SEND_COMPLETED)

{

    CyU3PThreadSleep(10);

    CyU3PDmaChannelGetStatus(handle, &state, &prodCount, &consCount);

}

Thanks for the help.

Regards,
Salvatore.

View solution in original post

0 Likes
Reply
3 Replies
Moderator
Moderator

Hello Salvatore,

The CyU3PDmaChannelWaitForCompletion() API returns CY_U3P_ERROR_ABORTED in these cases:

1.) /* Wait for the normal transaction to complete */

2.) /* Wait for the producer socket override transaction to complete */

3.) /* Wait for the consumer socket override transaction to complete */

So, is the manual transfer only happening when the AUTO channel is not being used?

Also, for the manual channel, what is the 2nd parameter passed to the CyU3PDmaChannelSetXfer() API? Is it a finite value or set to 0?

Please share your firmware so that i can review the modifications done and get a better understanding of the issue.


Regards,

Yashwant

0 Likes
Reply
New Contributor II

Hello Yashwant,

unfortunately I cannot share the firmware at the moment. The first post contains what I think to be the relevant parts. The DMA channels are created ONCE (at the startup), then never recreated again. This way, both reads and writes in AUTO mode (USB HOST <--> MMC) work correctly. Also the Read in MANUAL mode work.

Yes the manual transfer is being used when no other request is being made by the Host. No other API is invoked before/after the second function.
I've currently setup a Timer that sets a event flag which is waited upon in the HandleMSCTask() thread. So this function is called in the HandleMSCTask() thread.


As indicated by the documentation, CyU3PDmaChannelSetXfer() must not be called when using CyU3PDmaChannelSetupSendBuffer() / CyU3PDmaChannelSetupRecvBuffer() so I did not call it.


Regards,
Salvatore

0 Likes
Reply
New Contributor II

Hello everyone,

I've solved it. I've added a check before the CyU3PDmaChannelSetupRecvBuffer()/CyU3PDmaChannelSetupSendBuffer() calls:

CyU3PDmaState_t state; uint32_t prodCount, consCount;

CyU3PDmaChannelGetStatus(handle, &state, &prodCount, &consCount);

while(state != CY_U3P_DMA_CONFIGURED && state != CY_U3P_DMA_RECV_COMPLETED && state != CY_U3P_DMA_SEND_COMPLETED)

{

    CyU3PThreadSleep(10);

    CyU3PDmaChannelGetStatus(handle, &state, &prodCount, &consCount);

}

Thanks for the help.

Regards,
Salvatore.

View solution in original post

0 Likes
Reply