1 2 Previous Next 14 Replies Latest reply on Sep 16, 2013 10:55 AM by user_71310180

    How does I2C_Start() affect flash?

    user_71310180

      I have a piece of code that is continuously calculating a program CRC by scanning the PSoC4 program space. The initial CRC is calculated on the first POR. A 16-bit CRC is then stored in the last 2-bytes of the last row of the FLASH space and referenced for comparison. So, I scan from 0x0 to 0x00008000-sizeof(CRC). If the program memory ever changes during operation (i.e. the running CRC does not match the program CRC) the program is instructed to produce a fault code and discontinue normal operation. 

         

      I have been testing my project extensively. Everything works great. When I intentionally corrupt a random location in flash, as is typically done during verification and validation testing, the CRC checking catches the fault as expected. 

         

      Now here's the gotcha I'm hoping someone has an answer to. I have an I2C peripheral in the system, which is optionally enabled depending upon the device connected to a group of shared pins. During testing, I enable the I2C SCB by calling I2C_Start(). It is similarly disabled by calling I2C_Stop(). Within moments of calling I2C_Start() (and nothing else), the CRC checking process registers a change in the program memory and throws an error. I am surprised by this because the registers the processor and SCB blocks utilize are outside of my scanning area (0x40000000 – 0x4000FFFF and 0x40060000- -0x4006FFFF respectively).

         

      I can only conclude that something in flash is changing but can find very little in the TRM to suggest what that might be. This behavior is the same whether interrupts are enabled or not during I2C_Start(). 

         

      Does anyone know what in Flash is changing, where it is changing, or what other side effect starting I2C might have that ismaking the program think something is changing?

         

      Thanks.

        • 1. Re: How does I2C_Start() affect flash?
          ki.leung
                  1. If you don't start/enable the I2C, the CRC check is correct? 2. Can you set it up so that the i2C is enable/disable by an input pin. ie high to enable i2C and low to disable CRC run the program with pin high and low and see if that still fail. 3. If it only fail every time the pin is high. If it is possible, set and clear another output pin when ever you call the write to flash function call. Use a CRO to see if it was being called.   
          • 2. Re: How does I2C_Start() affect flash?
            ki.leung
                    I got the small text box again :-(   
            • 3. Re: How does I2C_Start() affect flash?
              user_14586677

              Curious, after the first CRC generate/store cycle, w/o starting I2C, you

                 

              do another CRC check that passes ? Thought is your scan ptr is one

                 

              byte off (or something like this) and picking up the change in flash due

                 

              to CRC write into last 2 rows of flash. The pointer of course would be

                 

              declared volatile if used in an ISR.

                 

               

                 

              Regards, Dana.

              • 4. Re: How does I2C_Start() affect flash?
                user_71310180

                 Here are a few more interesting clues. I tried making the CRC checking process atomic. That didn't fix anything. CRC still fails. The original idea behind the CRC check is that if the program CRC fails even once, it is forever failed. So this time I just allow that flag to be re-set to OK if the CRC passes in a subsequent run. That worked...but is only a bandaid to the problem. It does give some clues about where the problem lies.

                   

                So there are a couple other possibilities. The running CRC value could become corrupt, though it is a static variable declared within a function and inaccessable (in theory) to the outside world. The error flag could become corrupt, but that is also a static variable. Or the stack could become corrupt.

                   

                The evidence seems to point to the flag becoming corrupted. But I am not manipulating the stack in any way besides calling API functions. So something may be growing into it somehow. I tried growing the stack in CYDWR, but that didn't help either.

                   

                My next step is to look into the assembly and see where things are located. I will have to get back to you on that though.

                   

                In any case, the problem only occurs when I2C_Start() is called.

                • 5. Re: How does I2C_Start() affect flash?
                  user_14586677

                  Evidence as you point out sure seems to indicate ISR related.

                     

                   

                     

                  If you use a pointer for next byte access in CRC computation, thats

                     

                  what needs to be declared volatile to insure immunity from ISR

                     

                  related corruption.

                     

                   

                     

                  Regards, Dana.

                  • 6. Re: How does I2C_Start() affect flash?
                    junichi.hiraoka
                            If may, Does I2C_Start routine using same CRC generator hardware?   
                    • 7. Re: How does I2C_Start() affect flash?
                      ki.leung

                      1. You mentioned that you make the CRC check atomic, I assume you have all interrupt disabled during the CRC check process.

                         

                      2. If you just start but disable the i2C at start up only once, see if that makes any difference?

                      • 8. Re: How does I2C_Start() affect flash?
                        user_71310180

                         I appreciate all the thoughts. I will try answering some questions.

                           

                        1. If you don't start/enable the I2C, the CRC check is correct? 2. Can you set it up so that the i2C is enable/disable by an input pin. ie high to enable i2C and low to disable CRC run the program with pin high and low and see if that still fail. 3. If it only fail every time the pin is high. If it is possible, set and clear another output pin when ever you call the write to flash function call. Use a CRO to see if it was being called. 

                           

                        1. If I don't start the I2C peripheral, CRC checking always works. I've neve seen it fail unless I intentionally corrupt the program space for purposes of verification and validation. 

                           

                        2. I am unable to use another pin. The chip is in a system and I don't have easy access to pins. I can send commands to the chip to enable and disable I2C on the fly, which is where I see the problem.

                           

                        3. I'm not writing flash during this process. I only read the flash. The 16-bit program CRC is written only once during the life of the chip. During the very first power up of the chip, a complete system CRC is calculated. This value is stored at the end of the program flash and never written again. It is assumed that this value represents a valid program. Runtime CRC calculations simply compare a calculated result with that stored in flash.

                           

                         

                           

                        Curious, after the first CRC generate/store cycle, w/o starting I2C, you
                        do another CRC check that passes ? Thought is your scan ptr is one
                        byte off (or something like this) and picking up the change in flash due
                        to CRC write into last 2 rows of flash. The pointer of course would be
                        declared volatile if used in an ISR.

                           

                        Yes. Complete program CRCs are calculated repeatedly approximately every 2 seconds. They are always correct without starting I2C. The CRC function is not in an ISR. It is called from main during idle cycles. My program is a non-blocking super-loop.

                           

                        Simplified super loop execution looks like this:

                           

                        while(1)
                        {

                           

                        if regularly occuring event asserts
                        {

                           

                        take care of it

                           

                        }

                           

                        else // now in idle time

                           

                        {

                           

                        run incremental crc check

                           

                        }

                           

                        }

                           

                        I have tried halting interrupts while the "run incremental crc check" code executes by using "CyGlobalIntEnable" and "CyGlobalIntDisable" commands around it. That doesn't help.

                           

                         

                           

                        Evidence as you point out sure seems to indicate ISR related.

                        If you use a pointer for next byte access in CRC computation, thats
                        what needs to be declared volatile to insure immunity from ISR
                        related corruption.

                           

                        I have tried declaring the CRC variables as volatile (again, these are not within an ISR). It doesn't help.

                           

                        If may, Does I2C_Start routine using same CRC generator hardware?

                           

                        My CRC function is sofware and unrelated to I2C functionality.

                           

                        1. You mentioned that you make the CRC check atomic, I assume you have all interrupt disabled during the CRC check process.
                        2. If you just start but disable the i2C at start up only once, see if that makes any difference?

                           

                        1. Yes, as mentioned above, I have tried disabling interrupts during CRC computation. This, however, is unnecessary given how the program is written, assuming ISRs execute and return properly. The result was the same; CRC failed.

                           

                        2. How would you propose disableing the I2C? There is of course no I2C_Disable() function.

                        • 9. Re: How does I2C_Start() affect flash?
                          user_14586677

                          You might consider posting a case at -

                             

                           

                             

                              

                             

                                    

                             

                          www.cypress.com

                             

                          “Support”

                             

                          “Technical Support”

                             

                          “Create a Case”

                             

                           

                             

                          This should take care of disable -

                             

                           

                             

                           

                          • 10. Re: How does I2C_Start() affect flash?
                            user_78878863

                            Can you post the code for calculating the CRC?

                               

                            If have an idea I would need to verify:

                               
                                  
                            • according to the PSoC4 TRM the executable memory is from 0x00000000 up to 0x1fffffff
                            •     
                            • out of that range, 0x00000000 up to 0x00007fff is flash memory
                            •     
                            • but an "exception vector table" is located at 0x00000000
                                   
                                      
                              • it is used as interrupt table too (see TRM page 38)
                              •      
                            •     
                            • so it might be that starting the I2C component just sets a new interrupt vector, and therefore changes this location
                            •    
                               

                            So you can test this by just excluding that region. Or by checking whether the exception handlers 26 or 27 change - these are the ones for the SCB blocks. If you are advantageous, you can trace the call sequence for the I2C_Start() function down to what it really does, probably down to the assembler level...

                            • 11. Re: How does I2C_Start() affect flash?
                              user_71310180

                               That is exactly how I stop I2C. That's not the problem.

                                 

                              With regard to the vector table, I checked both locations and could not find any changes to those memory locations.

                              • 12. Re: How does I2C_Start() affect flash?
                                user_71310180

                                 Hi danaaknight and hli,

                                   

                                I think I missunderstood your comments. I tried what you suggested. I executed the following 

                                   


                                I2C_Start();
                                I2C_Stop();
                                CRC_Init(); // initialize program CRC if it hasn't been

                                   


                                And guess what? It works. I can start and stop the I2C peripheral after that and the system calculation CRC remains correct.

                                   


                                If you swap them:

                                   

                                CRC_Init(); // initialize program CRC if it hasn't been
                                I2C_Start();
                                I2C_Stop();

                                   

                                it fails. So, you both are on to something. I'm not sure what yet though. Perhaps a new interrupt vector was created, as suggested by hli. I'm just not seeing it during the debugging session with memory watch. I've tried skipping the first few bytes of program memory, but haven't had success yet.

                                • 13. Re: How does I2C_Start() affect flash?
                                  ki.leung

                                  Is the function  "CRC_Init()" perform the CRC calcution and write the value to the flash if it is the first time being called?

                                     

                                  if it is, how do you determine if it is the first time or not? Would that flag/byte used for checking corrupted so it didn't write the CRC and the next time it failed as the CRC value was not written

                                  • 14. Re: How does I2C_Start() affect flash?
                                    ki.leung

                                    I need an edit function.

                                       

                                     

                                       

                                    Press post too quickly

                                       

                                     

                                       

                                    You have a function to perforn the CRC calcution and write the value to the flash if it is the first time being called?

                                       

                                    if it is, how do you determine if it is the first time or not? Would that flag/byte used for checking corrupted so it didn't write the CRC and the next time it failed as the CRC value was not written

                                    1 2 Previous Next