cancel
Showing results for 
Search instead for 
Did you mean: 

PSoC 4 MCU

Contributor II

I’m looking for explanation or confirmation of a couple issues found while using CE222306 - PSoC 4 I2C Master

1) There appears to be an interrupt preventing the For loop in Main.c from proceeding beyond the I2C Write

- Moving the “Cycle through the LED Colors” section before the “Send packet with command to the slave” section allows the colors to cycle.

- Running the debugger, the code never goes past the command: if (TRANSFER_CMPLT == WriteCommandPacket(command)). Executing that command likely causes an interrupt that resets back to the beginning of Main.

- It appears the interrupt routines are drafted: mI2C_SCB_IRQ and mI2C_I2C_INT.c and cyapicallbacks.h. It would be helpful to have an ISR pre-set to let code proceed through the main loop. My work-around was to put the I2C Write command as the last command in the Main For loop.

Note: I’m guessing the I2C Read command may generate a similar interrupt. The project doesn’t allow code to progress past the I2C Write to get to that I2C Read, so it hasn’t been tested. Colors on the target I2C Slave kit change without the read.

2) The While Loops in the I2C Write and Read routines have no escape clause. The code can hang waiting for Master Complete.

- Recommend adding a timer or counter here.

I appreciate the examples Cypress has developed and the community as a repository for issues and concerns found that can help to improve those code examples.

Greg

0 Likes
Reply
1 Solution
Esteemed Contributor

Dear Greg-san,

I prepared exactly same hardware with you (except the protocol analyzer).

And I enjoyed the debugging for a couple of hours 😉

What I found is/are

(1) The "packet" of CE222306 and CE195362 are different!

CE222306: Packet is 5 bytes

byte[0] : data start position (0x01)

byte[1] : RED_COLOR

byte[2] : GREEN_COLOR

byte[3] : BLUE_COLOR

byte[4] : packet end (0x17)

CE195362: Packet is 4 bytes

byte[0] : Red LED control

byte[1] : Green LED control

byte[2] : Blue LED control

Byte[3] : Write counter (read only)

So sending 5 bytes from master always failed.

It was not because of the interrupt, but because of the protocol.

Meantime, I noticed that the position of colors were accepted OK,

so I assumed that for the EZI2C the first 4 bytes are valid.

So I modified the line of mI2C_I2CMasterWriteBuf()  in WriteCommandPacket() to

==============

    /* Start I2C write and check status */

    if(mI2C_I2C_MSTR_NO_ERROR == mI2C_I2CMasterWriteBuf(I2C_SLAVE_ADDR,

//                                                      buffer, BUFFER_SIZE,

                                                        buffer, 4,

                                                        mI2C_I2C_MODE_COMPLETE_XFER))

==============

(2) The slave does not seem to returning the packet, therefore ReadStatusPacket() always failed.

I commented out 3 lines related to this function.

So I changed the main() to

==============

int main()

{

    uint8 command = COLOR_RED;

  

    CyGlobalIntEnable;

  

    /* Start the I2C Master */

    mI2C_Start();

  

    rd_Buffer[RD_PACKET_SOP_POS] = PACKET_SOP;

    rd_Buffer[RD_PACKET_EOP_POS] = PACKET_EOP;

    for(;;)

    {

        /* Send packet with command to the slave */

        if (TRANSFER_CMPLT == WriteCommandPacket(command))

        {

            /* Read response packet from the slave */

//            if (TRANSFER_CMPLT == ReadStatusPacket())

//            {              

                /* Cycle through LED Colors */

                command++;

                if (command > COLOR_WHITE)

                {

                    command = COLOR_RED;

                }

//            }

        }

        /* Delay before changing LED color */

        CyDelay(500u);

    }

}

==============

Now my CY8CKIT-042 and CY8CKIT-044 seem to be communicating OK.

Attached are my "hacked" version of each samples.

Best Regards,

17-Oct-2019

Motoo Tanaka

View solution in original post

4 Replies
Esteemed Contributor

Hi,

You are talking about "I2C_Master_High_Level", right?

We also had many discussions about the behavior of I2C APIs.

And as far as I know of, it is recommended to use APIs with timeout function.

In the "I2C_Master_low_Level" sample, those functions with timeout are used.

> - It appears the interrupt routines are drafted: mI2C_SCB_IRQ and mI2C_I2C_INT.c and cyapicallbacks.h. It would be helpful to have an ISR pre-set to let code proceed through the main loop. My work-around was to put the I2C Write command as the last command in the Main For loop.

We can add user provided interrupts before calling    

CyGlobalIntEnable;

in main(), so in general, I hope that,  we don't have to deal with the default interrupts

when we want to have different interrupts.

Meantime,

> - Running the debugger, the code never goes past the command: if (TRANSFER_CMPLT == WriteCommandPacket(command)). Executing that command likely causes an interrupt that resets back to the beginning of Main.

Have you set up hardware as CE222306  suggested?

In my experience your symptom sounds familiar when I2C slave is not connected or no pull-up resistors are applied.

moto

0 Likes
Reply
Contributor II

Moto,

Thank you for the thoughts.

I will look at the I2C_Master_Low_Level to see how the timers are implemented. That's a great suggestion.

To clarify - I'm seeing the code jump back to the start of Main after every I2C Write with my kit setup. I have a customer who's seeing the code stuck in the while loop using a modified copy of the code. I haven't been able to replicate the "stuck in while loop" condition - though I've heard it can be an issue.

The author of another post has a similar "stuck in while loop" issue @ https://community.cypress.com/message/189916#189916

My setup:

- CY8CKIT-042 with CE222306 code example for I2C Master – all defaults

- CY8CKIT-044 with CE195362 code example for I2C Slave. I changed SCL from P4[0] to P6[0] and SDA from P4[1] to P6[1] to disconnect Kitprog from the I2C interface.

- I connected SCL, SDA and Ground between the two kits.

- The CY8CKIT-042 already has pullups on P4[0] and P4[1] so I didn’t add any.

- I plugged one of the two kits into a USB Charger while the other was plugged into the PC for programming and debugging.

- I used a Seleae logic analyzer with the I2C analyzer option to verify I2C traffic.

Greg

0 Likes
Reply
Esteemed Contributor

Dear Greg-san,

I prepared exactly same hardware with you (except the protocol analyzer).

And I enjoyed the debugging for a couple of hours 😉

What I found is/are

(1) The "packet" of CE222306 and CE195362 are different!

CE222306: Packet is 5 bytes

byte[0] : data start position (0x01)

byte[1] : RED_COLOR

byte[2] : GREEN_COLOR

byte[3] : BLUE_COLOR

byte[4] : packet end (0x17)

CE195362: Packet is 4 bytes

byte[0] : Red LED control

byte[1] : Green LED control

byte[2] : Blue LED control

Byte[3] : Write counter (read only)

So sending 5 bytes from master always failed.

It was not because of the interrupt, but because of the protocol.

Meantime, I noticed that the position of colors were accepted OK,

so I assumed that for the EZI2C the first 4 bytes are valid.

So I modified the line of mI2C_I2CMasterWriteBuf()  in WriteCommandPacket() to

==============

    /* Start I2C write and check status */

    if(mI2C_I2C_MSTR_NO_ERROR == mI2C_I2CMasterWriteBuf(I2C_SLAVE_ADDR,

//                                                      buffer, BUFFER_SIZE,

                                                        buffer, 4,

                                                        mI2C_I2C_MODE_COMPLETE_XFER))

==============

(2) The slave does not seem to returning the packet, therefore ReadStatusPacket() always failed.

I commented out 3 lines related to this function.

So I changed the main() to

==============

int main()

{

    uint8 command = COLOR_RED;

  

    CyGlobalIntEnable;

  

    /* Start the I2C Master */

    mI2C_Start();

  

    rd_Buffer[RD_PACKET_SOP_POS] = PACKET_SOP;

    rd_Buffer[RD_PACKET_EOP_POS] = PACKET_EOP;

    for(;;)

    {

        /* Send packet with command to the slave */

        if (TRANSFER_CMPLT == WriteCommandPacket(command))

        {

            /* Read response packet from the slave */

//            if (TRANSFER_CMPLT == ReadStatusPacket())

//            {              

                /* Cycle through LED Colors */

                command++;

                if (command > COLOR_WHITE)

                {

                    command = COLOR_RED;

                }

//            }

        }

        /* Delay before changing LED color */

        CyDelay(500u);

    }

}

==============

Now my CY8CKIT-042 and CY8CKIT-044 seem to be communicating OK.

Attached are my "hacked" version of each samples.

Best Regards,

17-Oct-2019

Motoo Tanaka

View solution in original post

Contributor II

Motoo-san,

Thank you for the ideas.

Per the comment:

So sending 5 bytes from master always failed.

It was not because of the interrupt, but because of the protocol.

I agree. The protocol error caused an interrupt. I was stuck trying to track the source of the interrupt with the debugger rather than stepping back and looking for errors in the system or code, that could cause interrupts.

Rather than shortening the Master write packet in the CE222306 code, I extended the Slave read packet in the CE195362 code to 6 (from 4) and adjusted the color indexes in the slave to match the Master: Red = 1; Green = 2; Blue = 3. I also moved the Count = 5 (from 3) and the corresponding Read_Only_Offset on the Slave side to 5.

Note: I had tried to change the Count and Read_Only_Offset to 4 in the Slave. The Read_Only_Offset is used to limit the ACKs. With the Read_Only_Offset at 4, the slave doesn’t send a fifth ACK. The Master isn’t setup to handle a NACK on the last byte and assumes the Tranfer fails. I.E. The command “if (TRANSFER_CMPLT == WriteCommandPacket(command))” doesn’t equate to true and thus the “if (TRANSFER_CMPLT_ReadStatusPacket())” doesn’t execute, nor does the, command variable increment and thus the colors on CY8CKIT-044 don’t cycle.

As you pointed out, the CE195362 code doesn’t look for Read requests, thus the ReadStatusPacket() function from the Master side fails. It shouldn’t be too hard to add code in the slave side to respond to the Read request and send the count. I did NOT add that code. Similar to your suggestion; I commented out the Read Request on the Master side to allow “command” to increment and the colors to cycle.

Thanks for your support.

Greg