2 Replies Latest reply on May 14, 2018 11:01 PM by hman

    i2c writes using cyusb_linux

    priyanob

      Hi,

       

      I am using CX3 and cyusb_linux in Linux for flashing. In my setup, I have additional I2C EEPROMs. Can I modify the source code of cyusb_linux Qt source base and write my own function which performs I2C flash write to my I2C EEPROMs? My EEPROM will have different slave addresses and I need to write to different memory locations in it.

       

      If so, please help me what to do with the function 'i2c_write' in file fx3_download.cpp?

        • 1. Re: i2c writes using cyusb_linux
          hman

          Hi,

           

          The FX3 bootloader checks for the EEPROM with address 0xA0 (that is: the slave device selection address

          sent would be 0xA0 for write and 0xA1 for read)

          This can't be changed.

           

           

          You can refer to the LoadFwSection() function in the BootAppGcc example found in the following path:

          C:\Program Files (x86)\Cypress\EZ-USB FX3 SDK\1.3\firmware\boot_fw\src (provided you have installed FX3 SDK)

           

           

          The above function will tell you how the firmware is loaded from the I2C EEPROM during FX3 Boot.

           

           

          How the firmware is loaded into EEPROM when programmed from control center in Windows:

          - The control center loads CyBootProgrammer.img into FX3 first which is capable of writing to EEPROM.

          - You can find the source of this image in the following example:

          C:\Program Files (x86)\Cypress\EZ-USB FX3 SDK\1.3\firmware\basic_examples\cyfxflashprog

          - In this firmware refer to CY_FX_RQT_I2C_EEPROM_WRITE vendor command.

          This vendor command handles the writes to the EEPROM.

           

           

          Now in the cyusb_linux application, in the i2c_write() function you can see that the following control transfer is made:

          cyusb_control_transfer(h, 0x40, 0xBA, devAddr, address, &buf[index], size, VENDORCMD_TIMEOUT);

           

           

          - Now you can relate this call in the application to the vendor command handling in the cyfxflashprog example pointed above.

           

          Regards,

          Hemanth

          • 2. Re: i2c writes using cyusb_linux
            hman

            Hi,

             

            Note: The below explanation is regarding how the different number of EEPROMs connected to FX3 can get programmed

            with firmware.

             

            If the below explanation is not clear then please post your EEPROM size and which manufacturer, for us to explain with that particular case.

             

            1. The default Bootloader initially looks for the EEPROM with slave address 0xA0 for

            the firmware. This can't be changed.

            2. The image(which may be part of the entire firmware) contains in it's second byte about

            the information of what kind of EEPROM is connected.

            The types of EEPROM are listed in the Boot format section of FX3 Programmer's Manual.

            3. Once the firmware in the first EEPROM (with address 0xA0) is read by the bootloader, it

            should address the next EEPROM if required which is there on the I2C bus.

            4. The addressing of the next EEPROM is same for many EEPROMs except one version of Microchip

            EEPROMs.

             

             

            How the firmware is programmed into different EEPROMs connected to FX3 on I2C Bus:

             

             

            Please find the below snippet of 'Control Center' windows C# application which has capability

            to program the EEPROMs:

             

            -------------------------------------------------------------------------------------------------------------------------------------------------

            unsafe internal FX3_FWDWNLOAD_ERROR_CODE DownloadUserIMGtoI2CE2PROM(ref byte[] buf, ref uint buflen)

                    {

                        int STAGE_SIZE = CyConst.CONTROLTFRER_DATA_LENGTH;                             

                        byte[] downloadbuf = new byte[STAGE_SIZE];

                        int NoOfStage = ((int)buflen / STAGE_SIZE);

                        int LastStage = ((int)buflen % STAGE_SIZE);

                        uint DownloadAddress = 0;

                        int FwImagePtr = 0;

                        int StageSize = STAGE_SIZE;           

                        int maxpkt = ControlEndPt.MaxPktSize;

                        //Get the I2C addressing size

                        byte ImgI2CSizeByte = buf[2]; // the 2nd byte of the IMG file will tell us the I2EPROM internal addressing.                        

                        uint AddresingStageSize = 0;

                        ImgI2CSizeByte = (byte)((ImgI2CSizeByte >> 1) & 0x07); // Bit3:1 represent the addressing           

                        bool IsMicroShipE2Prom = false;

             

             

                        switch (ImgI2CSizeByte)

                        {

                            case 0:

                            case 1:

                                return FX3_FWDWNLOAD_ERROR_CODE.I2CE2PROM_UNKNOWN_I2C_SIZE;

                            case 2:

                                AddresingStageSize = (4 * 1024); // 4KByte

                                break;

                            case 3:

                                AddresingStageSize = (8 * 1024); // 8KByte

                                break;

                            case 4:

                                AddresingStageSize = (16 * 1024); // 16KByte

                                break;

                            case 5:

                                AddresingStageSize = (32 * 1024); // 32KByte

                                break;

                            case 6:

                                AddresingStageSize = (64 * 1024); // 64KByte

                                break;

                            case 7:

                                IsMicroShipE2Prom = true; // 128KByte Addressing for Microchip.

                                AddresingStageSize = (64 * 1024); // 64KByte // case 7 represent 128Kbyte but it follow 64Kbyte addressing

                                break;               

                            default:

                                return FX3_FWDWNLOAD_ERROR_CODE.I2CE2PROM_UNKNOWN_I2C_SIZE;

                        }

             

             

                        ControlEndPt.TimeOut = 5000;

                        ControlEndPt.Target = CyConst.TGT_DEVICE;

                        ControlEndPt.ReqType = CyConst.REQ_VENDOR;

                        ControlEndPt.Direction = CyConst.DIR_TO_DEVICE;

                        ControlEndPt.ReqCode = 0xBA;

                        ControlEndPt.Value = (ushort)(DownloadAddress & 0x0000FFFF); // Get 16-bit LSB

                        ControlEndPt.Index = (ushort)(DownloadAddress >> 16);        // Get 16-bit MSB           

             

             

                        for (uint i = 0; i < NoOfStage; i++)

                        {

                            //Copy data from main buffer to tmp buffer

                            for (uint j = 0; j < STAGE_SIZE; j++)

                                downloadbuf[j] = buf[FwImagePtr + j];

             

             

                            if (!ControlEndPt.XferData(ref downloadbuf, ref StageSize))

                            {

             

             

                                return FX3_FWDWNLOAD_ERROR_CODE.FAILED;

                            }

             

             

                            ControlEndPt.Index += (ushort)StageSize; //Starting address  withing I2C chunk size(for I2C size :32Kbyte the Index will go like 0,4,8,12,16 etc..)

                            FwImagePtr += STAGE_SIZE; //post transfer increament of buffer pointer

             

             

                            // Address calculation done in the below box

                            if (IsMicroShipE2Prom)

                            {//Microchip Addressing(0-(1-64),4(64 to 128),1(128 to 192 ),5(192 to 256))

                                if (FwImagePtr >= (128 * 1024))

                                {

                                    if ((FwImagePtr % AddresingStageSize) == 0)

                                    {

                                        if (ControlEndPt.Value == 0x04)

                                            ControlEndPt.Value = 0x01;

                                        else

                                            ControlEndPt.Value = 0x05;

             

             

                                        ControlEndPt.Index = 0;

                                    }

                                }

                                else if ((FwImagePtr % AddresingStageSize) == 0)

                                {                     

                                    ControlEndPt.Value = 0x04;

                                    ControlEndPt.Index = 0;

                                }

                            }

                            else

                            {//ATMEL addressing sequential

                                if ((FwImagePtr % AddresingStageSize)==0)

                                {// Increament the Value field to represent the address and reset the Index value to zero.

                                    ControlEndPt.Value += 0x01;

                                    if(ControlEndPt.Value>=8)

                                        ControlEndPt.Value = 0x0; //reset the Address to ZERO

             

             

                                    ControlEndPt.Index = 0;

                                }

                            }              

                        }

             

             

                        if (LastStage != 0)

                        {//check for last stage

             

             

                            for (uint j = 0; j < LastStage; j++)

                                downloadbuf[j] = buf[FwImagePtr + j];

             

             

                            if ((LastStage % maxpkt) != 0)

                            {// make it multiple of max packet size

                                int diff = (maxpkt - (LastStage % maxpkt));

                                for (int j = LastStage; j < (LastStage + diff); j++)

                                    downloadbuf[j] = 0;

             

             

                                LastStage += diff;

                            }

             

             

                            if (!ControlEndPt.XferData(ref downloadbuf, ref LastStage))

                            {

                                return FX3_FWDWNLOAD_ERROR_CODE.FAILED;

                            }

                           /*Failure Case:

                             The device does not return failure message when file size is more than 128KByte and only one 128Byte E2PROM on the DVK.

                             Solution:

                             Read back the last stage data to confirm that all data transferred successfully.*/

                            ControlEndPt.ReqCode = 0xBB;

                            ControlEndPt.Direction = CyConst.DIR_FROM_DEVICE;

                            if (!ControlEndPt.XferData(ref downloadbuf, ref LastStage))

                            {

                                return FX3_FWDWNLOAD_ERROR_CODE.FAILED;

                            }

             

             

             

             

                        }

                        return FX3_FWDWNLOAD_ERROR_CODE.SUCCESS;

                    }

            --------------------------------------------------------------------------------------------------------------------------------------------

             

            5. The above code along with the previous comment can be referred to understand how the EEPROMs gets programmed by the Host Application.

             

             

            The special case of Microchip addressing is discussed below:

             

             

            - As can be seen from the above code,

            a. Addressing scheme can be known by reading the second byte of the image. In the above code the variable ImgI2CSizeByte tells that.

            b. For example if you are using Microchip 128KB EEPROM (24AA1025/24LC1025/24FC1025) then the first 1-64 KB of the first EEPROM on the bus

            is addressed by 0xA0

            c. Then the second half (64-128)KB of the first EEPROM is addressed by 0xA4

            (Refer this comment in the above code: //Microchip Addressing(0-(1-64),4(64 to 128),1(128 to 192 ),5(192 to 256)))

            d. Similarly the first part of second EEPROM is addressed by 0xA1 and second half by 0xA5

             

             

            Also please refer to below link for 24LC1025 part datasheet to get clear idea on addressing of the EEPROM:

            http://ww1.microchip.com/downloads/en/DeviceDoc/21941E.pdf

             

            Note: When multiple EEPROMs are used the A2, A1, A0, B0 pins whichever applicable to the EEPROM being used needs to be correctly pulled high/low for it to get properly addressed.

             

            Regards,

            Hemanth