i2c writes using cyusb_linux

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

cross mob
Anonymous
Not applicable

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?

0 Likes
1 Solution
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

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 = 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 = 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 = 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

Hemanth

View solution in original post

0 Likes
2 Replies
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

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

Hemanth
0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

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 = 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 = 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 = 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

Hemanth
0 Likes