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

USB superspeed peripherals Forum Discussions

mialc_1106291
Level 4
Level 4
10 questions asked 50 sign-ins 50 replies posted

Hi,

I'm using Cypress FX3 SDK 1.3.5 and have a question regarding CyU3PDmaChannelSetXfer. Can CyU3PDmaChannelSetXfer be used to initiate a transfer whose size is smaller than the size of the buffer allocated to the auto DMA channel? I'm using an auto DMA channel to transfer data between CY_U3P_LPP_SOCKET_SPI_PROD and CY_U3P_PIB_SOCKET_3. To do this I perofrm the following steps:

1. Configure IO matrix for 16-bit GPIF with Hardware SPI enabled
2. Configure SPI peripheral
3. Configure GPIF peripheral, load state machine, and advance to start state
4. Create DMA channel:
size = 16384
count = 1;
prodSckId = CY_U3P_LPP_SOCKET_SPI_PROD;
consSckId = CY_U3P_PIB_SOCKET_3;
dmaMode = CY_U3P_DMA_MODE_BYTE;
notification = 0;
cb = NULL;
5. determine size of FPGA configuration file stored in flash by reading 32-bit value from flash using a combination of CyU3PSpiTransmitWords and CyU3PSpiReceiveWords (e.g. non-DMA transfers).
6. enter loop where I do the following
a. lock mutex to claim ownership of SPI channel
b. calculate transfer size based on the maximum size (16384 bytes) and the amount of data remaining in the FPGA config file
c. Set chip select low and use CyU3PSpiTransmitWords to send the read address to the flash
d. Tell SPI peripheral to use DMA mode: CyU3PSpiSetBlockXfer(0, cbTrans) where cbTrans is 16384 bytes until the last transfer because the FPGA configuration file is not a multiple of 16384
e. initiate the DMA transfer: CyU3PDmaChannelSetXfer(&dmachFpgaCfg, cbTrans)
f. wait 500 ms for the transfer to complete (it should take less than 100ms with the SPI and GPIF configuration in use): CyU3PDmaChannelWaitForCompletion(&dmachFpgaCfg, 500);
g. tell SPI peripheral to switch back to register mode: CyU3PSpiDisableBlockXfer(CyFalse, CyTrue);
h. bring chip select high
i. unlock mutex used to claim ownership of SPI channel
j. increment address pointer by cbTrans and decrement transfer size by cbTrans
k. check to see if cbConfig is 0 and if so exit loop
l. give other threads opportunity to execute: CyU3PThreadRelinquish()

Testing has shown that CyU3PDmaChannelWaitForCompletion will report CY_U3P_ERROR_TIMEOUT after 500 miliseconds after transfer of the last chunk is initiated. In such case, the transfer size is 15532 bytes because that's all the data that remains to transfer. After CY_U3P_ERROR_TIMEOUT is returned I call CyU3PDmaChannelGetStatus and find that the producer and consumer counts are both 0, and the status of the DMA channel is active. If I forecfully set the FPGA configuration size to be an event multiple of 16384 bytes then no timeout occurs, however FPGA configuration fails because I clock in invalid configuration data.

This seems to indicate an issue with CyU3PDmaChannelSetXfer initiating a transfer size that is less than the buffer size that was allocated for the DMA channel.

Can someone tell me what I'm doing wrong? Do I have to destroy and then re-create the DMA channel if I want to use an auto channel DMA to transfer less data than the allocated buffer size?

Now you might ask why I'm doing this in chunks instead of transferring all of the data at once. That's because I need to allow another thread to access the SPI flash for reading and writing other configuration data in between, as reading the FPGA configuration could take up to 4 seconds for a large image and that could cause some vendor commands to fail.

 

Thanks,
Michael

0 Likes
1 Solution
Rashi_Vatsa
Moderator
Moderator
Moderator
5 likes given 500 solutions authored 1000 replies posted

Hello Michael,

For the AUTO DMA channel (SPI > PIB), the data will be committed to the PIB block when the producer event is triggered by the producer socket. The producer event will be triggered only when the DMA buffer is full or forceful socket wrap up is done from the firmware using CyU3PDmaChannelSetWrapUp API.

Please call CyU3PDmaChannelSetWrapUp commit the partially filled buffer to PIB block. Setting the second parameter of CyU3PDmaChannelSetXfer will revert the channel to idle state when the specified amount of data is transferred.

Some of the solutions can be -

- cbTrans can be used to understand how many DMA buffers will be used to transfer the amount of data.

- No. of DMA buffers received from SPI can be tracked using producer events for AUTO_SIGNAL channel

- When cbTrans/DMA buffer size -1 buffers are received call CyU3PDmaChannelSetWrapUp 

or

Register for SPI events and when the total amount of data is received by SPI (DMA transfers) then call CyU3PDmaChannelSetWrapUp i

Regards,
Rashi

View solution in original post

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

Hello Michael,

For the AUTO DMA channel (SPI > PIB), the data will be committed to the PIB block when the producer event is triggered by the producer socket. The producer event will be triggered only when the DMA buffer is full or forceful socket wrap up is done from the firmware using CyU3PDmaChannelSetWrapUp API.

Please call CyU3PDmaChannelSetWrapUp commit the partially filled buffer to PIB block. Setting the second parameter of CyU3PDmaChannelSetXfer will revert the channel to idle state when the specified amount of data is transferred.

Some of the solutions can be -

- cbTrans can be used to understand how many DMA buffers will be used to transfer the amount of data.

- No. of DMA buffers received from SPI can be tracked using producer events for AUTO_SIGNAL channel

- When cbTrans/DMA buffer size -1 buffers are received call CyU3PDmaChannelSetWrapUp 

or

Register for SPI events and when the total amount of data is received by SPI (DMA transfers) then call CyU3PDmaChannelSetWrapUp i

Regards,
Rashi
0 Likes

Hi Rashi,

Thanks for the information and the suggestions. I decided that it was easier create and destroy the DMA channel each time so that the buffer size would match the transfer size when the transfer size was less than 16384 bytes. This solved my problem without the need to figure out how many bytes were transferred each time the SPI event callback was invoked. For future reference, is the SPI event callback executed once after CyU3PSpiSetBlockXfer specified bytes have been transferred?

Thanks,
Michael

0 Likes

Hi Michael,

The second parameter of CyU3PSpiSetConfig can be passed with event callback to get the callbacks when CY_U3P_SPI_EVENT_RX_DONE/CY_U3P_SPI_EVENT_TX_DONE i.e. reception / transmission is completed

Regards,
Rashi
0 Likes

Hi Rashi,

Am I correct in assuming that the CY_U3P_SPI_EVENT_RX_DONE event will be received after cbTrans bytes have been transferred, as specified in this call CyU3PSpiSetBlockXfer(0, cbTrans)?

Thanks,
Michael

0 Likes

Hello,

Yes, if the callback is registered the events will be triggered when data is transmitted/received

Regards,
Rashi