8 Replies Latest reply on May 4, 2020 12:48 AM by JayakrishnaT_76

    Fx3BootAppGcc bootFromSpi()

    lopo_1264666

      I imported this project from "C:\Program Files (x86)\Cypress\EZ-USB FX3 SDK\1.3\Eclipse\templates\fx3templates".

      I2C_BOOT is pretty straightforward and I'm a bit confused about SPI_BOOT.

       

      In bootFromSpi():

      (1) Why we need this line of code? It looks like external memory address page boundary alignment but I'm not so sure. Even if this is the case, I thought only write to SPI memory needs page boundary alignment but not for read command.

           bytesToTransfer = bytesToTransfer - (spiAddress % SPI_DMA_XFER_SIZE);

       

      (2) I2C_BOOT didn't check if downloadAddress < CY_FX3_BOOT_ITCM_END but SPI_BOOT did. May I know what is the purpose?

      if "(downloadAddress + bytesToTransfer) < CY_FX3_BOOT_ITCM_END", DMA read transfer below will copy data from SPI slave to SPI_DMA_BUF_ADDRESS first before copy over to ITCM. in the else{} statement below, will DMA read transfer overwrite "downloadAddress" straight?

       

       

                  /* Validate ITCM Memory */

                  if ((downloadAddress + bytesToTransfer) < CY_FX3_BOOT_ITCM_END)

                  {

                      /* Set up the SPI DMA transfer to System Memory */

                      status = CyFx3BootSpiDmaXferData (CyTrue, SPI_DMA_BUF_ADDRESS, SPI_DMA_XFER_SIZE, 100);

                  }

                  else

                  {

                      /* Set up the SPI DMA transfer to System Memory */

                      status = CyFx3BootSpiDmaXferData (CyTrue, downloadAddress, SPI_DMA_XFER_SIZE, 100);

                  }

       

                  /* Validate ITCM Memory */

                  if ((downloadAddress + bytesToTransfer) < CY_FX3_BOOT_ITCM_END)

                  {

                      CyFx3BootMemCopy ((uint8_t*)downloadAddress, (uint8_t *)SPI_DMA_BUF_ADDRESS, bytesToTransfer);

                  }

        • 1. Re: Fx3BootAppGcc bootFromSpi()
          JayakrishnaT_76

          Hello,

           

          Please find my comments to your question 2 in the previous response:

          The function CyFx3BootSpiDmaXferData  uses DMA mode of data transfer. This function will store the data into the address that is passed as the second parameter. Also, it is not possible to use the memory region in the ITCM region as a target for DMA transfers. Hence, the transferred data is stored into a dummy address and later on copied to the downloadAddress using CyFx3BootMemCopy.

          Now, the elseif{} statement will write the data obtained directly into downloadAddress. This is possible as this memory region is outside ITCM region. Hence this memory region can be used as a target for DMA transfers.

          This implementation is different from I2C boot option. In I2C boot option, we make use of the API CyFx3BootI2cReceiveBytes which makes use of register mode (Non DMA mode) of data transfer. This API returns a pointer of the buffer where data is placed. This pointer is used for copying the buffer contents to the corresponding secAddress.

           

          Best Regards,

          Jayakrishna

          • 2. Re: Fx3BootAppGcc bootFromSpi()
            lopo_1264666

            I too found out that SPI boot has extra lines for CyFx3BootJumpToProgramEntry as compared to I2C boot. Do we need to add this to I2C boot?

            • 3. Re: Fx3BootAppGcc bootFromSpi()
              lopo_1264666

              I found CyFx3BootJumpToProgramEntry in I2C.

              • 4. Re: Fx3BootAppGcc bootFromSpi()
                lopo_1264666

                I found the answer for this too:

                            if ((tmp + gI2cByteAddr) > I2C_SLAVE_SPACE)

                                tmp = I2C_SLAVE_SPACE - gI2cByteAddr;

                • 5. Re: Fx3BootAppGcc bootFromSpi()
                  lopo_1264666

                  Still waiting for your reply on :

                  bytesToTransfer = bytesToTransfer - (spiAddress % SPI_DMA_XFER_SIZE);

                  • 6. Re: Fx3BootAppGcc bootFromSpi()
                    lopo_1264666

                    According to your comments for Q2, I think the else{} statement below should change to status = CyFx3BootSpiDmaXferData (CyTrue, downloadAddress, bytesToTransfer, 100) since it writes directly to the system RAM?

                     

                                /* Invoke the SPI function to do the DMA transfer */

                                CyFx3BootSpiSetBlockXfer (0, SPI_DMA_XFER_SIZE);

                     

                                /* Validate ITCM Memory */

                                if ((downloadAddress + bytesToTransfer) < CY_FX3_BOOT_ITCM_END)

                                {

                                    /* Set up the SPI DMA transfer to System Memory */

                                    status = CyFx3BootSpiDmaXferData (CyTrue, SPI_DMA_BUF_ADDRESS, SPI_DMA_XFER_SIZE, 100);

                                }

                                else

                                {

                                    /* Set up the SPI DMA transfer to System Memory */

                                    status = CyFx3BootSpiDmaXferData (CyTrue, downloadAddress, SPI_DMA_XFER_SIZE, 100);

                                }

                    • 7. Re: Fx3BootAppGcc bootFromSpi()
                      JayakrishnaT_76

                      Hello,

                       

                      When the API CyFx3BootSpiDmaXferData  is used, the length parameter can be set with any value. But internally, the length parameter is checked to understand if it is a multiple of 16 or not. If it is a multiple of 16, then the same length parameter is used. Otherwise, the length parameter is converted to the next multiple of 16. Due to this, SPI_DMA_XFER_SIZE (64 bytes) is used as the length parameter for the API CyFx3BootSpiDmaXferData.

                      Even though SPI_DMA_XFER_SIZE is used as length parameter for the API CyFx3BootSpiDmaXferData, the downloadAddress and spiAddress variables are incremented by bytesToTransfer only. So, upon next iteration of the loop, a few bytes (equal to SPI_DMA_XFER_SIZE - bytesToTransfer) will be overwritten from downloadAddress. Hence the result is same as using bytestoTransfer as length for the API CyFx3BootSpiDmaXferData.

                      Please let me know if you have any queries on this. In the meanwhile, I will get back to you with my comments for the question asked in your response 5.

                       

                      Best Regards,

                      Jayakrishna

                      • 8. Re: Fx3BootAppGcc bootFromSpi()
                        JayakrishnaT_76

                        EDITTED FOR BETTER CLARITY

                         

                        Hello,

                         

                        The following statement:

                         

                        bytesToTransfer = bytesToTransfer - (spiAddress % SPI_DMA_XFER_SIZE);

                         

                        is used for making spiAddress a multiple of 64. The page size of the flash used is 256 Bytes. So initially, the spiAddress will be 12. On executing the above instruction, bytesToTransfer is changed to 52. Now after completing first iteration, spiAddress is incremented by 52. This makes spiAddress 64. From this point, bytesToTransfer will remain as 64 itself. So, spiAddress will be incremented in steps of 64 from here. As 64 is a multiple of 256, it ensures that read does not take place from 2 different pages.

                         

                        Regarding question 2 in the original query,

                        The function CyFx3BootSpiDmaXferData  uses DMA mode of data transfer. This function will store the data into the address that is passed as the second parameter. Also, it is not possible to use the memory region in the ITCM region as a target for DMA transfers. Hence, the transferred data is stored into a dummy address and later on copied to the downloadAddress using CyFx3BootMemCopy.

                        Now, the elseif{} statement will write the data obtained directly into downloadAddress. This is possible as this memory region is outside ITCM region. Hence this memory region can be used as a target for DMA transfers.

                        This implementation is different from I2C boot option. In I2C boot option, we make use of the API CyFx3BootI2cReceiveBytes which makes use of register mode (Non DMA mode) of data transfer. This API returns a pointer of the buffer where data is placed. This pointer is used for copying the buffer contents to the corresponding secAddress.

                         

                         

                        Best Regards,

                        Jayakrishna