How to recompile libcyu3lpp.a?

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

cross mob
dilic_2635671
Level 4
Level 4

Hi,

I am looking to have CyU3PSpiTransmitWords() and CyU3PSpiReceiveWords() in same SS low/high period. Is there any existing function doing that? Or how can I re-compile the libcyu3lpp source?

Thanks,

Dick

0 Likes
1 Solution
dilic_2635671
Level 4
Level 4

'I just have it working now. The only code need to change is the if statement to "if (i == 0)"

View solution in original post

0 Likes
10 Replies
lock attach
Attachments are accessible only for community members.
KandlaguntaR_36
Moderator
Moderator
Moderator
25 solutions authored 10 solutions authored 5 solutions authored
We have added a new API to handle both Transmit and Receive in one API in the attached modified library.

Please replace the libcyu3lpp.a in the Cypress\EZ-USB FX3 SDK\1.3\fw_lib\1_3_3\fx3_release Folder with the attached libcyu3lpp.a.

The API is, CyU3PSpiTransferWords ( uint8_t *txBuf, uint32_t txByteCount, uint8_t *rxBuf, uint32_t rxByteCount) 

Here, txBuf and rxBuf are Source data pointers. These need to be padded to nearest byte if the word length is not byte aligned.  txByteCount, rxByteCount need to be a multiple of the word length aligned to the next byte

Please use this API with modified library.
Note that this API will be added in the next release of SDK 1.3.4 .

How to Recompile the libcyu3lpp.a?

Import the lpp_source project (default SDK path: C:\Program Files (x86)\Cypress\EZ-USB FX3 SDK\1.3\firmware\lpp_source) into Eclipse.

And do modifications required in the .c files (spi or i2c ). Then Build using release mode or debug mode.

You can see that the libcyu3lpp.a is built.

Replace the older libcyu3lpp.a file with newly built file in the following path: Cypress\EZ-USB FX3 SDK\1.3\fw_lib\1_3_3\fx3_release Folder with the attached libcyu3lpp.a, if you do release build.

Source of the CyU3PSpiTransferWords SPI is here

/* Function to do combined read/writes in register mode. */

CyU3PReturnStatus_t

CyU3PSpiTransferWords (

  uint8_t *txBuf,

  uint32_t txByteCount,

  uint8_t *rxBuf,

  uint32_t rxByteCount)

{

  CyU3PReturnStatus_t status;

  uint32_t byteCount, i;

  uint32_t temp, intrMask;

  uint32_t timeout;

  uint8_t wordLen;

  if (!glIsSpiConfigured)

  {

  return CY_U3P_ERROR_NOT_CONFIGURED;

  }

  if (((txBuf == 0) && (rxBuf == 0)) || ((txByteCount == 0) && (rxByteCount == 0)))

  {

  return CY_U3P_SUCCESS;

  }

  if (((txByteCount != 0) && (txBuf == 0)) || ((rxByteCount != 0) && (rxBuf == 0)))

  {

  return CY_U3P_ERROR_NULL_POINTER;

  }

  status = CyU3PSpiGetLock ();

  if (status != CY_U3P_SUCCESS)

  {

  return status;

  }

  /* Maximum number of words to transfer. */

  byteCount = CY_U3P_MAX (txByteCount, rxByteCount);

  /* Get the wordLen from the config register and convert it to byte length. */

  temp = SPI->lpp_spi_config;

  wordLen = ((temp & CY_U3P_LPP_SPI_WL_MASK) >> CY_U3P_LPP_SPI_WL_POS);

  if ((wordLen & 0x07) != 0)

  {

  wordLen = (wordLen >> 3) + 1;

  }

  else

  {

  wordLen = (wordLen >> 3);

  }

  /* We can only transfer data in multiples of the word length. */

  if (((txByteCount % wordLen) != 0) || ((rxByteCount % wordLen) != 0))

  {

  status = CY_U3P_ERROR_BAD_ARGUMENT;

  }

  /* Check if the DMA mode is running. */

  if ((temp & (CY_U3P_LPP_SPI_DMA_MODE | CY_U3P_LPP_SPI_ENABLE)) == (CY_U3P_LPP_SPI_DMA_MODE | CY_U3P_LPP_SPI_ENABLE))

  {

  status = CY_U3P_ERROR_ALREADY_STARTED;

  }

  if (status != CY_U3P_SUCCESS)

  {

  CyU3PSpiReleaseLock();

  return status;

  }

  CyU3PSpiResetFifo (CyTrue, CyTrue);

  /* Disable interrupts. */

  intrMask = SPI->lpp_spi_intr_mask;

  SPI->lpp_spi_intr_mask = 0;

  /* Enable the TX and RX bits. */

  if (rxByteCount != 0)

  SPI->lpp_spi_config |= CY_U3P_LPP_SPI_TX_ENABLE | CY_U3P_LPP_SPI_RX_ENABLE;

  else

  SPI->lpp_spi_config |= CY_U3P_LPP_SPI_TX_ENABLE;

  /* Re-enable SPI block. */

  SPI->lpp_spi_config |= CY_U3P_LPP_SPI_ENABLE;

  timeout = CY_U3P_MAX (glSpiWriteTimeout, glSpiReadTimeout);

  /* As in the ReceiveWords case, we transmit two data words before starting to look for RX_DATA. */

  for (i = 0; i <= byteCount; i += wordLen)

  {

  if (i < byteCount)

  {

  /* Form the data value to be transferred out. While the txByteCount has not run out, take data

  from the buffer. After that, transmit 0's.

  */

  temp = 0;

  if (i < txByteCount)

  {

  switch (wordLen)

  {

  case 4:

  temp |= (txBuf[i + 3] << 24);

  case 3:

  temp |= (txBuf[i + 2] << 16);

  case 2:

  temp |= (txBuf[i + 1] << 8);

  default:

  temp |= txBuf;

  break;

  }

  }

  SPI->lpp_spi_egress_data = temp;

  }

  /* On the first iteration, wait for TX_SPACE only. From then on, wait for RX_DATA and TX_SPACE. */

/* THIS IF CONDITION IS CORRECTED AS  milkfish1227_2635671 POINTED OUT */

  if (i == 0)

  temp = CY_U3P_LPP_SPI_TX_SPACE;

  else

  temp = CY_U3P_LPP_SPI_TX_SPACE | CY_U3P_LPP_SPI_RX_DATA;

  while ((SPI->lpp_spi_status & temp) != temp)

  {

  if (timeout-- == 0)

  {

  status = CY_U3P_ERROR_TIMEOUT;

  break;

  }

  }

  if (status != CY_U3P_SUCCESS)

  {

  break;

  }

  /* If receive is not complete, wait for the RX_DATA interrupt and read the data. */

  if ((i > 0) && (i <= rxByteCount))

  {

  temp = SPI->lpp_spi_ingress_data;

  switch (wordLen)

  {

  case 4:

  rxBuf[i + 3 - wordLen] = (uint8_t)((temp >> 24) & 0xFF);

  case 3:

  rxBuf[i + 2 - wordLen] = (uint8_t)((temp >> 16) & 0xFF);

  case 2:

  rxBuf[i + 1 - wordLen] = (uint8_t)((temp >> 😎 & 0xFF);

  default:

  rxBuf[i - wordLen] = (uint8_t)(temp & 0xFF);

  break;

  }

  }

  }

  /* There is no need to wait for TX_DONE as we are waiting for RX_DATA in all loop iterations. */

  /* Disable the TX and RX. */

  SPI->lpp_spi_config &= ~(CY_U3P_LPP_SPI_TX_ENABLE | CY_U3P_LPP_SPI_RX_ENABLE);

  /* Clear all interrupts and restore interrupt mask. */

  SPI->lpp_spi_intr |= CY_U3P_LPP_SPI_TX_DONE | CY_U3P_LPP_SPI_RX_DATA;

  SPI->lpp_spi_intr_mask = intrMask;

  /* Wait until the SPI block is no longer busy and disable. */

  while ((SPI->lpp_spi_status & CY_U3P_LPP_SPI_BUSY) != 0);

  SPI->lpp_spi_config &= ~CY_U3P_LPP_SPI_ENABLE;

  CyU3PSpiReleaseLock ();

  return status;

}

Regards,

Sridhar

0 Likes
dilic_2635671
Level 4
Level 4

Thank you so much. I do have DMA mode working which use CyU3PSpiSetBlockXfer() API.

0 Likes
dilic_2635671
Level 4
Level 4

How about the host app? Currently control point API can use either Read or Write. We need a function can Write/Read at same time.

In your example code, Write have no way to get the SPI response. Read can't have much data other than Value and Index. We need to Write 4 bytes address and data and able to get response from SPI.

Thanks,

Dick

0 Likes
dilic_2635671
Level 4
Level 4

Hi,

The new CyU3PSpiTransferWords() function doesn't seems to work. At least in my case, I don't see the data out in the FPGA waveform.

I am sending 4 0 0 0 1 1 1 1 to SPI.

Not sure what's going on. I can't post .png file to this post, but from the waveform the "1 1 1 1" is missing.

I haven't really looking the code yet.

Any thoughts what might be wrong?

I think I need go back to use reg mode instead of DMA due to the limit of DMA TX/RX size at least 32. I need to be able to send single byte.

Any way to post .png file?

     CyU3PSpiSetSsnLine (CyFalse);

    status = CyU3PSpiTransmitWords (txBuf, byteCount);

    CyU3PSpiSetSsnLine (CyTrue);

    CyU3PSpiSetSsnLine (CyFalse);

    status = CyU3PSpiTransferWords (txBuf, byteCount, rxBuf, byteCount);

    CyU3PSpiSetSsnLine (CyTrue);

0 Likes
dilic_2635671
Level 4
Level 4

The other question I have is - how come there is no break in switch case?

                switch (wordLen)

                {

                case 4:

                    temp |= (txBuf[i + 3] << 24);

                case 3:

                    temp |= (txBuf[i + 2] << 16);

                case 2:

                    temp |= (txBuf[i + 1] << 8);

                default:

                    temp |= txBuf;

                    break;

                }

0 Likes
dilic_2635671
Level 4
Level 4

Never mind, I guess it's in the comments - Do fallthrough switch instead of a loop

0 Likes
dilic_2635671
Level 4
Level 4

Correction - I am sending 4 0 0 0 1 1 1 1 to SPI. Only 4 goes out. Might be something wrong in the loop.

0 Likes
dilic_2635671
Level 4
Level 4

I am able to get the Write waveform correctly after modify the code in following. Oiginal code doesn't even match to the coomments.

Original code is "if (i > 0).

So I am kind of wondering if there is any testing running against this new code?

        /* On the first iteration, wait for TX_SPACE only. From then on, wait for RX_DATA and TX_SPACE. */

// mlin

        if (i == 0)

            temp = CY_U3P_LPP_SPI_TX_SPACE;

        else

            temp = CY_U3P_LPP_SPI_TX_SPACE | CY_U3P_LPP_SPI_RX_DATA;

0 Likes
dilic_2635671
Level 4
Level 4

'I just have it working now. The only code need to change is the if statement to "if (i == 0)"

0 Likes

Yes, you are correct milkfish1227_2635671​. I have modified the IF condition to if (i==0).

Regards,

Sridhar

0 Likes