CYASSERT in I2C ISR causing PSoC freeze

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

cross mob
Anonymous
Not applicable

Hi,

   

I made some general tests with I2C block transfer communication, and found that sometime the software became frozen (PSoC Creator 3.3 SP1 with I2C v3.50). After digging into details I realized, that I2C_INT.C defines the interrupt service routine (ISR), which contains few CYASSERT instructions, which are suspected to be responsible for the freeze (it is know that CYASSERT is compiled to 'halt' in 'Debug' compilation mode.) By using a PSoC 5LP development board give an easy possibility for detecting the CYASSERT case would happen, if a built in board LED is turned on in these cases. Furthermore as the development board has four LEDs, thus different LEDs can be used in the altogether 3 CYASSERT cases. The remaining 4th LED was just used an indication of I2C communication phase (turning on before I2C block transfer, and turning off after it).

   


After this making intensive test sometimes it was noticed, that the firmware halted, as one of the error LEDs and the 4th LED remained in turned on state. Indeed, quite an aggressive test was made, even the power from the I2C pullup resistors were removed for simulating faulty I2C devices, which easily caused the LEDs turning on.

   


But after all I do not know how to make "foolproof" I2C block transfer. I would like to have a solution, when anything "bad" happens on the I2C bus, the PSoC firmware detects it and it could continue its task. It is suspicious, that besides all of the CYASSERT cases there is a conditional compilation directive for handling a timeout, but I did not find a way to use the I2C "integrated" timer yet. The other possibility, if the original ISR is modified (that is at the moment what I am doing), and some recovery code is added to the error cases. And here I would add some indication in the returning status (I2C_state |= I2C_SM_MSTR_HALT|I2C_MSTAT_ERR_XFER;), which can be checked in the main loop.

   


What is the recommended way to implement a reliable I2C block transfer communication? How the "built in" timer can be used?

   

One more addition, that in the error cases maybe a non-blocking "I2C stop" must be added too, at least to bring out the I2C Master from undetermined state, and make it ready for the next operation, if the I2C bus becomes usable again.

   

Thanks,

   

Lajos

   

 

   

ps:

   

Here is the code part, which is derived from the generated I2C_INT.C (and of course further modified) I am referring to:

   


Original version:

   

                    #if(I2C_TIMEOUT_ENABLED)
                        /* Exit interrupt to take chance for timeout timer to handle this case */
                        I2C_DisableInt();
                        I2C_ClearPendingInt();
                    #else
                        /* Block execution flow: unexpected condition */
                        CYASSERT(0u != 0u);
                    #endif /* (I2C_TIMEOUT_ENABLED) */

   


LED supported debugging version:

   

                    #if(I2C_TIMEOUT_ENABLED)
                        /* Exit interrupt to take chance for timeout timer to handle this case */
                        I2C_DisableInt();
                        I2C_ClearPendingInt();
                    #else
                        /* Block execution flow: unexpected condition */
                        LED1(1);
                        CYASSERT(0u != 0u);
                    #endif /* (I2C_TIMEOUT_ENABLED) */

   


Improved version:

   

                    #if(I2C_TIMEOUT_ENABLED)
                        /* Exit interrupt to take chance for timeout timer to handle this case */
                        I2C_DisableInt();
                        I2C_ClearPendingInt();
                    #else
                        /* Block execution flow: unexpected condition */
                        LED1(1);
                        //CYASSERT(0u != 0u);
                        I2C_DisableInt();
                        I2C_ClearPendingInt();
                        I2C_state |= I2C_SM_MSTR_HALT|I2C_MSTAT_ERR_XFER;

   

                    #endif /* (I2C_TIMEOUT_ENABLED) */

   


I discovered, that I2C_TIMEOUT_ENABLED is defined in I2C.h, like this:

   

#define I2C_TIMEOUT_ENABLE             (0u)
...
#define I2C_TIMEOUT_ENABLED            (0u != I2C_TIMEOUT_ENABLE)

0 Likes
8 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

First: Never tamper in the generated files, they frequently get overwritten and nobody here in the forum can follow your request.

   

Second: Blame I2C. In the definition of I2C some points have been forgotten, for instance a timeout exit. Error codes and situations have been specified. When an implementation does not follow these rules, it is not I2C any more.

   

Workaround: Do not use I2C.

   

Or

   

Every I2C API call (except reading a byte) returns a status byte which you will have to check for non-zero indicating an error.

   

Or

   

Write your own communication component which handles everything as you want to.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Hi Bob,

   

I know, that the generated interrupt is not recommended to change. I did not do that. Instead, I copied the generated file into a "user defined" source code, added a new name of the new interrupt code and modified that one, and use that one after registration.

   

I mean this way:

   

void    I2CMaster_Start(uint8 use_std_isr)
{
    I2C_Start();
    if (use_std_isr)
        CyIntSetVector(I2C_ISR_NUMBER, &I2C_ISR);
    else
        CyIntSetVector(I2C_ISR_NUMBER, &I2C_MODIFIED_ISR);
}

   

And that is not a question: in our project we have I2C devices, so I need to use I2C. I was expecting, if I use the built in I2C module, I can handle my device correctly.

   

 

   

Furthermore when the I2C_MasterWriteBuf or I2C_MasterReadBuf is called, then the status is checked, and that is ok. The bad thing happens, when the real transfer is executed in the background by the ISR.

   

Br,

   

Lajos

   

 

   

Br,

   

Lajos

0 Likes
Anonymous
Not applicable

Bob,

   

the problem is not a non-compliant I2C slave but malfunction of a device, for instance caused by power failure.

   

When you want a robust embedded system your controller needs to react reasonable to all situations.

   

I high-level API that does not recover from all problems is problematic.

   

The error codes of the calls WriteBuffer, etc. cannot cover the situation that had not happened yet.

   

Andreas

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

I have got a small logic analyzer that is able to test for valid communication signals as UART, I2C and more. Price was quite less than $100.

   

This is quite useful for digital signal checking, for analog signals I use my good old oscillo.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Hi Bob,

   

 

   

It is nice you have good tools. I do not know why you mentioned it, and its price here. Or is your plan to test similar cases with that analyzer?

   

I underline again, that PSoC firmware freeze during the I2C communication can be detected with few LEDs, which are available on the PSoC 5LP development board. It has been done already. And ideally the API for I2C could handle all the error cases, including detecting hardware failures on the I2C bus. My understanding that the original ISR code was design carefully, as there are cases, where the possible error situations are detected, but not handled correctly, or handled as halting the processor core. I think it would be more usable to have the possibility to return an error code instead of the halt...

   

So let us put back the original request and find a robust way to use the I2C API.

   

Br,

   

Lajos

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Well, when you reject my soft plan to direct you into my assumed direction...

   
        
  • Millions of I2C applications show that it can made working
  •     
  • Probably some thousands of Cypress applications show the very same experience: running flawlessly
  •     
  • Your application does not run
  •    
   

That lets me think that the error might be with your implementation and not with the general way I2C works. Sorry.

   

So if I were you I would try to find out what it might be:

   

Electrical: Termination resistor values, speed, rise & fall times, noise, supply...

   

Protocol errors: shutting down a component before transmission ended ....

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Hi Bob,

   

I totally understand your arguments, that besides millions of running applications you believe the built in API is correct. For me this only means, that the probability of the occurrence of the PsoC freeze caused by I2C ISR must be small enough, but not obviously zero. And I am not surprised that this kind of errors remains in a system, as most of the cases, when someone runs into this, its reason is not easily identifiable, and the usual solution is to restart the system.

   

You may also be right, that if the I2C device works faultlessly, there is no hardware error in the environment, then these cases are handled correctly by the API. However in my tests I intentionally tested hardware failures too, as I was curious how the application handles it. So in this sense it has not really important to check the signal with an analyzer, as it is known those would be invalid.

   

I would emphasize, the CYASSERT of the I2C ISR are compiled to halt instruction, and in the test program the only place where the LED was turned on is just before the CYASSERT. In an extensive tests it was experienced that the firmware could be frozen, and each time the LED was turned on. It gave me evidence that the built in API is causing the freeze.

   

I would like to implement a robust application. Your suggestion is reasonable, if the application detects failure from a device, try to reinitialize it. However in the identified error cases the PsoC becomes frozen, so it does not have possibility to initiate the recovery process.

   

So I am still waiting for constructive suggestions.

   

Br,
Lajos

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

I suggest you to get in contact with Cypress directly. To do so: At top of this page select "Design Support -> Create a Support Case" and describe your problem. Cypress will get in contact with you.

   

 

   

Bob

0 Likes