CY7C65211A I2C Bootloader host is requesting too many bytes from PSoC5LP device?

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

cross mob
KyTr_1955226
Level 6
Level 6
250 sign-ins 10 likes given 50 solutions authored

I'm running into some strange issues with trying to develop an I2C Bootloader Host.

The problem I'm having looks at least on the surface similar to this issue I was having about a year and a half ago, so this may end up being sort of a sequel to that thread:

I2C Bootloader Error: PSoC Bootloader sending extra bytes to host?

Basically, I have an I2C Bootloader Host program built in C#, using interop services for use of cyusbserial.dll and bootl_utils.dll.

cyusbserial.dll is the one found here that fixes ACKs being too long: Reduce Delay Observed During I2C Read Operations In USB-Serial – KBA227320

bootl_utils.dll is built from the source included with PSoC Creator 4.1.  The only change I made to the bootl_utils source is described my previous thread at the top of this post. (it shouldn't have an effect on the current behavior, but who knows!)

I am interfacing with a CY7C65211A USB-Serial bridge in I2C Vendor mode.

Interfacing with the bridge appears to be no issue.  I can send my "Enter Bootloader" command to the I2C slave device and it enters the loader as instructed.

The problem comes when I try and actually bootload the PSoC5.

When I attempt to bootload, the first command to enter the bootloader looks completely fine:

bootl_enter.JPG

The problem arises with the first read, where the host keeps ACKing data well past the EoP byte (0x17).  The packet looks good, the host app just keeps reading for some reason:

bootl_read.JPG

The read then hangs on an 0xFF byte, until eventually (5 seconds later, the configured read timeout) the host finally NAKs and sends the command to exit the bootloader (0x3B):

exit.JPG

I have confirmed that this is definitely an issue with the host application.  I am able to enter the bootloader with my application, then bootload successfully using the Bootloader Host included with Creator and the I2C Bridge in the MiniProg3.  I'm just at a loss as to where this is going wrong.  In my ReadData() function on the host, it is entering with the correct size parameter.  I confirmed via debug breakpoint that length == 16, which is correct if we include the address byte.  I have no idea why it is ACKing all these extra bytes?

The error code returned from CyBtldr_Program() is the CYRET_ERR_BTLDR_MASK (0x4000) with no error code, which I suppose makes sense, as the status byte from the target is 0x00 (SUCCESS).

I have attached the Bootloader Host Application project.  Maybe someone can point something out that I'm missing?  It's not the cleanest code (I've been messing with it quite a bit), but it shouldn't be too hard to navigate hopefully.

0 Likes
1 Solution
YatheeshD_36
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hello,

I have gone through the host application. Please see my comments below:

1. Based on the register address size of the slave device, before the read transaction, an I2C write should be initiated with the starting  register address in the  CY_DATA_BUFFER.buffer field and the register address size in the CY_DATA_BUFFER.length field.  In the same write transaction the isNakBit  and isStopBit field of the CY_I2C_DATA_CONFIG should be set to false. Make sure if this sequence is followed while debugging the application.

2. Before calling the CyI2cRead, the CY_I2C_DATA_CONFIG should be configured with isNakBit = true and isStopBit = true, please check if this is properly configured while debugging and the length of the CY_DATA_BUFFER should be the actual length that is to be read from the device.

Please check if the above conditions are met. If they are proper, then you can use the try the old cyusbserial.dll and check if you are still facing the problem.

Thanks,

Yatheesh

View solution in original post

0 Likes
13 Replies
YatheeshD_36
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hello,

I have gone through the host application. Please see my comments below:

1. Based on the register address size of the slave device, before the read transaction, an I2C write should be initiated with the starting  register address in the  CY_DATA_BUFFER.buffer field and the register address size in the CY_DATA_BUFFER.length field.  In the same write transaction the isNakBit  and isStopBit field of the CY_I2C_DATA_CONFIG should be set to false. Make sure if this sequence is followed while debugging the application.

2. Before calling the CyI2cRead, the CY_I2C_DATA_CONFIG should be configured with isNakBit = true and isStopBit = true, please check if this is properly configured while debugging and the length of the CY_DATA_BUFFER should be the actual length that is to be read from the device.

Please check if the above conditions are met. If they are proper, then you can use the try the old cyusbserial.dll and check if you are still facing the problem.

Thanks,

Yatheesh

0 Likes

Yatheesh,

1. The contents and sizes of the buffer are determined by the calls from bootl_utils.  I am just providing the callback to read and write the data with a pointer to the buffer and the size as arguments.  If the data sizes or commands (registers) are incorrect, that's presumably an issue with the cypress bootload utilities library.

2. I did check the isNakBit and isStopBit fields.  While doing what you suggested (isNakBit = 1, isStopBit = 1 for the Read) seems to at least get me further along in the process (I see more transactions occur before it fails),  However for writes, setting isNakBit and isStopBit to 0 does not seem correct.  The master seems to have a problem moving on after the ACK and the subsequent read gets mangled:

wr_nak0_stop0.JPG

Compare that with setting isNakBit = 0 and isStopBit = 1 for writes, it looks as it should, and with a correct read from the PSoC5 bootloader:

Capture.JPG

With these settings, the process at least gets to the point where it issues the first 0x39 (Write Flash Row) command, but then seems to botch the reading of the response for that command:

ProgramRow.JPG

It almost looks like the PSoC isn't ready and is stretching the clock?

My current Read/Write Callback Functions:

public unsafe int ReadData(IntPtr buffer, int size)

        {

            string strdata;

            int status = 0;

            CY_RETURN_STATUS cy_stat;

            byte[] data = new byte[MaxTransferSize];

            fixed (byte* b = data)

            {

                cyReadDataBuffer.buffer = b;

                cyReadDataBuffer.length = (uint)size;

                cyI2CDataConfig.isNakBit = 1;

                cyI2CDataConfig.isStopBit = 1;

                fixed (CY_I2C_DATA_CONFIG* data_cfg = &cyI2CDataConfig)

                {

                    fixed (CY_DATA_BUFFER* dta_buff = &cyReadDataBuffer)

                    {

                        cy_stat = CyI2cRead(cyDeviceHandle, data_cfg, dta_buff, 5000);

                    }

                }

            }

            Marshal.Copy(data, 0, buffer, size);

            strdata = BitConverter.ToString(data).TrimEnd('-', '0');

            WriteLog(Color.Blue, 0, "R: " + strdata + "\r\n");

            if (cy_stat == CY_RETURN_STATUS.CY_SUCCESS)

            {

                status = ERR_SUCCESS;

            }

            else

            {

                status = ERR_READ;

                CyI2cReset(cyDeviceHandle, 0);

            }

            return status;

        }

        public unsafe int WriteData(IntPtr buffer, int size)

        {

            string strdata;

            int status = 0;

            CY_RETURN_STATUS cy_stat;

            byte[] data = new byte[MaxTransferSize];

            Marshal.Copy(buffer, data, 0, size);

            fixed (byte* b = data)

            {

                cyDataBuffer.buffer = b;

                cyDataBuffer.length = (uint)size;

                cyI2CDataConfig.isNakBit = 0;

                cyI2CDataConfig.isStopBit = 1;

                fixed (CY_I2C_DATA_CONFIG* data_cfg = &cyI2CDataConfig)

                {

                    fixed (CY_DATA_BUFFER* dta_buff = &cyDataBuffer)

                    {

                        cy_stat = CyI2cWrite(cyDeviceHandle, data_cfg, dta_buff, 5000);

                    }

                }

            }

            strdata = BitConverter.ToString(data).TrimEnd('-', '0');

            WriteLog(Color.Purple, 0, "W: " + strdata + "\r\n");

            if (cy_stat == CY_RETURN_STATUS.CY_SUCCESS)

            {

                status = ERR_SUCCESS;

            }

            else

            {

                status = ERR_WRITE;

                CyI2cReset(cyDeviceHandle, 1);

            }

            return status;

        }

Transaction log for bootload attempt w/ these settings:

W: 01-38-00-00-C7-FF-17

R: 01-00-08-00-69-30-10-2E-00-3C-01-01-E2-FE-17

W: 01-33-01-00-00-CB-FF-17

R: 01-05-00-00-FA-FF-17-FF-FF

W: 01-32-01-00-00-CC-FF-17

R: 01-00-04-00-15-00-FF-00-E7-FE-17

W: 01-37-39-00-00-40-00-20-11-15-00-00-51-1E-00-00-51-1E-00-00-08-B5-00-F0-BD-FC-00-00-10-B5-05-4C-23-78-33-B9-04-4B-13-B1-04-48-AF-F3-00-80-01-23-23-70-10-BD-48-C1-FF-1F-00-00-00-00-88-74-F0-17

R: 01-00-00-00-FF-FF-17

W: 01-37-39-00-46-00-00-08-4B-10-B5-1B-B1-08-49-08-48-AF-F3-00-80-08-48-03-68-03-B9-10-BD-07-4B-00-2B-FB-D0-BD-E8-10-40-18-47-00-BF-00-00-00-00-4C-C1-FF-1F-88-46-00-00-C8-C0-FF-1F-00-00-64-ED-17

R: 01-00-00-00-FF-FF-17

W: 01-37-39-00-00-00-80-B5-9A-B0-62-B6-02-F0-AB-F9-02-F0-BF-F9-02-F0-F9-F8-02-F0-45-F9-02-21-00-20-01-F0-27-F9-00-F0-D9-FC-85-4C-00-F0-01-02-D3-B2-22-70-00-F0-1E-02-04-2A-0D-D0-02-D8-02-BA-E5-17

R: 01-00-00-00-FF-FF-17

W: 01-37-39-00-2A-05-D0-27-E0-08-2A-0E-D0-10-2A-13-D0-22-E0-00-22-62-70-FB-B1-7B-4A-13-E0-01-22-62-70-0B-B9-7A-4A-0E-E0-7A-4A-0C-E0-02-22-62-70-0B-B9-78-4A-07-E0-78-4A-05-E0-03-22-62-70-E6-EA-17

R: 01-00-00-00-FF-FF-17

W: 01-37-39-00-0B-B9-77-4A-00-E0-77-4A-13-78-03-F0-F1-03-43-F0-08-03-13-70-13-78-43-F0-01-03-13-70-01-45-00-40-01-4F-00-40-07-52-00-40-09-64-00-40-02-65-00-40-15-00-01-40-37-01-01-40-58-C7-F1-17

R: 01-00-00-00-FF-FF-17

W: 01-39-06-00-00-15-00-02-01-40-68-FF-17

R: FF-01-00-00-00-FF-FF

W: 01-3B-00-00-C4-FF-17

Program failed, status: 16385 (0x4001)

0 Likes

Hello,

Yes, the slave is stretching the clock.

Can you please let me know how you are accessing/selecting the registers for an I2C Read.

The CyI2CRead() function does not have a provision to select the register address from which the data should be read. So it has to be implemented using a combination of write and Read commands. 

If you are dynamically accessing the registers that you what to read from, then to follow the I2C read protocol you will need to do an I2C write (CyI2CWrite ) with the register address in the data field, this i2c write should have isStopBit  set to 0 indicating the slave that the transaction is not yet stopped. Then a CyI2CRead command should be sent to the slave to read the required  amount of data from it, please set the isNakBit and isStopBit to one . Here there will be a repeated start before the final stop bit.

When the master (USB Serial),  isNakBit is set to true in an I2C read transaction, the master will always NAK the data received from the slave after receiving the expected amount of data.

Please make sure that below protocol is been initiated by the I2C master during a Read transaction. 

pastedImage_2.png

Best Regards,

Yatheesh

0 Likes

Yatheesh,

The bootloader does not do I2C Write/Read in the traditional <Start><Addr(W)><Reg><Restart><Addr(R)><Reg><Stop> format.  They operate on discrete Write and Read packets with specific commands, like so:

Write Packet:

writepkt.JPG

Read Packet:

readpkt.JPG

Note the adherence to the structure laid out in the bootloader datasheet:

bootl_packets.JPG

What's curious is that on the transaction where the failure occurs and the clock is stretched, the PSoC returns a 0xFF before the 0x01 SoP byte and the 0x00 status code.  The PSoC has a successful status code 0x00, but is sneaking a 0xFF in the first outgoing byte rather than the 0x01, causing the host to terminate the process.

This is all being decided and handled by the bootl_utils library on the PC side and the Bootloader component on the PSoC5LP that I am loading.  The Cypress libraries are in control of assembling and sending/receiving the packets.

The PSoC is simply calling Bootloader_Start().  My application is calling CyBtldr_Program(), which is what uses my provided I2C_Read() and I2C_Write() functions as ReadData() and WriteData() as specified bootloader component documentation.

So the problem seems like the PSoC Bootloader firmware is having a problem, which is odd, considering I had no problem loading with the Bootloader Host included with PSoC Creator using the Miniprog3 as my USB-I2C Bridge.

This is also why I have another thread open trying to get the CY7C65211A properly working as a CDC device, so I can test it with the Bootloader Host in Creator:

CY7C65211A - Finding/Installing proper CDC Driver?

The CY7C65211A should be usable by the Bootloader Host tool included with PSoC Creator when is it in CDC-I2C mode:

AN60317: I2C Bootloader supported USB to I2C ports?

Still not sure if the problem is on the PSoC side or the host side, as there's evidence pointing to both.  Just trying to narrow it down

0 Likes

Hello,

For the current issue, can you please try reducing the I2C frequency and try the same, the slave device might not be getting enough time to process the requested data. We have not encountered such issues before for USB Serial device as I2C master.

Please make sure that the USB Serial device vendor interface is bound to the latest Cypress cyusb3 driver - version 1.2.3.20 from the FX3 SDK: https://www.cypress.com/documentation/software-and-drivers/ez-usb-fx3-software-development-kit

If you are using I2C under CDC, then you will have to use the cypress VCP library to communicate with the slave device.

Best Regards,

Yatheesh

0 Likes

Yatheesh,

I have installed the FX3 SDK, and updated the drivers.  Here is what is now being used in CDC mode:

drivers.JPG

And in Vendor I2C Mode:

driver (vendor).JPG

Do both of these look correct?

I will note that when set I2C CDC mode, the Bootloader Host in PSoC Creator recognizes the device, but as a UART Port rather than an I2C Port.

Attempting to load with the updated Vendor Device Driver still shows the same problem with the Write Flash Row command (slave stretches clock on address)

I don't believe it is a communications speed problem.  I am only running I2C @ 100kHz, the same speed in which I successfully programmed using a MiniProg3 in I2C Mode.

0 Likes

Hello,

Yes the drivers look fine.

Seems like the USB-Serial Device is not causing any issues in the application as the clock is stretched by the slave device and the  !2C master is not reporting any error and returns successfully in read operation.

Thanks,

Yatheesh

0 Likes

Yatheesh,

Good to know the drivers look OK, but I was under the impression that the 65211A in CDC I2C mode would be recognized in the PSoC Creator Bootloader Host as a I2C device rather than a UART?  Am I simply mistaken on this?  Because as of now it just shows up as a UART:

host_cdc.JPG

P.S. This thread is now verging into the same question and my other thread:

CY7C65211A - Finding/Installing proper CDC Driver?

Would we like to consolidate there instead of communicating across 2 threads?

I'm probably going to create a thread for the issue with the PSoC Bootloader Stretching the clock in the PSoC5LP forum.

0 Likes

Hello,

When the USB-Serial device is configured in I2C CDC mode, the corresponding interface will be bound to cypress CDC driver, the same which is used for UART CDC.

The Bootloader Host utility detects this as a UART device, as it is configured as a virtual COM port and comes up on the host PC as a CDC device with a COM interface and a Data interface.

The PID value assigned to the CY7C65211A part when configured in different modes may due to the configuration utility.

This is not a problem as the USB-Serial Configuration utility is detecting it as a 211A part, which is based on the silicon ID of the device.

Regards,

Yatheesh

0 Likes

So how do I use the 211A as a CDC USB-I2C bridge for the bootloader host rather than a UART interface?  Are you saying I need to use a different driver for the CDC interface?  A different VID/PID?  What driver is for the CDC USB-I2C interface?

The whole reason I picked this part in particular was because I was told I would be able to use it with the bootloader host as a USB-I2C bridge.

0 Likes

Hello,

The USB-Serial Device when programmed in I2C/SPI /UART CDC will always bind to the cypress CDC driver. Its the host application that is recognizing the device as a UART device.

Thanks,

Yatheesh

0 Likes

Yatheesh,

According to the answer in this thread:

AN60317: I2C Bootloader supported USB to I2C ports?

Bootloader host supports USB Communication Device Class (CDC). Thus you can select any USB-I2C bridge with CDC support.

Do you have any idea as to why the Bootloader Host in Creator would not recognize the port as I2C?

Should I perhaps make a separate thread for this?  I managed to sort out my comm issues when using the vendor driver in my custom host app.

See:

PSoC5LP I2C Bootloader: PSoC is stretching clock on "Write Flash" command?

Thanks again for the support

0 Likes

Hello,

Please create a thread in the PSOC community regarding the bootloader host application and the clock stretching.

Thanks,

Yatheesh

0 Likes